mina2-2.0.7.orig/0000755000175000017500000000000012162575507013027 5ustar ebourgebourgmina2-2.0.7.orig/NOTICE.txt0000644000175000017500000000043712032276040014537 0ustar ebourgebourgApache MINA Copyright 2007-2012 The Apache Software Foundation. This product includes software developed at The Apache Software Foundation (http://www.apache.org/). Please refer to each LICENSE..txt file for the license terms of the components that Apache MINA depends on. mina2-2.0.7.orig/src/0000755000175000017500000000000012162575507013616 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-rfc1006/0000755000175000017500000000000012033616474015615 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-rfc1006/bin/0000755000175000017500000000000012033651315016356 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-http/0000755000175000017500000000000012162575507015517 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-http/pom.xml.releaseBackup0000644000175000017500000000344012033674301021567 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7-SNAPSHOT mina-http org.apache.mina 2.0.7-SNAPSHOT Apache MINA HTTP client and server codec bundle ${project.groupId}.http ${project.groupId} ${project.groupId} mina-core ${project.version} bundle mina2-2.0.7.orig/src/mina-http/pom.xml0000644000175000017500000000337012033674306017031 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7 mina-http org.apache.mina 2.0.7 Apache MINA HTTP client and server codec bundle ${project.groupId}.http ${project.groupId} ${project.groupId} mina-core ${project.version} bundle mina2-2.0.7.orig/src/mina-http/src/0000755000175000017500000000000012033672430016274 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-http/src/test/0000755000175000017500000000000012033672430017253 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-http/src/test/java/0000755000175000017500000000000012033672430020174 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-http/src/test/java/org/0000755000175000017500000000000012033672430020763 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-http/src/test/java/org/apache/0000755000175000017500000000000012033672430022204 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-http/src/test/java/org/apache/mina/0000755000175000017500000000000012033672430023130 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-http/src/test/java/org/apache/mina/http/0000755000175000017500000000000012162575507024121 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-http/src/test/java/org/apache/mina/http/HttpRequestImplTestCase.java0000644000175000017500000000562512033672430031530 0ustar ebourgebourgpackage org.apache.mina.http; import static org.junit.Assert.*; import java.util.List; import java.util.Map; import org.apache.mina.http.api.HttpMethod; import org.apache.mina.http.api.HttpRequest; import org.apache.mina.http.api.HttpVersion; import org.junit.Test; public class HttpRequestImplTestCase { @Test public void testGetParameterNoParameter() { HttpRequest req = new HttpRequestImpl(HttpVersion.HTTP_1_1, HttpMethod.GET, "/","", null); assertNull("p0 doesn't exist", req.getParameter("p0")); } @Test public void testGetParameterOneEmptyParameter() { HttpRequest req = new HttpRequestImpl(HttpVersion.HTTP_1_1, HttpMethod.GET, "/", "p0=", null); assertEquals("p0 is emtpy", "", req.getParameter("p0")); assertNull("p1 doesn't exist", req.getParameter("p1")); } @Test public void testGetParameterOneParameter() { HttpRequest req = new HttpRequestImpl(HttpVersion.HTTP_1_1, HttpMethod.GET, "/", "p0=0", null); assertEquals("p0 is '0'", "0", req.getParameter("p0")); assertNull("p1 doesn't exist", req.getParameter("p1")); } @Test public void testGetParameter3Parameters() { HttpRequest req = new HttpRequestImpl(HttpVersion.HTTP_1_1, HttpMethod.GET, "/", "p0=&p1=1&p2=2", null); assertEquals("p0 is emtpy", "", req.getParameter("p0")); assertEquals("p1 is '1'", "1", req.getParameter("p1")); assertEquals("p2 is '2'", "2", req.getParameter("p2")); assertNull("p3 doesn't exist", req.getParameter("p3")); } @Test public void testGetParametersNoParameter() { HttpRequest req = new HttpRequestImpl(HttpVersion.HTTP_1_1, HttpMethod.GET, "/", "", null); assertTrue("Empty Map", req.getParameters().isEmpty()); } @Test public void testGetParameters3Parameters() { HttpRequest req = new HttpRequestImpl(HttpVersion.HTTP_1_1, HttpMethod.GET, "/","p0=&p1=1&p2=2", null); Map> parameters = req.getParameters(); assertEquals("3 parameters", 3, parameters.size()); assertEquals("one p0", 1, parameters.get("p0").size()); assertEquals("p0 is emtpy", "", parameters.get("p0").get(0)); assertEquals("one p1", 1, parameters.get("p1").size()); assertEquals("p1 is '1'", "1", parameters.get("p1").get(0)); assertEquals("one p2", 1, parameters.get("p2").size()); assertEquals("p2 is '2'", "2", parameters.get("p2").get(0)); } @Test public void testGetParameters3ParametersWithDuplicate() { HttpRequest req = new HttpRequestImpl(HttpVersion.HTTP_1_1, HttpMethod.GET, "/","p0=&p1=1&p0=2", null); Map> parameters = req.getParameters(); assertEquals("2 parameters", 2, parameters.size()); assertEquals("two p0", 2, parameters.get("p0").size()); assertEquals("1st p0 is emtpy", "", parameters.get("p0").get(0)); assertEquals("2nd p0 is '2'", "2", parameters.get("p0").get(1)); assertEquals("one p1", 1, parameters.get("p1").size()); assertEquals("p1 is '1'", "1", parameters.get("p1").get(0)); assertNull("No p2", parameters.get("p2")); } } mina2-2.0.7.orig/src/mina-http/src/main/0000755000175000017500000000000012033672430017220 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-http/src/main/java/0000755000175000017500000000000012033672430020141 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-http/src/main/java/org/0000755000175000017500000000000012033672430020730 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/0000755000175000017500000000000012033672430022151 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/0000755000175000017500000000000012033672430023075 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/0000755000175000017500000000000012162575507024066 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/HttpClientCodec.java0000644000175000017500000000354112033672430027736 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolEncoder; public class HttpClientCodec extends ProtocolCodecFilter { /** Key for decoder current state */ private static final String DECODER_STATE_ATT = "http.ds"; /** Key for the partial HTTP requests head */ private static final String PARTIAL_HEAD_ATT = "http.ph"; private static ProtocolEncoder encoder = new HttpClientEncoder(); private static ProtocolDecoder decoder = new HttpClientDecoder(); public HttpClientCodec() { super(encoder, decoder); } @Override public void sessionClosed(IoFilter.NextFilter nextFilter, IoSession session) throws Exception { super.sessionClosed(nextFilter, session); session.removeAttribute(DECODER_STATE_ATT); session.removeAttribute(PARTIAL_HEAD_ATT); } }mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/HttpServerCodec.java0000644000175000017500000000354112033672430027766 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolEncoder; public class HttpServerCodec extends ProtocolCodecFilter { /** Key for decoder current state */ private static final String DECODER_STATE_ATT = "http.ds"; /** Key for the partial HTTP requests head */ private static final String PARTIAL_HEAD_ATT = "http.ph"; private static ProtocolEncoder encoder = new HttpServerEncoder(); private static ProtocolDecoder decoder = new HttpServerDecoder(); public HttpServerCodec() { super(encoder, decoder); } @Override public void sessionClosed(IoFilter.NextFilter nextFilter, IoSession session) throws Exception { super.sessionClosed(nextFilter, session); session.removeAttribute(DECODER_STATE_ATT); session.removeAttribute(PARTIAL_HEAD_ATT); } }mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/HttpClientDecoder.java0000644000175000017500000002176012033672430030271 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import org.apache.mina.http.api.DefaultHttpResponse; import org.apache.mina.http.api.HttpEndOfContent; import org.apache.mina.http.api.HttpStatus; import org.apache.mina.http.api.HttpVersion; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HttpClientDecoder implements ProtocolDecoder { private static final Logger LOG = LoggerFactory.getLogger(HttpClientCodec.class); /** Key for decoder current state */ private static final String DECODER_STATE_ATT = "http.ds"; /** Key for the partial HTTP requests head */ private static final String PARTIAL_HEAD_ATT = "http.ph"; /** Key for the number of bytes remaining to read for completing the body */ private static final String BODY_REMAINING_BYTES = "http.brb"; /** Key for indicating chunked data */ private static final String BODY_CHUNKED = "http.ckd"; /** Regex to parse HttpRequest Request Line */ public static final Pattern REQUEST_LINE_PATTERN = Pattern.compile(" "); /** Regex to parse HttpRequest Request Line */ public static final Pattern RESPONSE_LINE_PATTERN = Pattern.compile(" "); /** Regex to parse out QueryString from HttpRequest */ public static final Pattern QUERY_STRING_PATTERN = Pattern.compile("\\?"); /** Regex to parse out parameters from query string */ public static final Pattern PARAM_STRING_PATTERN = Pattern.compile("\\&|;"); /** Regex to parse out key/value pairs */ public static final Pattern KEY_VALUE_PATTERN = Pattern.compile("="); /** Regex to parse raw headers and body */ public static final Pattern RAW_VALUE_PATTERN = Pattern.compile("\\r\\n\\r\\n"); /** Regex to parse raw headers from body */ public static final Pattern HEADERS_BODY_PATTERN = Pattern.compile("\\r\\n"); /** Regex to parse header name and value */ public static final Pattern HEADER_VALUE_PATTERN = Pattern.compile(": "); /** Regex to split cookie header following RFC6265 Section 5.4 */ public static final Pattern COOKIE_SEPARATOR_PATTERN = Pattern.compile(";"); public void decode(final IoSession session, final IoBuffer msg, final ProtocolDecoderOutput out) { DecoderState state = (DecoderState)session.getAttribute(DECODER_STATE_ATT); if (null == state) { session.setAttribute(DECODER_STATE_ATT, DecoderState.NEW); state = (DecoderState)session.getAttribute(DECODER_STATE_ATT); } switch (state) { case HEAD: LOG.debug("decoding HEAD"); // grab the stored a partial HEAD request final ByteBuffer oldBuffer = (ByteBuffer)session.getAttribute(PARTIAL_HEAD_ATT); // concat the old buffer and the new incoming one IoBuffer.allocate(oldBuffer.remaining() + msg.remaining()).put(oldBuffer).put(msg).flip(); // now let's decode like it was a new message case NEW: LOG.debug("decoding NEW"); final DefaultHttpResponse rp = parseHttpReponseHead(msg.buf()); if (rp == null) { // we copy the incoming BB because it's going to be recycled by the inner IoProcessor for next reads final ByteBuffer partial = ByteBuffer.allocate(msg.remaining()); partial.put(msg.buf()); partial.flip(); // no request decoded, we accumulate session.setAttribute(PARTIAL_HEAD_ATT, partial); session.setAttribute(DECODER_STATE_ATT, DecoderState.HEAD); } else { out.write(rp); // is it a response with some body content ? LOG.debug("response with content"); session.setAttribute(DECODER_STATE_ATT, DecoderState.BODY); final String contentLen = rp.getHeader("content-length"); if (contentLen != null) { LOG.debug("found content len : {}", contentLen); session.setAttribute(BODY_REMAINING_BYTES, Integer.valueOf(contentLen)); } else if ("chunked".equalsIgnoreCase(rp.getHeader("transfer-encoding"))) { LOG.debug("no content len but chunked"); session.setAttribute(BODY_CHUNKED, Boolean.valueOf("true")); } else if ("close".equalsIgnoreCase(rp.getHeader("connection"))) { session.close(true); } else { throw new HttpException(HttpStatus.CLIENT_ERROR_LENGTH_REQUIRED, "no content length !"); } } break; case BODY: LOG.debug("decoding BODY: {} bytes", msg.remaining()); final int chunkSize = msg.remaining(); // send the chunk of body if (chunkSize != 0) { final IoBuffer wb = IoBuffer.allocate(msg.remaining()); wb.put(msg); wb.flip(); out.write(wb); } msg.position(msg.limit()); // do we have reach end of body ? int remaining = 0; // if chunked, remaining is the msg.remaining() if( session.getAttribute(BODY_CHUNKED) != null ) { remaining = chunkSize; } else { // otherwise, manage with content-length remaining = (Integer) session.getAttribute(BODY_REMAINING_BYTES); remaining -= chunkSize; } if (remaining <= 0 ) { LOG.debug("end of HTTP body"); session.setAttribute(DECODER_STATE_ATT, DecoderState.NEW); session.removeAttribute(BODY_REMAINING_BYTES); if( session.getAttribute(BODY_CHUNKED) != null ) { session.removeAttribute(BODY_CHUNKED); } out.write(new HttpEndOfContent()); } else { if( session.getAttribute(BODY_CHUNKED) == null ) { session.setAttribute(BODY_REMAINING_BYTES, Integer.valueOf(remaining)); } } break; default: throw new HttpException(HttpStatus.SERVER_ERROR_INTERNAL_SERVER_ERROR, "Unknonwn decoder state : " + state); } } public void finishDecode(final IoSession session, final ProtocolDecoderOutput out) throws Exception { } public void dispose(final IoSession session) throws Exception { } private DefaultHttpResponse parseHttpReponseHead(final ByteBuffer buffer) { // Java 6 >> String raw = new String(buffer.array(), 0, buffer.limit(), Charset.forName("UTF-8")); final String raw = new String(buffer.array(), 0, buffer.limit()); final String[] headersAndBody = RAW_VALUE_PATTERN.split(raw, -1); if (headersAndBody.length <= 1) { // we didn't receive the full HTTP head return null; } String[] headerFields = HEADERS_BODY_PATTERN.split(headersAndBody[0]); headerFields = ArrayUtil.dropFromEndWhile(headerFields, ""); final String requestLine = headerFields[0]; final Map generalHeaders = new HashMap(); for (int i = 1; i < headerFields.length; i++) { final String[] header = HEADER_VALUE_PATTERN.split(headerFields[i]); generalHeaders.put(header[0].toLowerCase(), header[1]); } final String[] elements = RESPONSE_LINE_PATTERN.split(requestLine); HttpStatus status = null; final int statusCode = Integer.valueOf(elements[1]); for (int i = 0; i < HttpStatus.values().length; i++) { status = HttpStatus.values()[i]; if (statusCode == status.code()) { break; } } final HttpVersion version = HttpVersion.fromString(elements[0]); // we put the buffer position where we found the beginning of the HTTP body buffer.position(headersAndBody[0].length() + 4); return new DefaultHttpResponse(version, status, generalHeaders); } } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/HttpServerEncoder.java0000644000175000017500000000574112033672430030334 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.util.Map; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolEncoder; import org.apache.mina.filter.codec.ProtocolEncoderOutput; import org.apache.mina.http.api.HttpEndOfContent; import org.apache.mina.http.api.HttpResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HttpServerEncoder implements ProtocolEncoder { private static final Logger LOG = LoggerFactory.getLogger(HttpServerCodec.class); private static final CharsetEncoder ENCODER = Charset.forName("UTF-8").newEncoder(); public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { LOG.debug("encode {}", message.getClass().getCanonicalName()); if (message instanceof HttpResponse) { LOG.debug("HttpResponse"); HttpResponse msg = (HttpResponse) message; StringBuilder sb = new StringBuilder(msg.getStatus().line()); for (Map.Entry header : msg.getHeaders().entrySet()) { sb.append(header.getKey()); sb.append(": "); sb.append(header.getValue()); sb.append("\r\n"); } sb.append("\r\n"); // Java 6 >> byte[] bytes = sb.toString().getBytes(Charset.forName("UTF-8")); // byte[] bytes = sb.toString().getBytes(); // out.write(ByteBuffer.wrap(bytes)); IoBuffer buf = IoBuffer.allocate(sb.length()).setAutoExpand(true); buf.putString(sb.toString(), ENCODER); buf.flip(); out.write(buf); } else if (message instanceof ByteBuffer) { LOG.debug("Body {}", message); out.write(message); } else if (message instanceof HttpEndOfContent) { LOG.debug("End of Content"); // end of HTTP content // keep alive ? } } public void dispose(IoSession session) throws Exception { // TODO Auto-generated method stub } } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/DateUtil.java0000644000175000017500000001004312033672430026430 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.TimeZone; import java.util.regex.Pattern; public class DateUtil { private final static Locale LOCALE = Locale.US; private final static TimeZone GMT_ZONE; private final static String RFC_1123_PATTERN = "EEE, dd MMM yyyy HH:mm:ss zzz"; private final static DateFormat RFC_1123_FORMAT; /** Pattern to find digits only. */ private final static Pattern DIGIT_PATTERN = Pattern.compile("^\\d+$"); static { RFC_1123_FORMAT = new SimpleDateFormat(DateUtil.RFC_1123_PATTERN, DateUtil.LOCALE); GMT_ZONE = TimeZone.getTimeZone("GMT"); DateUtil.RFC_1123_FORMAT.setTimeZone(DateUtil.GMT_ZONE); } public static String getCurrentAsString() { return DateUtil.RFC_1123_FORMAT.format(new Date()); //NOPMD } /** * Translate a given date String in the RFC 1123 * format to a long representing the number of milliseconds * since epoch. * * @param dateString a date String in the RFC 1123 * format. * @return the parsed Date in milliseconds. */ private static long parseDateStringToMilliseconds(final String dateString) { try { return DateUtil.RFC_1123_FORMAT.parse(dateString).getTime(); //NOPMD } catch (final ParseException e) { return 0; } } /** * Parse a given date String to a long * representation of the time. Where the provided value is all digits the * value is returned as a long, otherwise attempt is made to * parse the String as a RFC 1123 date. * * @param dateValue the value to parse. * @return the long value following parse, or zero where not * successful. */ public static long parseToMilliseconds(final String dateValue) { long ms = 0; if (DateUtil.DIGIT_PATTERN.matcher(dateValue).matches()) { ms = Long.parseLong(dateValue); } else { ms = parseDateStringToMilliseconds(dateValue); } return ms; } /** * Converts a millisecond representation of a date to a * RFC 1123 formatted String. * * @param dateValue the Date represented as milliseconds. * @return a String representation of the date. */ public static String parseToRFC1123(final long dateValue) { final Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(dateValue); return DateUtil.RFC_1123_FORMAT.format(calendar.getTime()); //NOPMD } /** * Convert a given Date object to a RFC 1123 * formatted String. * * @param date the Date object to convert * @return a String representation of the date. */ public static String getDateAsString(Date date) { return RFC_1123_FORMAT.format(date); //NOPMD } } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/api/0000755000175000017500000000000012162575507024637 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/api/HttpVerb.java0000644000175000017500000000166712033672430027240 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http.api; public enum HttpVerb { GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE, CONNECT } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/api/HttpEndOfContent.java0000644000175000017500000000173412033672430030663 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http.api; public class HttpEndOfContent { @Override public String toString() { return "HttpEndOfContent"; } } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/api/HttpRequest.java0000644000175000017500000000431612033672430027764 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http.api; import java.util.List; import java.util.Map; /** * An HTTP request * * @author jvermillar * */ public interface HttpRequest extends HttpMessage { /** * Determines whether this request contains at least one parameter with the specified name * * @param name The parameter name * @return true if this request contains at least one parameter with the specified name */ boolean containsParameter(String name); /** * Returns the value of a request parameter as a String, or null if the parameter does not exist. * * If the request contained multiple parameters with the same name, this method returns the first parameter * encountered in the request with the specified name * * @param name The parameter name * @return The value */ String getParameter(String name); String getQueryString(); /** * Returns a read only {@link Map} of query parameters whose key is a {@link String} and whose value is a * {@link List} of {@link String}s. */ Map> getParameters(); /** * Return the HTTP method used for this message {@link HttpMethod} * * @return the method */ HttpMethod getMethod(); /** * Retrurn the HTTP request path * @retrun the request path */ String getRequestPath(); } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/api/HttpMethod.java0000644000175000017500000000200212033672430027542 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http.api; /** * * @author The Apache MINA Project (dev@mina.apache.org) * */ public enum HttpMethod { GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE, CONNECT } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/api/HttpResponse.java0000644000175000017500000000232212033672430030125 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http.api; /** * An HTTP response to an HTTP request * * @author The Apache MINA Project (dev@mina.apache.org) * */ public interface HttpResponse extends HttpMessage { /** * The HTTP status code for the HTTP response (e.g. 200 for OK, 404 for not found, etc..) * * @return the status of the HTTP response */ public HttpStatus getStatus(); } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/api/HttpVersion.java0000644000175000017500000000347412033672430027765 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http.api; /** * Type safe enumeration representing HTTP protocol version * * @author The Apache MINA Project (dev@mina.apache.org) */ public enum HttpVersion { /** * HTTP 1/1 */ HTTP_1_1("HTTP/1.1"), /** * HTTP 1/0 */ HTTP_1_0("HTTP/1.0"); private final String value; private HttpVersion(String value) { this.value = value; } /** * Returns the {@link HttpVersion} instance from the specified string. * * @return The version, or null if no version is found */ public static HttpVersion fromString(String string) { if (HTTP_1_1.toString().equalsIgnoreCase(string)) { return HTTP_1_1; } if (HTTP_1_0.toString().equalsIgnoreCase(string)) { return HTTP_1_0; } return null; } /** * @return A String representation of this version */ @Override public String toString() { return value; } } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/api/HttpContentChunk.java0000644000175000017500000000174112033672430030736 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http.api; import java.nio.ByteBuffer; import java.util.List; public interface HttpContentChunk { List getContent(); } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/api/HttpStatus.java0000644000175000017500000001361512033672430027621 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http.api; /** * An Enumeration of all known HTTP status codes. */ public enum HttpStatus { /** * 200 - OK */ SUCCESS_OK(200, "HTTP/1.1 200 OK"), /** * 201 - Created */ SUCCESS_CREATED(201, "HTTP/1.1 201 Created"), /** * 202 - Accepted */ SUCCESS_ACCEPTED(202, "HTTP/1.1 202 Accepted"), /** * 203 - Non-Authoritative Information */ SUCCESS_NON_AUTHORATIVE_INFORMATION(203, "HTTP/1.1 203 Non-Authoritative Information"), /** * 204 - No Content */ SUCCESS_NO_CONTENT(204, "HTTP/1.1 204 No Content"), /** * 205 - Reset Content */ SUCCESS_RESET_CONTENT(205, "HTTP/1.1 205 Reset Content"), /** * 206 - Created */ SUCCESS_PARTIAL_CONTENT(206, "HTTP/1.1 206 Partial Content"), /** * 300 - Multiple Choices */ REDIRECTION_MULTIPLE_CHOICES(300, "HTTP/1.1 300 Multiple Choices"), /** * 301 - Moved Permanently */ REDIRECTION_MOVED_PERMANENTLY(301, "HTTP/1.1 301 Moved Permanently"), /** * 302 - Found / Moved Temporarily */ REDIRECTION_FOUND(302, "HTTP/1.1 302 Found"), /** * 303 - See Others */ REDIRECTION_SEE_OTHER(303, "HTTP/1.1 303 See Other"), /** * 304 - Not Modified */ REDIRECTION_NOT_MODIFIED(304, "HTTP/1.1 304 Not Modified"), /** * 305 - Use Proxy */ REDIRECTION_USE_PROXY(305, "HTTP/1.1 305 Use Proxy"), /** * 307 - Temporary Redirect */ REDIRECTION_TEMPORARILY_REDIRECT(307, "HTTP/1.1 307 Temporary Redirect"), /** * 400 - Bad Request */ CLIENT_ERROR_BAD_REQUEST(400, "HTTP/1.1 400 Bad Request"), /** * 401 - Unauthorized */ CLIENT_ERROR_UNAUTHORIZED(401, "HTTP/1.1 401 Unauthorized"), /** * 403 - Forbidden */ CLIENT_ERROR_FORBIDDEN(403, "HTTP/1.1 403 Forbidden"), /** * 404 - Not Found */ CLIENT_ERROR_NOT_FOUND(404, "HTTP/1.1 404 Not Found"), /** * 405 - Method Not Allowed */ CLIENT_ERROR_METHOD_NOT_ALLOWED(405, "HTTP/1.1 405 Method Not Allowed"), /** * 406 - Not Acceptable */ CLIENT_ERROR_NOT_ACCEPTABLE(406, "HTTP/1.1 406 Not Acceptable"), /** * 407 - Proxy Authentication Required */ CLIENT_ERROR_PROXY_AUTHENTICATION_REQUIRED(407, "HTTP/1.1 407 Proxy Authentication Required"), /** * 408 - Request Timeout */ CLIENT_ERROR_REQUEST_TIMEOUT(408, "HTTP/1.1 408 Request Timeout"), /** * 409 - Conflict */ CLIENT_ERROR_CONFLICT(409, "HTTP/1.1 409 Conflict"), /** * 410 - Gone */ CLIENT_ERROR_GONE(410, "HTTP/1.1 410 Gone"), /** * 411 - Length Required */ CLIENT_ERROR_LENGTH_REQUIRED(411, "HTTP/1.1 411 Length Required"), /** * 412 - Precondition Failed */ CLIENT_ERROR_PRECONDITION_FAILED(412, "HTTP/1.1 412 Precondition Failed"), /** * 413 - Request Entity Too Large */ CLIENT_ERROR_REQUEST_ENTITY_TOO_LARGE(413, "HTTP/1.1 413 Request Entity Too Large"), /** * 414 - Bad Request */ CLIENT_ERROR_REQUEST_URI_TOO_LONG(414, "HTTP/1.1 414 Request-URI Too Long"), /** * 415 - Unsupported Media Type */ CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE(415, "HTTP/1.1 415 Unsupported Media Type"), /** * 416 - Requested Range Not Satisfiable */ CLIENT_ERROR_REQUESTED_RANGE_NOT_SATISFIABLE(416, "HTTP/1.1 416 Requested Range Not Satisfiable"), /** * 417 - Expectation Failed */ CLIENT_ERROR_EXPECTATION_FAILED(417, "HTTP/1.1 417 Expectation Failed"), /** * 500 - Internal Server Error */ SERVER_ERROR_INTERNAL_SERVER_ERROR(500, "HTTP/1.1 500 Internal Server Error"), /** * 501 - Not Implemented */ SERVER_ERROR_NOT_IMPLEMENTED(501, "HTTP/1.1 501 Not Implemented"), /** * 502 - Bad Gateway */ SERVER_ERROR_BAD_GATEWAY(502, "HTTP/1.1 502 Bad Gateway"), /** * 503 - Service Unavailable */ SERVER_ERROR_SERVICE_UNAVAILABLE(503, "HTTP/1.1 503 Service Unavailable"), /** * 504 - Gateway Timeout */ SERVER_ERROR_GATEWAY_TIMEOUT(504, "HTTP/1.1 504 Gateway Timeout"), /** * 505 - HTTP Version Not Supported */ SERVER_ERROR_HTTP_VERSION_NOT_SUPPORTED(505, "HTTP/1.1 505 HTTP Version Not Supported"); /** The code associated with this status, for example "404" for "Not Found". */ private int code; /** * The line associated with this status, "HTTP/1.1 501 Not Implemented". */ private String line; /** * Create an instance of this type. * * @param code the status code. * @param phrase the associated phrase. */ private HttpStatus(int code, String phrase) { this.code = code; line = phrase; } /** * Retrieve the status code for this instance. * * @return the status code. */ public int code() { return code; } /** * Retrieve the status line for this instance. * * @return the status line. */ public String line() { return line + "\r\n"; } } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/api/DefaultHttpResponse.java0000644000175000017500000000433512033672430031440 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http.api; import java.util.Map; public class DefaultHttpResponse implements HttpResponse { private final HttpVersion version; private final HttpStatus status; private final Map headers; public DefaultHttpResponse(HttpVersion version, HttpStatus status, Map headers) { this.version = version; this.status = status; this.headers = headers; } public HttpVersion getProtocolVersion() { return version; } public String getContentType() { return headers.get("content-type"); } public boolean isKeepAlive() { // TODO check header and version for keep alive return false; } public String getHeader(String name) { return headers.get(name); } public boolean containsHeader(String name) { return headers.containsKey(name); } public Map getHeaders() { return headers; } public HttpStatus getStatus() { return status; } @Override public String toString() { String result = "HTTP RESPONSE STATUS: " + status + "\n"; result += "VERSION: " + version + "\n"; result += "--- HEADER --- \n"; for (String key : headers.keySet()) { String value = headers.get(key); result += key + ":" + value + "\n"; } return result; } } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/api/HttpMessage.java0000644000175000017500000000425712033672430027724 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http.api; import java.util.Map; /** * An HTTP message, the ancestor of HTTP request & response. * * @author The Apache MINA Project (dev@mina.apache.org) */ public interface HttpMessage { /** * The HTTP version of the message * * @return HTTP/1.0 or HTTP/1.1 */ public HttpVersion getProtocolVersion(); /** * Gets the Content-Type header of the message. * * @return The content type. */ public String getContentType(); /** * Returns true if this message enables keep-alive connection. */ public boolean isKeepAlive(); /** * Returns the value of the HTTP header with the specified name. If more than one header with the given name is * associated with this request, one is selected and returned. * * @param name The name of the desired header * @return The header value - or null if no header is found with the specified name */ public String getHeader(String name); /** * Returns true if the HTTP header with the specified name exists in this request. */ public boolean containsHeader(String name); /** * Returns a read-only {@link Map} of HTTP headers whose key is a {@link String} and whose value is a {@link String} * s. */ public Map getHeaders(); } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/HttpServerDecoder.java0000644000175000017500000002040112033672430030310 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import org.apache.mina.http.api.HttpEndOfContent; import org.apache.mina.http.api.HttpMethod; import org.apache.mina.http.api.HttpStatus; import org.apache.mina.http.api.HttpVersion; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HttpServerDecoder implements ProtocolDecoder { private static final Logger LOG = LoggerFactory.getLogger(HttpServerCodec.class); /** Key for decoder current state */ private static final String DECODER_STATE_ATT = "http.ds"; /** Key for the partial HTTP requests head */ private static final String PARTIAL_HEAD_ATT = "http.ph"; /** Key for the number of bytes remaining to read for completing the body */ private static final String BODY_REMAINING_BYTES = "http.brb"; /** Regex to parse HttpRequest Request Line */ public static final Pattern REQUEST_LINE_PATTERN = Pattern.compile(" "); /** Regex to parse out QueryString from HttpRequest */ public static final Pattern QUERY_STRING_PATTERN = Pattern.compile("\\?"); /** Regex to parse out parameters from query string */ public static final Pattern PARAM_STRING_PATTERN = Pattern.compile("\\&|;"); /** Regex to parse out key/value pairs */ public static final Pattern KEY_VALUE_PATTERN = Pattern.compile("="); /** Regex to parse raw headers and body */ public static final Pattern RAW_VALUE_PATTERN = Pattern.compile("\\r\\n\\r\\n"); /** Regex to parse raw headers from body */ public static final Pattern HEADERS_BODY_PATTERN = Pattern.compile("\\r\\n"); /** Regex to parse header name and value */ public static final Pattern HEADER_VALUE_PATTERN = Pattern.compile(": "); /** Regex to split cookie header following RFC6265 Section 5.4 */ public static final Pattern COOKIE_SEPARATOR_PATTERN = Pattern.compile(";"); public void decode(final IoSession session, final IoBuffer msg, final ProtocolDecoderOutput out) { DecoderState state = (DecoderState)session.getAttribute(DECODER_STATE_ATT); if (null == state) { session.setAttribute(DECODER_STATE_ATT, DecoderState.NEW); state = (DecoderState)session.getAttribute(DECODER_STATE_ATT); } switch (state) { case HEAD: LOG.debug("decoding HEAD"); // grab the stored a partial HEAD request final ByteBuffer oldBuffer = (ByteBuffer)session.getAttribute(PARTIAL_HEAD_ATT); // concat the old buffer and the new incoming one IoBuffer.allocate(oldBuffer.remaining() + msg.remaining()).put(oldBuffer).put(msg).flip(); // now let's decode like it was a new message case NEW: LOG.debug("decoding NEW"); final HttpRequestImpl rq = parseHttpRequestHead(msg.buf()); if (rq == null) { // we copy the incoming BB because it's going to be recycled by the inner IoProcessor for next reads final ByteBuffer partial = ByteBuffer.allocate(msg.remaining()); partial.put(msg.buf()); partial.flip(); // no request decoded, we accumulate session.setAttribute(PARTIAL_HEAD_ATT, partial); session.setAttribute(DECODER_STATE_ATT, DecoderState.HEAD); } else { out.write(rq); // is it a request with some body content ? if (rq.getMethod() == HttpMethod.POST || rq.getMethod() == HttpMethod.PUT) { LOG.debug("request with content"); session.setAttribute(DECODER_STATE_ATT, DecoderState.BODY); final String contentLen = rq.getHeader("content-length"); if (contentLen != null) { LOG.debug("found content len : {}", contentLen); session.setAttribute(BODY_REMAINING_BYTES, Integer.valueOf(contentLen)); } else { throw new HttpException(HttpStatus.CLIENT_ERROR_LENGTH_REQUIRED, "no content length !"); } } else { LOG.debug("request without content"); session.setAttribute(DECODER_STATE_ATT, DecoderState.NEW); out.write(new HttpEndOfContent()); } } break; case BODY: LOG.debug("decoding BODY: {} bytes", msg.remaining()); final int chunkSize = msg.remaining(); // send the chunk of body if (chunkSize != 0) { final IoBuffer wb = IoBuffer.allocate(msg.remaining()); wb.put(msg); wb.flip(); out.write(wb); } msg.position(msg.limit()); // do we have reach end of body ? int remaining = (Integer) session.getAttribute(BODY_REMAINING_BYTES); remaining -= chunkSize; if (remaining <= 0) { LOG.debug("end of HTTP body"); session.setAttribute(DECODER_STATE_ATT, DecoderState.NEW); session.removeAttribute(BODY_REMAINING_BYTES); out.write(new HttpEndOfContent()); } else { session.setAttribute(BODY_REMAINING_BYTES, Integer.valueOf(remaining)); } break; default: throw new HttpException(HttpStatus.CLIENT_ERROR_BAD_REQUEST, "Unknonwn decoder state : " + state); } } public void finishDecode(final IoSession session, final ProtocolDecoderOutput out) throws Exception { } public void dispose(final IoSession session) throws Exception { } private HttpRequestImpl parseHttpRequestHead(final ByteBuffer buffer) { // Java 6 >> String raw = new String(buffer.array(), 0, buffer.limit(), Charset.forName("UTF-8")); final String raw = new String(buffer.array(), 0, buffer.limit()); final String[] headersAndBody = RAW_VALUE_PATTERN.split(raw, -1); if (headersAndBody.length <= 1) { // we didn't receive the full HTTP head return null; } String[] headerFields = HEADERS_BODY_PATTERN.split(headersAndBody[0]); headerFields = ArrayUtil.dropFromEndWhile(headerFields, ""); final String requestLine = headerFields[0]; final Map generalHeaders = new HashMap(); for (int i = 1; i < headerFields.length; i++) { final String[] header = HEADER_VALUE_PATTERN.split(headerFields[i]); generalHeaders.put(header[0].toLowerCase(), header[1]); } final String[] elements = REQUEST_LINE_PATTERN.split(requestLine); final HttpMethod method = HttpMethod.valueOf(elements[0]); final HttpVersion version = HttpVersion.fromString(elements[2]); final String[] pathFrags = QUERY_STRING_PATTERN.split(elements[1]); final String requestedPath = pathFrags[0]; final String queryString = pathFrags.length == 2 ? pathFrags[1] : ""; // we put the buffer position where we found the beginning of the HTTP body buffer.position(headersAndBody[0].length() + 4); return new HttpRequestImpl(version, method, requestedPath, queryString, generalHeaders); } } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/ArrayUtil.java0000644000175000017500000000240512033672430026634 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http; public class ArrayUtil { public static String[] dropFromEndWhile(String[] array, String regex) { for (int i = array.length - 1; i >= 0; i--) { if (!array[i].trim().equals("")) { String[] trimmedArray = new String[i + 1]; System.arraycopy(array, 0, trimmedArray, 0, i + 1); return trimmedArray; } } return null; } } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/HttpException.java0000644000175000017500000000304512033672430027517 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http; import org.apache.mina.http.api.HttpStatus; @SuppressWarnings("serial") public class HttpException extends RuntimeException { private final int statusCode; public HttpException(final int statusCode) { this(statusCode, ""); } public HttpException(final HttpStatus statusCode) { this(statusCode, ""); } public HttpException(final int statusCode, final String message) { super(message); this.statusCode = statusCode; } public HttpException(final HttpStatus statusCode, final String message) { super(message); this.statusCode = statusCode.code(); } public int getStatusCode() { return statusCode; } } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/HttpRequestImpl.java0000644000175000017500000001044112033672430030031 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.mina.http.api.HttpMethod; import org.apache.mina.http.api.HttpRequest; import org.apache.mina.http.api.HttpVersion; public class HttpRequestImpl implements HttpRequest { private final HttpVersion version; private final HttpMethod method; private final String requestedPath; private final String queryString; private final Map headers; public HttpRequestImpl(HttpVersion version, HttpMethod method, String requestedPath, String queryString, Map headers) { this.version = version; this.method = method; this.requestedPath = requestedPath; this.queryString = queryString; this.headers = headers;//Collections.unmodifiableMap(headers); } public HttpVersion getProtocolVersion() { return version; } public String getContentType() { return headers.get("content-type"); } public boolean isKeepAlive() { // TODO Auto-generated method stub return false; } public String getHeader(String name) { return headers.get(name); } public boolean containsHeader(String name) { return headers.containsKey(name); } public Map getHeaders() { return headers; } public boolean containsParameter(String name) { Matcher m = parameterPattern(name); return m.find(); } public String getParameter(String name) { Matcher m = parameterPattern(name); if (m.find()) { return m.group(1); } else { return null; } } protected Matcher parameterPattern(String name) { return Pattern.compile("[&]"+name+"=([^&]*)").matcher("&"+queryString); } public Map> getParameters() { Map> parameters = new HashMap>(); String[] params = queryString.split("&"); if (params.length == 1) { return parameters; } for (int i = 0; i < params.length; i++) { String[] param = params[i].split("="); String name = param[0]; String value = param.length == 2 ? param[1] : ""; if (!parameters.containsKey(name)) { parameters.put(name, new ArrayList()); } parameters.get(name).add(value); } return parameters; } public String getQueryString() { return queryString; } public HttpMethod getMethod() { return method; } public String getRequestPath() { return requestedPath; } public String toString() { String result = "HTTP REQUEST METHOD: " + method + "\n"; result += "VERSION: " + version + "\n"; result += "PATH: " + requestedPath + "\n"; result += "QUERY:" + queryString + "\n"; result += "--- HEADER --- \n"; for (String key : headers.keySet()) { String value = headers.get(key); result += key + ":" + value + "\n"; } result += "--- PARAMETERS --- \n"; Map> parameters = getParameters(); for (String key : parameters.keySet()) { Collection values = parameters.get(key); for (String value : values) { result += key + ":" + value + "\n"; } } return result; } } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/HttpClientEncoder.java0000644000175000017500000000450412033672430030300 0ustar ebourgebourgpackage org.apache.mina.http; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.util.Map; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolEncoder; import org.apache.mina.filter.codec.ProtocolEncoderOutput; import org.apache.mina.http.api.HttpEndOfContent; import org.apache.mina.http.api.HttpRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HttpClientEncoder implements ProtocolEncoder { private static final Logger LOG = LoggerFactory.getLogger(HttpClientCodec.class); private static final CharsetEncoder ENCODER = Charset.forName("UTF-8").newEncoder(); public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { LOG.debug("encode {}", message.getClass().getCanonicalName()); if (message instanceof HttpRequest) { LOG.debug("HttpRequest"); HttpRequest msg = (HttpRequest)message; StringBuilder sb = new StringBuilder(msg.getMethod().toString()); sb.append(" "); sb.append(msg.getRequestPath()); if (!"".equals(msg.getQueryString())) { sb.append("?"); sb.append(msg.getQueryString()); } sb.append(" "); sb.append(msg.getProtocolVersion()); sb.append("\r\n"); for (Map.Entry header : msg.getHeaders().entrySet()) { sb.append(header.getKey()); sb.append(": "); sb.append(header.getValue()); sb.append("\r\n"); } sb.append("\r\n"); // Java 6 >> byte[] bytes = sb.toString().getBytes(Charset.forName("UTF-8")); // byte[] bytes = sb.toString().getBytes(); // out.write(ByteBuffer.wrap(bytes)); IoBuffer buf = IoBuffer.allocate(sb.length()).setAutoExpand(true); buf.putString(sb.toString(), ENCODER); buf.flip(); out.write(buf); } else if (message instanceof ByteBuffer) { LOG.debug("Body"); out.write(message); } else if (message instanceof HttpEndOfContent) { LOG.debug("End of Content"); // end of HTTP content // keep alive ? } } public void dispose(IoSession arg0) throws Exception { // TODO Auto-generated method stub } } mina2-2.0.7.orig/src/mina-http/src/main/java/org/apache/mina/http/DecoderState.java0000644000175000017500000000211612033672430027265 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.http; public enum DecoderState { NEW, // waiting for a new HTTP requests, the session is new of last request was completed HEAD, // accumulating the HTTP request head (everything before the body) BODY // receiving HTTP body slices } mina2-2.0.7.orig/src/mina-filter-compression/0000755000175000017500000000000012162575507020364 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-filter-compression/pom.xml.releaseBackup0000644000175000017500000000371112033674301024435 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7-SNAPSHOT mina-filter-compression Apache MINA Compression Filter bundle ${project.groupId}.filter.compression ${project.groupId}.filter.compression ${project.groupId} mina-core ${project.version} bundle com.jcraft jzlib org.easymock easymock mina2-2.0.7.orig/src/mina-filter-compression/pom.xml0000644000175000017500000000370012033674306021673 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7 mina-filter-compression Apache MINA Compression Filter bundle ${project.groupId}.filter.compression ${project.groupId}.filter.compression ${project.groupId} mina-core ${project.version} bundle com.jcraft jzlib org.easymock easymock mina2-2.0.7.orig/src/mina-filter-compression/src/0000755000175000017500000000000012032276014021136 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-filter-compression/src/test/0000755000175000017500000000000012032276014022115 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-filter-compression/src/test/java/0000755000175000017500000000000012032276014023036 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-filter-compression/src/test/java/org/0000755000175000017500000000000012032276014023625 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-filter-compression/src/test/java/org/apache/0000755000175000017500000000000012032276014025046 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-filter-compression/src/test/java/org/apache/mina/0000755000175000017500000000000012032276014025772 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-filter-compression/src/test/java/org/apache/mina/filter/0000755000175000017500000000000012032276014027257 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-filter-compression/src/test/java/org/apache/mina/filter/compression/0000755000175000017500000000000012162575507031635 5ustar ebourgebourg././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-filter-compression/src/test/java/org/apache/mina/filter/compression/ZlibTest.javamina2-2.0.7.orig/src/mina-filter-compression/src/test/java/org/apache/mina/filter/compression/ZlibTe0000644000175000017500000001125712032276014032742 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.compression; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.nio.charset.Charset; import org.apache.mina.core.buffer.IoBuffer; import org.junit.Before; import org.junit.Test; /** * @author Apache MINA Project */ public class ZlibTest { private Zlib deflater = null; private Zlib inflater = null; @Before public void setUp() throws Exception { deflater = new Zlib(Zlib.COMPRESSION_MAX, Zlib.MODE_DEFLATER); inflater = new Zlib(Zlib.COMPRESSION_MAX, Zlib.MODE_INFLATER); } @Test public void testCompression() throws Exception { String strInput = ""; // increase the count to as many as required to generate a long // string for input for (int i = 0; i < 10; i++) { strInput += "The quick brown fox jumps over the lazy dog. "; } IoBuffer byteInput = IoBuffer.wrap(strInput.getBytes("UTF8")); // increase the count to have the compression and decompression // done using the same instance of Zlib for (int i = 0; i < 5; i++) { IoBuffer byteCompressed = deflater.deflate(byteInput); IoBuffer byteUncompressed = inflater.inflate(byteCompressed); String strOutput = byteUncompressed.getString(Charset.forName("UTF8").newDecoder()); assertTrue(strOutput.equals(strInput)); } } @Test public void testCorruptedData() throws Exception { String strInput = "Hello World"; IoBuffer byteInput = IoBuffer.wrap(strInput.getBytes("UTF8")); IoBuffer byteCompressed = deflater.deflate(byteInput); // change the contents to something else. Since this doesn't check // for integrity, it wont throw an exception byteCompressed.put(5, (byte) 0xa); IoBuffer byteUncompressed = inflater.inflate(byteCompressed); String strOutput = byteUncompressed.getString(Charset.forName("UTF8").newDecoder()); assertFalse(strOutput.equals(strInput)); } @Test public void testCorruptedHeader() throws Exception { String strInput = "Hello World"; IoBuffer byteInput = IoBuffer.wrap(strInput.getBytes("UTF8")); IoBuffer byteCompressed = deflater.deflate(byteInput); // write a bad value into the zlib header. Make sure that // the decompression fails byteCompressed.put(0, (byte) 0xca); try { inflater.inflate(byteCompressed); } catch (IOException e) { assertTrue(true); return; } assertTrue(false); } @Test public void testFragments() throws Exception { String strInput = ""; for (int i = 0; i < 10; i++) { strInput += "The quick brown fox jumps over the lazy dog. "; } IoBuffer byteInput = IoBuffer.wrap(strInput.getBytes("UTF8")); IoBuffer byteCompressed = null; for (int i = 0; i < 5; i++) { byteCompressed = deflater.deflate(byteInput); if (i == 0) { // decompress the first compressed output since it contains // the zlib header, which will not be generated for further // compressions done with the same instance IoBuffer byteUncompressed = inflater.inflate(byteCompressed); String strOutput = byteUncompressed.getString(Charset.forName("UTF8").newDecoder()); assertTrue(strOutput.equals(strInput)); } } // check if the last compressed data block can be decompressed // successfully. IoBuffer byteUncompressed = inflater.inflate(byteCompressed); String strOutput = byteUncompressed.getString(Charset.forName("UTF8").newDecoder()); assertTrue(strOutput.equals(strInput)); } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-filter-compression/src/test/java/org/apache/mina/filter/compression/CompressionFilterTest.javamina2-2.0.7.orig/src/mina-filter-compression/src/test/java/org/apache/mina/filter/compression/Compre0000644000175000017500000002024512032276014032773 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.compression; import static org.junit.Assert.assertTrue; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.DefaultWriteRequest; import org.apache.mina.core.write.WriteRequest; import org.easymock.AbstractMatcher; import org.easymock.MockControl; import org.junit.Before; import org.junit.Test; /** * @author Apache MINA Project */ public class CompressionFilterTest { private MockControl mockSession; private MockControl mockNextFilter; private MockControl mockIoFilterChain; private IoSession session; private NextFilter nextFilter; private IoFilterChain ioFilterChain; private CompressionFilter filter; private Zlib deflater; private Zlib inflater; private Zlib actualDeflater; private Zlib actualInflater; // the sample data to be used for testing String strCompress = "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. " + "The quick brown fox jumps over the lazy dog. "; @Before public void setUp() { // create the necessary mock controls. mockSession = MockControl.createControl(IoSession.class); mockNextFilter = MockControl.createControl(NextFilter.class); mockIoFilterChain = MockControl.createControl(IoFilterChain.class); // set the default matcher mockNextFilter.setDefaultMatcher(new DataMatcher()); session = (IoSession) mockSession.getMock(); nextFilter = (NextFilter) mockNextFilter.getMock(); ioFilterChain = (IoFilterChain) mockIoFilterChain.getMock(); // create an instance of the filter filter = new CompressionFilter(CompressionFilter.COMPRESSION_MAX); // deflater and inflater that will be used by the filter deflater = new Zlib(Zlib.COMPRESSION_MAX, Zlib.MODE_DEFLATER); inflater = new Zlib(Zlib.COMPRESSION_MAX, Zlib.MODE_INFLATER); // create instances of the deflater and inflater to help test the output actualDeflater = new Zlib(Zlib.COMPRESSION_MAX, Zlib.MODE_DEFLATER); actualInflater = new Zlib(Zlib.COMPRESSION_MAX, Zlib.MODE_INFLATER); } @Test public void testCompression() throws Exception { // prepare the input data IoBuffer buf = IoBuffer.wrap(strCompress.getBytes("UTF8")); IoBuffer actualOutput = actualDeflater.deflate(buf); WriteRequest writeRequest = new DefaultWriteRequest(buf); // record all the mock calls ioFilterChain.contains(CompressionFilter.class); mockIoFilterChain.setReturnValue(false); ioFilterChain.getSession(); mockIoFilterChain.setReturnValue(session); session.setAttribute(CompressionFilter.class.getName() + ".Deflater", deflater); mockSession.setDefaultMatcher(new DataMatcher()); mockSession.setReturnValue(null, MockControl.ONE); session.setAttribute(CompressionFilter.class.getName() + ".Inflater", inflater); mockSession.setReturnValue(null, MockControl.ONE); session.containsAttribute(CompressionFilter.DISABLE_COMPRESSION_ONCE); mockSession.setReturnValue(false); session.getAttribute(CompressionFilter.class.getName() + ".Deflater"); mockSession.setReturnValue(deflater); nextFilter.filterWrite(session, new DefaultWriteRequest(actualOutput)); // switch to playback mode mockSession.replay(); mockIoFilterChain.replay(); mockNextFilter.replay(); // make the actual calls on the filter filter.onPreAdd(ioFilterChain, "CompressionFilter", nextFilter); filter.filterWrite(nextFilter, session, writeRequest); // verify that all the calls happened as recorded mockNextFilter.verify(); assertTrue(true); } @Test public void testDecompression() throws Exception { // prepare the input data IoBuffer buf = IoBuffer.wrap(strCompress.getBytes("UTF8")); IoBuffer byteInput = actualDeflater.deflate(buf); IoBuffer actualOutput = actualInflater.inflate(byteInput); // record all the mock calls ioFilterChain.contains(CompressionFilter.class); mockIoFilterChain.setReturnValue(false); ioFilterChain.getSession(); mockIoFilterChain.setReturnValue(session); session.setAttribute(CompressionFilter.class.getName() + ".Deflater", deflater); mockSession.setDefaultMatcher(new DataMatcher()); mockSession.setReturnValue(null, MockControl.ONE); session.setAttribute(CompressionFilter.class.getName() + ".Inflater", inflater); mockSession.setReturnValue(null, MockControl.ONE); session.getAttribute(CompressionFilter.class.getName() + ".Inflater"); mockSession.setReturnValue(inflater); nextFilter.messageReceived(session, actualOutput); // switch to playback mode mockSession.replay(); mockIoFilterChain.replay(); mockNextFilter.replay(); // make the actual calls on the filter filter.onPreAdd(ioFilterChain, "CompressionFilter", nextFilter); filter.messageReceived(nextFilter, session, byteInput); // verify that all the calls happened as recorded mockNextFilter.verify(); assertTrue(true); } /** * A matcher used to check if the actual and expected outputs matched */ class DataMatcher extends AbstractMatcher { @Override protected boolean argumentMatches(Object arg0, Object arg1) { // we need to only verify the ByteBuffer output if (arg0 instanceof WriteRequest) { WriteRequest expected = (WriteRequest) arg0; WriteRequest actual = (WriteRequest) arg1; IoBuffer bExpected = (IoBuffer) expected.getMessage(); IoBuffer bActual = (IoBuffer) actual.getMessage(); return bExpected.equals(bActual); } return true; } } } mina2-2.0.7.orig/src/mina-filter-compression/src/main/0000755000175000017500000000000012032276014022062 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-filter-compression/src/main/java/0000755000175000017500000000000012032276014023003 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-filter-compression/src/main/java/org/0000755000175000017500000000000012032276014023572 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-filter-compression/src/main/java/org/apache/0000755000175000017500000000000012032276014025013 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-filter-compression/src/main/java/org/apache/mina/0000755000175000017500000000000012032276014025737 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-filter-compression/src/main/java/org/apache/mina/filter/0000755000175000017500000000000012032276014027224 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-filter-compression/src/main/java/org/apache/mina/filter/compression/0000755000175000017500000000000012162575507031602 5ustar ebourgebourg././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-filter-compression/src/main/java/org/apache/mina/filter/compression/Zlib.javamina2-2.0.7.orig/src/mina-filter-compression/src/main/java/org/apache/mina/filter/compression/Zlib.j0000644000175000017500000001742512032276014032651 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.compression; import java.io.IOException; import org.apache.mina.core.buffer.IoBuffer; import com.jcraft.jzlib.JZlib; import com.jcraft.jzlib.ZStream; /** * A helper class for interfacing with the JZlib library. This class acts both * as a compressor and decompressor, but only as one at a time. The only * flush method supported is Z_SYNC_FLUSH also known as Z_PARTIAL_FLUSH * * @author Apache MINA Project */ class Zlib { /** Try o get the best possible compression */ public static final int COMPRESSION_MAX = JZlib.Z_BEST_COMPRESSION; /** Favor speed over compression ratio */ public static final int COMPRESSION_MIN = JZlib.Z_BEST_SPEED; /** No compression */ public static final int COMPRESSION_NONE = JZlib.Z_NO_COMPRESSION; /** Default compression */ public static final int COMPRESSION_DEFAULT = JZlib.Z_DEFAULT_COMPRESSION; /** Compression mode */ public static final int MODE_DEFLATER = 1; /** Uncompress mode */ public static final int MODE_INFLATER = 2; /** The requested compression level */ private int compressionLevel; /** The inner stream used to inflate or deflate the data */ private ZStream zStream = null; /** The selected operation mode : INFLATE or DEFLATE */ private int mode = -1; /** * Creates an instance of the ZLib class. * * @param compressionLevel the level of compression that should be used. One of * COMPRESSION_MAX, COMPRESSION_MIN, * COMPRESSION_NONE or COMPRESSION_DEFAULT * @param mode the mode in which the instance will operate. Can be either * of MODE_DEFLATER or MODE_INFLATER * @throws IllegalArgumentException if the mode is incorrect */ public Zlib(int compressionLevel, int mode) { switch (compressionLevel) { case COMPRESSION_MAX: case COMPRESSION_MIN: case COMPRESSION_NONE: case COMPRESSION_DEFAULT: this.compressionLevel = compressionLevel; break; default: throw new IllegalArgumentException("invalid compression level specified"); } // create a new instance of ZStream. This will be done only once. zStream = new ZStream(); switch (mode) { case MODE_DEFLATER: zStream.deflateInit(this.compressionLevel); break; case MODE_INFLATER: zStream.inflateInit(); break; default: throw new IllegalArgumentException("invalid mode specified"); } this.mode = mode; } /** * Uncompress the given buffer, returning it in a new buffer. * * @param inBuffer the {@link IoBuffer} to be decompressed. The contents * of the buffer are transferred into a local byte array and the buffer is * flipped and returned intact. * @return the decompressed data * @throws IOException if the decompression of the data failed for some reason. * @throws IllegalArgumentException if the mode is not MODE_DEFLATER */ public IoBuffer inflate(IoBuffer inBuffer) throws IOException { if (mode == MODE_DEFLATER) { throw new IllegalStateException("not initialized as INFLATER"); } byte[] inBytes = new byte[inBuffer.remaining()]; inBuffer.get(inBytes).flip(); // We could probably do this better, if we're willing to return multiple buffers // (e.g. with a callback function) byte[] outBytes = new byte[inBytes.length * 2]; IoBuffer outBuffer = IoBuffer.allocate(outBytes.length); outBuffer.setAutoExpand(true); synchronized (zStream) { zStream.next_in = inBytes; zStream.next_in_index = 0; zStream.avail_in = inBytes.length; zStream.next_out = outBytes; zStream.next_out_index = 0; zStream.avail_out = outBytes.length; int retval = 0; do { retval = zStream.inflate(JZlib.Z_SYNC_FLUSH); switch (retval) { case JZlib.Z_OK: // completed decompression, lets copy data and get out case JZlib.Z_BUF_ERROR: // need more space for output. store current output and get more outBuffer.put(outBytes, 0, zStream.next_out_index); zStream.next_out_index = 0; zStream.avail_out = outBytes.length; break; default: // unknown error outBuffer = null; if (zStream.msg == null) { throw new IOException("Unknown error. Error code : " + retval); } else { throw new IOException("Unknown error. Error code : " + retval + " and message : " + zStream.msg); } } } while (zStream.avail_in > 0); } return outBuffer.flip(); } /** * Compress the input. The result will be put in a new buffer. * * @param inBuffer the buffer to be compressed. The contents are transferred * into a local byte array and the buffer is flipped and returned intact. * @return the buffer with the compressed data * @throws IOException if the compression of teh buffer failed for some reason * @throws IllegalStateException if the mode is not MODE_DEFLATER */ public IoBuffer deflate(IoBuffer inBuffer) throws IOException { if (mode == MODE_INFLATER) { throw new IllegalStateException("not initialized as DEFLATER"); } byte[] inBytes = new byte[inBuffer.remaining()]; inBuffer.get(inBytes).flip(); // according to spec, destination buffer should be 0.1% larger // than source length plus 12 bytes. We add a single byte to safeguard // against rounds that round down to the smaller value int outLen = (int) Math.round(inBytes.length * 1.001) + 1 + 12; byte[] outBytes = new byte[outLen]; synchronized (zStream) { zStream.next_in = inBytes; zStream.next_in_index = 0; zStream.avail_in = inBytes.length; zStream.next_out = outBytes; zStream.next_out_index = 0; zStream.avail_out = outBytes.length; int retval = zStream.deflate(JZlib.Z_SYNC_FLUSH); if (retval != JZlib.Z_OK) { outBytes = null; inBytes = null; throw new IOException("Compression failed with return value : " + retval); } IoBuffer outBuf = IoBuffer.wrap(outBytes, 0, zStream.next_out_index); return outBuf; } } /** * Cleans up the resources used by the compression library. */ public void cleanUp() { if (zStream != null) { zStream.free(); } } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-filter-compression/src/main/java/org/apache/mina/filter/compression/CompressionFilter.javamina2-2.0.7.orig/src/mina-filter-compression/src/main/java/org/apache/mina/filter/compression/Compre0000644000175000017500000002161212032276014032737 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.compression; import java.io.IOException; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.filter.util.WriteRequestFilter; /** * An {@link IoFilter} which compresses all data using * JZlib. * Support for the LZW (DLCZ) algorithm is also planned. *

* This filter only supports compression using the PARTIAL FLUSH method, * since that is the only method useful when doing stream level compression. *

* This filter supports compression/decompression of the input and output * channels selectively. It can also be enabled/disabled on the fly. *

* This filter does not discard the zlib objects, keeping them around for the * entire life of the filter. This is because the zlib dictionary needs to * be built up over time, which is used during compression and decompression. * Over time, as repetitive data is sent over the wire, the compression efficiency * steadily increases. *

* Note that the zlib header is written only once. It is not necessary that * the data received after processing by this filter may not be complete due * to packet fragmentation. *

* It goes without saying that the other end of this stream should also have a * compatible compressor/decompressor using the same algorithm. * * @author Apache MINA Project */ public class CompressionFilter extends WriteRequestFilter { /** * Max compression level. Will give the highest compression ratio, but * will also take more cpu time and is the slowest. */ public static final int COMPRESSION_MAX = Zlib.COMPRESSION_MAX; /** * Provides the best speed at the price of a low compression ratio. */ public static final int COMPRESSION_MIN = Zlib.COMPRESSION_MIN; /** * No compression done on the data. */ public static final int COMPRESSION_NONE = Zlib.COMPRESSION_NONE; /** * The default compression level used. Provides the best balance * between speed and compression */ public static final int COMPRESSION_DEFAULT = Zlib.COMPRESSION_DEFAULT; /** * A session attribute that stores the {@link Zlib} object used for compression. */ private final AttributeKey DEFLATER = new AttributeKey(getClass(), "deflater"); /** * A session attribute that stores the {@link Zlib} object used for decompression. */ private final AttributeKey INFLATER = new AttributeKey(getClass(), "inflater"); /** * A flag that allows you to disable compression once. */ public static final AttributeKey DISABLE_COMPRESSION_ONCE = new AttributeKey(CompressionFilter.class, "disableOnce"); private boolean compressInbound = true; private boolean compressOutbound = true; private int compressionLevel; /** * Creates a new instance which compresses outboud data and decompresses * inbound data with default compression level. */ public CompressionFilter() { this(true, true, COMPRESSION_DEFAULT); } /** * Creates a new instance which compresses outboud data and decompresses * inbound data with the specified compressionLevel. * * @param compressionLevel the level of compression to be used. Must * be one of {@link #COMPRESSION_DEFAULT}, * {@link #COMPRESSION_MAX}, * {@link #COMPRESSION_MIN}, and * {@link #COMPRESSION_NONE}. */ public CompressionFilter(final int compressionLevel) { this(true, true, compressionLevel); } /** * Creates a new instance. * * @param compressInbound true if data read is to be decompressed * @param compressOutbound true if data written is to be compressed * @param compressionLevel the level of compression to be used. Must * be one of {@link #COMPRESSION_DEFAULT}, * {@link #COMPRESSION_MAX}, * {@link #COMPRESSION_MIN}, and * {@link #COMPRESSION_NONE}. */ public CompressionFilter(final boolean compressInbound, final boolean compressOutbound, final int compressionLevel) { this.compressionLevel = compressionLevel; this.compressInbound = compressInbound; this.compressOutbound = compressOutbound; } @Override public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception { if (!compressInbound || !(message instanceof IoBuffer)) { nextFilter.messageReceived(session, message); return; } Zlib inflater = (Zlib) session.getAttribute(INFLATER); if (inflater == null) { throw new IllegalStateException(); } IoBuffer inBuffer = (IoBuffer) message; IoBuffer outBuffer = inflater.inflate(inBuffer); nextFilter.messageReceived(session, outBuffer); } /* * @see org.apache.mina.core.IoFilter#filterWrite(org.apache.mina.core.IoFilter.NextFilter, org.apache.mina.core.IoSession, org.apache.mina.core.IoFilter.WriteRequest) */ @Override protected Object doFilterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws IOException { if (!compressOutbound) { return null; } if (session.containsAttribute(DISABLE_COMPRESSION_ONCE)) { // Remove the marker attribute because it is temporary. session.removeAttribute(DISABLE_COMPRESSION_ONCE); return null; } Zlib deflater = (Zlib) session.getAttribute(DEFLATER); if (deflater == null) { throw new IllegalStateException(); } IoBuffer inBuffer = (IoBuffer) writeRequest.getMessage(); if (!inBuffer.hasRemaining()) { // Ignore empty buffers return null; } else { return deflater.deflate(inBuffer); } } @Override public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { if (parent.contains(CompressionFilter.class)) { throw new IllegalStateException("Only one " + CompressionFilter.class + " is permitted."); } Zlib deflater = new Zlib(compressionLevel, Zlib.MODE_DEFLATER); Zlib inflater = new Zlib(compressionLevel, Zlib.MODE_INFLATER); IoSession session = parent.getSession(); session.setAttribute(DEFLATER, deflater); session.setAttribute(INFLATER, inflater); } /** * Returns true if incoming data is being compressed. */ public boolean isCompressInbound() { return compressInbound; } /** * Sets if incoming data has to be compressed. */ public void setCompressInbound(boolean compressInbound) { this.compressInbound = compressInbound; } /** * Returns true if the filter is compressing data being written. */ public boolean isCompressOutbound() { return compressOutbound; } /** * Set if outgoing data has to be compressed. */ public void setCompressOutbound(boolean compressOutbound) { this.compressOutbound = compressOutbound; } @Override public void onPostRemove(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { super.onPostRemove(parent, name, nextFilter); IoSession session = parent.getSession(); if (session == null) { return; } Zlib inflater = (Zlib) session.getAttribute(INFLATER); Zlib deflater = (Zlib) session.getAttribute(DEFLATER); if (deflater != null) { deflater.cleanUp(); } if (inflater != null) { inflater.cleanUp(); } } } mina2-2.0.7.orig/src/mina-filter-compression/src/main/resources/0000755000175000017500000000000012032276014024074 5ustar ebourgebourgmina2-2.0.7.orig/src/pom.xml.releaseBackup0000644000175000017500000007237712033674301017705 0ustar ebourgebourg 4.0.0 org.apache apache 11 3.0.0 Apache MINA Project http://mina.apache.org/ org.apache.mina 2.0.7-SNAPSHOT mina-parent Apache MINA pom http://mina.apache.org/ 2004 jira http://issues.apache.org/jira/browse/DIRMINA scm:svn:http://svn.apache.org/repos/asf/mina/mina/tags/2.0.6 http://svn.apache.org/viewvc/mina/mina/tags/2.0.6 scm:svn:https://svn.apache.org/repos/asf/mina/mina/branches/2.0 apache.websites scp://people.apache.org/www/mina.apache.org/report/trunk/ mail

dev@mina.apache.org
Apache MINA is a network application framework which helps users develop high performance and highly scalable network applications easily. It provides an abstract event-driven asynchronous API over various transports such as TCP/IP and UDP/IP via Java NIO. Apache 2.0 License http://www.apache.org/licenses/LICENSE-2.0 repo 0.8 3.0.4 2.3 1.7 2.3.7 2.7.1 2.9.1 2.5 2.4 2.5.1 2.5.1 1.0.0-beta-1 2.5 2.7 1.0 2.9 1.1.1 2.5.2 1.4 2.3.1 2.4 2.0 2.8.1 2.0-beta-2 2.3 3.0.4 3.0.4 3.1 2.7.1 3.0-alpha-2 2.5 1.0-alpha-3 2.3.2 1.3 2.6 1.7 3.1 2.2 1.7.1 2.12.2 2.12.2 2.4 1.4 1.3.1 3.11.1 2.6 2.5.2 2.5.2 3.7.ga 1.0 1.2.0 4.10 1.1.1 1.2.17 3.0.5 4.3 2.0.2 1.6.6 1.6.6 1.6.6 2.5.6.SEC03 5.5.23 3.11.1 mina-legal mina-core mina-transport-apr mina-filter-compression mina-statemachine mina-integration-beans mina-integration-xbean mina-integration-ognl mina-integration-jmx mina-example mina-http ${project.groupId} mina-core ${project.version} bundle ${project.groupId} mina-transport-apr ${project.version} bundle ${project.groupId} mina-filter-compression ${project.version} bundle ${project.groupId} mina-integration-beans ${project.version} bundle ${project.groupId} mina-integration-ognl ${project.version} bundle ${project.groupId} mina-integration-jmx ${project.version} bundle ${project.groupId} mina-statemachine ${project.version} bundle tomcat tomcat-apr ${version.tomcat.apr} com.jcraft jzlib ${version.jzlib} org.apache.xbean xbean-spring ${version.xbean.spring} org.springframework spring ${version.springframework} commons-logging commons-logging commons-logging commons-logging-api javax.servlet servlet-api ognl ognl ${version.ognl} jboss javassist ${version.jboss.javassist} jdom jdom ${version.jdom} true jmock jmock ${version.jmock} true pmd pmd ${version.pmd} commons-lang commons-lang ${version.commons.lang} org.slf4j slf4j-api ${version.slf4j.api} org.slf4j jcl-over-slf4j ${version.slf4j.jcl.over.slf4j} org.slf4j slf4j-log4j12 ${version.slf4j.log4j12} log4j log4j ${version.log4j} junit junit ${version.junit} test org.easymock easymock ${version.easymock} test org.easymock easymockclassextension ${version.easymockclassextension} test com.agical.rmock rmock ${version.rmock} test org.slf4j slf4j-api org.slf4j slf4j-log4j12 test junit junit test serial with-LGPL-dependencies mina-transport-serial apache-release maven-javadoc-plugin install javadoc true maven-jxr-plugin true install jxr test-jxr distribution org.apache.maven.plugins maven-assembly-plugin ${version.assembly.plugin} org.apache.maven.plugins maven-changes-plugin ${version.changes.plugin} org.apache.maven.plugins maven-checkstyle-plugin ${version.checkstyle.plugin} org.apache.maven.plugins maven-clean-plugin ${version.clean.plugin} org.apache.maven.plugins maven-compiler-plugin ${version.compiler.plugin} 1.5 1.5 true true ISO-8859-1 org.apache.maven.plugins maven-dependency-plugin ${version.dependency.plugin} org.apache.maven.plugins maven-deploy-plugin ${version.deploy.plugin} true org.apache.maven.plugins maven-docck-plugin ${version.docck.plugin} org.apache.maven.plugins maven-eclipse-plugin ${version.eclipse.plugin} true true true org.apache.maven.plugins maven-enforcer-plugin ${version.enforcer.plugin} org.apache.maven.plugins maven-gpg-plugin ${version.gpg.plugin} org.apache.maven.plugins maven-install-plugin ${version.install.plugin} org.apache.maven.plugins maven-jar-plugin ${version.jar.plugin} org.apache.maven.plugins maven-javadoc-plugin ${version.javadoc.plugin} org.apache.maven.plugins maven-jxr-plugin ${version.jxr.plugin} org.apache.maven.plugins maven-plugin-plugin ${version.plugin.plugin} org.apache.maven.plugins maven-pmd-plugin ${version.pmd.plugin} org.apache.maven.plugins maven-project-info-reports-plugin ${version.project.info.plugin} org.apache.maven.plugins maven-release-plugin ${version.release.plugin} org.apache.maven.plugins maven-remote-resources-plugin ${version.remote.resources.plugin} org.apache.maven.plugins maven-resources-plugin ${version.resources.plugin} org.apache.maven.plugins maven-scm-plugin ${version.scm.plugin} org.apache.maven.plugins maven-site-plugin ${version.site.plugin} org.apache.maven.plugins maven-source-plugin ${version.source.plugin} org.apache.maven.plugins maven-surefire-report-plugin ${version.surfire.report.plugin} org.apache.maven.plugins maven-surefire-plugin ${version.surefire.plugin} -Xmx1024m org.apache.felix maven-bundle-plugin ${version.bundle.plugin} org.apache.geronimo.genesis.plugins tools-maven-plugin ${version.tools.maven.plugin} org.apache.rat apache-rat-plugin ${version.apache.rat.plugin} true false **/resources/svn_ignore.txt **/resources/Reveal in Finder.launch **/target/** **/.classpath **/.project **/.settings/** **/LICENSE.* **/NOTICE-bin.txt **/resources/** verify check org.apache.xbean maven-xbean-plugin ${version.xbean.plugin} org.codehaus.mojo build-helper-maven-plugin ${version.build.helper.plugin} org.codehaus.mojo clirr-maven-plugin ${version.clirr.plugin} org.codehaus.mojo cobertura-maven-plugin ${version.cobertura.plugin} org.codehaus.mojo dashboard-maven-plugin ${version.dashboard.plugin} org.codehaus.mojo findbugs-maven-plugin ${version.findbugs.plugin} false org.codehaus.mojo javancss-maven-plugin ${version.javancss.plugin} org.codehaus.mojo jdepend-maven-plugin ${version.jdepend.plugin} org.codehaus.mojo taglist-maven-plugin ${version.taglist.plugin} TODO @todo @deprecated FIXME org.codehaus.mojo versions-maven-plugin ${version.versions.plugin} maven-compiler-plugin ${version.compiler.plugin} UTF-8 1.5 1.5 true true true maven-surefire-plugin ${version.surefire.plugin} **/Abstract* **/*RegressionTest* maven-source-plugin ${version.source.plugin} attach-source jar maven-release-plugin https://svn.apache.org/repos/asf/mina/mina/tags clean install clean deploy forked-path true org.apache.felix maven-bundle-plugin ${version.bundle.plugin} true true ${symbolicName} ${exportedPackage}.*;version=${project.version} org.apache.maven.plugins maven-javadoc-plugin ${version.javadoc.plugin} false true true UTF-8 UTF-8 Apache MINA ${project.version} API Documentation Apache MINA ${project.version} API Documentation UTF-8 *.example.* http://java.sun.com/j2se/1.5.0/docs/api/ http://www.slf4j.org/api/ http://static.springframework.org/spring/docs/2.0.x/api/ http://dcl.mathcs.emory.edu/util/backport-util-concurrent/doc/api/ en_US org.apache.maven.plugins maven-jxr-plugin ${version.jxr.plugin} false true UTF-8 UTF-8 Apache MINA ${project.version} Cross Reference Apache MINA ${project.version} Cross Reference org.codehaus.mojo rat-maven-plugin ${version.rat.maven.plugin} **/target/**/* **/.* **/NOTICE.txt **/LICENSE*.txt false mina2-2.0.7.orig/src/pom.xml0000644000175000017500000007240112033674306015131 0ustar ebourgebourg 4.0.0 org.apache apache 11 3.0.0 Apache MINA Project http://mina.apache.org/ org.apache.mina 2.0.7 mina-parent Apache MINA pom http://mina.apache.org/ 2004 jira http://issues.apache.org/jira/browse/DIRMINA scm:svn:https://svn.apache.org/repos/asf/mina/mina/tags/2.0.7 scm:svn:https://svn.apache.org/repos/asf/mina/mina/tags/2.0.7 scm:svn:https://svn.apache.org/repos/asf/mina/mina/tags/2.0.7 apache.websites scp://people.apache.org/www/mina.apache.org/report/trunk/ mail
dev@mina.apache.org
Apache MINA is a network application framework which helps users develop high performance and highly scalable network applications easily. It provides an abstract event-driven asynchronous API over various transports such as TCP/IP and UDP/IP via Java NIO. Apache 2.0 License http://www.apache.org/licenses/LICENSE-2.0 repo 0.8 3.0.4 2.3 1.7 2.3.7 2.7.1 2.9.1 2.5 2.4 2.5.1 2.5.1 1.0.0-beta-1 2.5 2.7 1.0 2.9 1.1.1 2.5.2 1.4 2.3.1 2.4 2.0 2.8.1 2.0-beta-2 2.3 3.0.4 3.0.4 3.1 2.7.1 3.0-alpha-2 2.5 1.0-alpha-3 2.3.2 1.3 2.6 1.7 3.1 2.2 1.7.1 2.12.2 2.12.2 2.4 1.4 1.3.1 3.11.1 2.6 2.5.2 2.5.2 3.7.ga 1.0 1.2.0 4.10 1.1.1 1.2.17 3.0.5 4.3 2.0.2 1.6.6 1.6.6 1.6.6 2.5.6.SEC03 5.5.23 3.11.1 mina-legal mina-core mina-transport-apr mina-filter-compression mina-statemachine mina-integration-beans mina-integration-xbean mina-integration-ognl mina-integration-jmx mina-example mina-http ${project.groupId} mina-core ${project.version} bundle ${project.groupId} mina-transport-apr ${project.version} bundle ${project.groupId} mina-filter-compression ${project.version} bundle ${project.groupId} mina-integration-beans ${project.version} bundle ${project.groupId} mina-integration-ognl ${project.version} bundle ${project.groupId} mina-integration-jmx ${project.version} bundle ${project.groupId} mina-statemachine ${project.version} bundle tomcat tomcat-apr ${version.tomcat.apr} com.jcraft jzlib ${version.jzlib} org.apache.xbean xbean-spring ${version.xbean.spring} org.springframework spring ${version.springframework} commons-logging commons-logging commons-logging commons-logging-api javax.servlet servlet-api ognl ognl ${version.ognl} jboss javassist ${version.jboss.javassist} jdom jdom ${version.jdom} true jmock jmock ${version.jmock} true pmd pmd ${version.pmd} commons-lang commons-lang ${version.commons.lang} org.slf4j slf4j-api ${version.slf4j.api} org.slf4j jcl-over-slf4j ${version.slf4j.jcl.over.slf4j} org.slf4j slf4j-log4j12 ${version.slf4j.log4j12} log4j log4j ${version.log4j} junit junit ${version.junit} test org.easymock easymock ${version.easymock} test org.easymock easymockclassextension ${version.easymockclassextension} test com.agical.rmock rmock ${version.rmock} test org.slf4j slf4j-api org.slf4j slf4j-log4j12 test junit junit test serial with-LGPL-dependencies mina-transport-serial apache-release maven-javadoc-plugin install javadoc true maven-jxr-plugin true install jxr test-jxr distribution org.apache.maven.plugins maven-assembly-plugin ${version.assembly.plugin} org.apache.maven.plugins maven-changes-plugin ${version.changes.plugin} org.apache.maven.plugins maven-checkstyle-plugin ${version.checkstyle.plugin} org.apache.maven.plugins maven-clean-plugin ${version.clean.plugin} org.apache.maven.plugins maven-compiler-plugin ${version.compiler.plugin} 1.5 1.5 true true ISO-8859-1 org.apache.maven.plugins maven-dependency-plugin ${version.dependency.plugin} org.apache.maven.plugins maven-deploy-plugin ${version.deploy.plugin} true org.apache.maven.plugins maven-docck-plugin ${version.docck.plugin} org.apache.maven.plugins maven-eclipse-plugin ${version.eclipse.plugin} true true true org.apache.maven.plugins maven-enforcer-plugin ${version.enforcer.plugin} org.apache.maven.plugins maven-gpg-plugin ${version.gpg.plugin} org.apache.maven.plugins maven-install-plugin ${version.install.plugin} org.apache.maven.plugins maven-jar-plugin ${version.jar.plugin} org.apache.maven.plugins maven-javadoc-plugin ${version.javadoc.plugin} org.apache.maven.plugins maven-jxr-plugin ${version.jxr.plugin} org.apache.maven.plugins maven-plugin-plugin ${version.plugin.plugin} org.apache.maven.plugins maven-pmd-plugin ${version.pmd.plugin} org.apache.maven.plugins maven-project-info-reports-plugin ${version.project.info.plugin} org.apache.maven.plugins maven-release-plugin ${version.release.plugin} org.apache.maven.plugins maven-remote-resources-plugin ${version.remote.resources.plugin} org.apache.maven.plugins maven-resources-plugin ${version.resources.plugin} org.apache.maven.plugins maven-scm-plugin ${version.scm.plugin} org.apache.maven.plugins maven-site-plugin ${version.site.plugin} org.apache.maven.plugins maven-source-plugin ${version.source.plugin} org.apache.maven.plugins maven-surefire-report-plugin ${version.surfire.report.plugin} org.apache.maven.plugins maven-surefire-plugin ${version.surefire.plugin} -Xmx1024m org.apache.felix maven-bundle-plugin ${version.bundle.plugin} org.apache.geronimo.genesis.plugins tools-maven-plugin ${version.tools.maven.plugin} org.apache.rat apache-rat-plugin ${version.apache.rat.plugin} true false **/resources/svn_ignore.txt **/resources/Reveal in Finder.launch **/target/** **/.classpath **/.project **/.settings/** **/LICENSE.* **/NOTICE-bin.txt **/resources/** verify check org.apache.xbean maven-xbean-plugin ${version.xbean.plugin} org.codehaus.mojo build-helper-maven-plugin ${version.build.helper.plugin} org.codehaus.mojo clirr-maven-plugin ${version.clirr.plugin} org.codehaus.mojo cobertura-maven-plugin ${version.cobertura.plugin} org.codehaus.mojo dashboard-maven-plugin ${version.dashboard.plugin} org.codehaus.mojo findbugs-maven-plugin ${version.findbugs.plugin} false org.codehaus.mojo javancss-maven-plugin ${version.javancss.plugin} org.codehaus.mojo jdepend-maven-plugin ${version.jdepend.plugin} org.codehaus.mojo taglist-maven-plugin ${version.taglist.plugin} TODO @todo @deprecated FIXME org.codehaus.mojo versions-maven-plugin ${version.versions.plugin} maven-compiler-plugin ${version.compiler.plugin} UTF-8 1.5 1.5 true true true maven-surefire-plugin ${version.surefire.plugin} **/Abstract* **/*RegressionTest* maven-source-plugin ${version.source.plugin} attach-source jar maven-release-plugin https://svn.apache.org/repos/asf/mina/mina/tags clean install clean deploy forked-path true org.apache.felix maven-bundle-plugin ${version.bundle.plugin} true true ${symbolicName} ${exportedPackage}.*;version=${project.version} org.apache.maven.plugins maven-javadoc-plugin ${version.javadoc.plugin} false true true UTF-8 UTF-8 Apache MINA ${project.version} API Documentation Apache MINA ${project.version} API Documentation UTF-8 *.example.* http://java.sun.com/j2se/1.5.0/docs/api/ http://www.slf4j.org/api/ http://static.springframework.org/spring/docs/2.0.x/api/ http://dcl.mathcs.emory.edu/util/backport-util-concurrent/doc/api/ en_US org.apache.maven.plugins maven-jxr-plugin ${version.jxr.plugin} false true UTF-8 UTF-8 Apache MINA ${project.version} Cross Reference Apache MINA ${project.version} Cross Reference org.codehaus.mojo rat-maven-plugin ${version.rat.maven.plugin} **/target/**/* **/.* **/NOTICE.txt **/LICENSE*.txt false
mina2-2.0.7.orig/src/mina-transport-apr/0000755000175000017500000000000012162575507017354 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-apr/pom.xml.releaseBackup0000644000175000017500000000351412033674301023426 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7-SNAPSHOT mina-transport-apr Apache MINA APR Transport bundle ${project.groupId}.transport.socket.apr ${project.groupId}.transport.socket.apr ${project.groupId} mina-core ${project.version} bundle tomcat tomcat-apr mina2-2.0.7.orig/src/mina-transport-apr/pom.xml0000644000175000017500000000350312033674306020664 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7 mina-transport-apr Apache MINA APR Transport bundle ${project.groupId}.transport.socket.apr ${project.groupId}.transport.socket.apr ${project.groupId} mina-core ${project.version} bundle tomcat tomcat-apr mina2-2.0.7.orig/src/mina-transport-apr/src/0000755000175000017500000000000012032276012020124 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-apr/src/main/0000755000175000017500000000000012032276012021050 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-apr/src/main/java/0000755000175000017500000000000012032276012021771 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/0000755000175000017500000000000012032276012022560 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/0000755000175000017500000000000012032276012024001 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/0000755000175000017500000000000012032276012024725 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/0000755000175000017500000000000012032276012026761 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/socket/0000755000175000017500000000000012032276012030251 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/socket/apr/0000755000175000017500000000000012162575507031052 5ustar ebourgebourg././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/socket/apr/AprLibrary.javamina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/socket/apr/AprLibrar0000644000175000017500000000611212032276013032635 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.apr; import org.apache.tomcat.jni.Library; import org.apache.tomcat.jni.Pool; /** * Internal singleton used for initializing correctly the APR native library * and the associated root memory pool. * * It'll finalize nicely the native resources (libraries and memory pools). * * Each memory pool used in the APR transport module needs to be children of the * root pool {@link AprLibrary#getRootPool()}. * * @author Apache MINA Project */ class AprLibrary { // is APR library was initialized (load of native libraries) private static AprLibrary library = null; /** * get the shared instance of APR library, if none, initialize one * @return the current APR library singleton */ static synchronized AprLibrary getInstance() { if (!isInitialized()) initialize(); return library; } /** * initialize the APR Library by loading the associated native libraries * and creating the associated singleton */ private static synchronized void initialize() { if (library == null) library = new AprLibrary(); } /** * is the APR library was initialized. * @return true if the Library is initialized, false otherwise */ static synchronized boolean isInitialized() { return library != null; } // APR memory pool (package wide mother pool) private final long pool; /** * APR library singleton constructor. Called only when accessing the * singleton the first time. * It's initializing an APR memory pool for the whole package (a.k.a mother or root pool). */ private AprLibrary() { try { Library.initialize(null); } catch (Exception e) { throw new RuntimeException("Error loading Apache Portable Runtime (APR).", e); } pool = Pool.create(0); } @Override protected void finalize() throws Throwable { super.finalize(); Pool.destroy(pool); } /** * get the package wide root pool, the mother of all the pool created * in APR transport module. * @return number identifying the root pool */ long getRootPool() { return pool; } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/socket/apr/AprSession.javamina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/socket/apr/AprSessio0000644000175000017500000001641312032276013032674 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.apr; import java.net.InetSocketAddress; import org.apache.mina.core.filterchain.DefaultIoFilterChain; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.IoService; import org.apache.mina.core.session.AbstractIoSession; import org.apache.mina.core.session.IoSession; import org.apache.tomcat.jni.Address; import org.apache.tomcat.jni.Socket; /** * An abstract {@link IoSession} serving of base for APR based sessions. * * @author Apache MINA Project */ public abstract class AprSession extends AbstractIoSession { // good old socket descriptor private long descriptor; // the processor processing this session private final IoProcessor processor; // the mandatory filter chain of this session private final IoFilterChain filterChain = new DefaultIoFilterChain(this); // the two endpoint addresses private final InetSocketAddress remoteAddress; private final InetSocketAddress localAddress; // current polling results private boolean readable = true; private boolean writable = true; private boolean interestedInRead; private boolean interestedInWrite; /** * Creates a new instance of {@link AprSession}. Need to be called by extending types * @param service the {@link IoService} creating this session. Can be {@link AprSocketAcceptor} or * {@link AprSocketConnector} * @param processor the {@link AprIoProcessor} managing this session. * @param descriptor the low level APR socket descriptor for this socket. {@see Socket#create(int, int, int, long)} * @throws Exception exception produced during the setting of all the socket parameters. */ AprSession(IoService service, IoProcessor processor, long descriptor) throws Exception { super(service); this.processor = processor; this.descriptor = descriptor; long ra = Address.get(Socket.APR_REMOTE, descriptor); long la = Address.get(Socket.APR_LOCAL, descriptor); this.remoteAddress = new InetSocketAddress(Address.getip(ra), Address.getInfo(ra).port); this.localAddress = new InetSocketAddress(Address.getip(la), Address.getInfo(la).port); } /** * Creates a new instance of {@link AprSession}. Need to be called by extending types. * The constructor add remote address for UDP based sessions. * @param service the {@link IoService} creating this session. Can be {@link AprSocketAcceptor} or * {@link AprSocketConnector} * @param processor the {@link AprIoProcessor} managing this session. * @param descriptor the low level APR socket descriptor for this socket. {@see Socket#create(int, int, int, long)} * @param remoteAddress the remote end-point * @throws Exception exception produced during the setting of all the socket parameters. */ AprSession(IoService service, IoProcessor processor, long descriptor, InetSocketAddress remoteAddress) throws Exception { super(service); this.processor = processor; this.descriptor = descriptor; long la = Address.get(Socket.APR_LOCAL, descriptor); this.remoteAddress = remoteAddress; this.localAddress = new InetSocketAddress(Address.getip(la), Address.getInfo(la).port); } /** * Get the socket descriptor {@see Socket#create(int, int, int, long)}. * @return the low level APR socket descriptor */ long getDescriptor() { return descriptor; } /** * Set the socket descriptor. * @param desc the low level APR socket descriptor created by {@see Socket#create(int, int, int, long)} */ void setDescriptor(long desc) { this.descriptor = desc; } /** * {@inheritDoc} */ @Override public IoProcessor getProcessor() { return processor; } /** * {@inheritDoc} */ public InetSocketAddress getLocalAddress() { return localAddress; } /** * {@inheritDoc} */ public InetSocketAddress getRemoteAddress() { return remoteAddress; } /** * {@inheritDoc} */ public IoFilterChain getFilterChain() { return filterChain; } /** * {@inheritDoc} */ @Override public InetSocketAddress getServiceAddress() { return (InetSocketAddress) super.getServiceAddress(); } /** * Is this session was tagged are readable after a call to {@link Socket#pool(long)}. * @return true if this session is ready for read operations */ boolean isReadable() { return readable; } /** * Set if this session is readable after a call to {@link Socket#pool(long)}. * @param readable true for set this session ready for read operations */ void setReadable(boolean readable) { this.readable = readable; } /** * Is this session is tagged writable after a call to {@link Socket#pool(long)}. * @return true if this session is ready for write operations */ boolean isWritable() { return writable; } /** * Set if this session is writable after a call to {@link Socket#pool(long)}. * @param writable true for set this session ready for write operations */ void setWritable(boolean writable) { this.writable = writable; } /** * Does this session needs to be registered for read events. * Used for building poll set {@see Poll}. * @return true if registered */ boolean isInterestedInRead() { return interestedInRead; } /** * Set if this session needs to be registered for read events. * Used for building poll set {@see Poll}. * @param isOpRead true if need to be registered */ void setInterestedInRead(boolean isOpRead) { this.interestedInRead = isOpRead; } /** * Does this session needs to be registered for write events. * Used for building poll set {@see Poll}. * @return true if registered */ boolean isInterestedInWrite() { return interestedInWrite; } /** * Set if this session needs to be registered for write events. * Used for building poll set {@see Poll}. * @param isOpWrite true if need to be registered */ void setInterestedInWrite(boolean isOpWrite) { this.interestedInWrite = isOpWrite; } }././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/socket/apr/AprSocketConnector.javamina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/socket/apr/AprSocket0000644000175000017500000003157612032276013032666 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.apr; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Queue; import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.polling.AbstractPollingIoConnector; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.IoService; import org.apache.mina.core.service.SimpleIoProcessorPool; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.transport.socket.DefaultSocketSessionConfig; import org.apache.mina.transport.socket.SocketConnector; import org.apache.mina.transport.socket.SocketSessionConfig; import org.apache.tomcat.jni.Address; import org.apache.tomcat.jni.Poll; import org.apache.tomcat.jni.Pool; import org.apache.tomcat.jni.Socket; import org.apache.tomcat.jni.Status; /** * {@link IoConnector} for APR based socket transport (TCP/IP). * * @author Apache MINA Project */ public final class AprSocketConnector extends AbstractPollingIoConnector implements SocketConnector { /** * This constant is deduced from the APR code. It is used when the timeout * has expired while doing a poll() operation. */ private static final int APR_TIMEUP_ERROR = -120001; private static final int POLLSET_SIZE = 1024; private final Map requests = new HashMap(POLLSET_SIZE); private final Object wakeupLock = new Object(); private volatile long wakeupSocket; private volatile boolean toBeWakenUp; private volatile long pool; private volatile long pollset; // socket poller private final long[] polledSockets = new long[POLLSET_SIZE << 1]; private final Queue polledHandles = new ConcurrentLinkedQueue(); private final Set failedHandles = new HashSet(POLLSET_SIZE); private volatile ByteBuffer dummyBuffer; /** * Create an {@link AprSocketConnector} with default configuration (multiple thread model). */ public AprSocketConnector() { super(new DefaultSocketSessionConfig(), AprIoProcessor.class); ((DefaultSocketSessionConfig) getSessionConfig()).init(this); } /** * Constructor for {@link AprSocketConnector} with default configuration, and * given number of {@link AprIoProcessor} for multithreading I/O operations * @param processorCount the number of processor to create and place in a * {@link SimpleIoProcessorPool} */ public AprSocketConnector(int processorCount) { super(new DefaultSocketSessionConfig(), AprIoProcessor.class, processorCount); ((DefaultSocketSessionConfig) getSessionConfig()).init(this); } /** * Constructor for {@link AprSocketConnector} with default configuration but a * specific {@link IoProcessor}, useful for sharing the same processor over multiple * {@link IoService} of the same type. * @param processor the processor to use for managing I/O events */ public AprSocketConnector(IoProcessor processor) { super(new DefaultSocketSessionConfig(), processor); ((DefaultSocketSessionConfig) getSessionConfig()).init(this); } /** * Constructor for {@link AprSocketConnector} with a given {@link Executor} for handling * connection events and a given {@link IoProcessor} for handling I/O events, useful for sharing * the same processor and executor over multiple {@link IoService} of the same type. * @param executor the executor for connection * @param processor the processor for I/O operations */ public AprSocketConnector(Executor executor, IoProcessor processor) { super(new DefaultSocketSessionConfig(), executor, processor); ((DefaultSocketSessionConfig) getSessionConfig()).init(this); } /** * {@inheritDoc} */ @Override protected void init() throws Exception { // initialize a memory pool for APR functions pool = Pool.create(AprLibrary.getInstance().getRootPool()); wakeupSocket = Socket.create(Socket.APR_INET, Socket.SOCK_DGRAM, Socket.APR_PROTO_UDP, pool); dummyBuffer = Pool.alloc(pool, 1); pollset = Poll.create(POLLSET_SIZE, pool, Poll.APR_POLLSET_THREADSAFE, Long.MAX_VALUE); if (pollset <= 0) { pollset = Poll.create(62, pool, Poll.APR_POLLSET_THREADSAFE, Long.MAX_VALUE); } if (pollset <= 0) { if (Status.APR_STATUS_IS_ENOTIMPL(-(int) pollset)) { throw new RuntimeIoException("Thread-safe pollset is not supported in this platform."); } } } /** * {@inheritDoc} */ @Override protected void destroy() throws Exception { if (wakeupSocket > 0) { Socket.close(wakeupSocket); } if (pollset > 0) { Poll.destroy(pollset); } if (pool > 0) { Pool.destroy(pool); } } /** * {@inheritDoc} */ @Override protected Iterator allHandles() { return polledHandles.iterator(); } /** * {@inheritDoc} */ @Override protected boolean connect(Long handle, SocketAddress remoteAddress) throws Exception { InetSocketAddress ra = (InetSocketAddress) remoteAddress; long sa; if (ra != null) { if (ra.getAddress() == null) { sa = Address.info(Address.APR_ANYADDR, Socket.APR_INET, ra.getPort(), 0, pool); } else { sa = Address.info(ra.getAddress().getHostAddress(), Socket.APR_INET, ra.getPort(), 0, pool); } } else { sa = Address.info(Address.APR_ANYADDR, Socket.APR_INET, 0, 0, pool); } int rv = Socket.connect(handle, sa); if (rv == Status.APR_SUCCESS) { return true; } if (Status.APR_STATUS_IS_EINPROGRESS(rv)) { return false; } throwException(rv); throw new InternalError(); // This sentence will never be executed. } /** * {@inheritDoc} */ @Override protected ConnectionRequest getConnectionRequest(Long handle) { return requests.get(handle); } /** * {@inheritDoc} */ @Override protected void close(Long handle) throws Exception { finishConnect(handle); int rv = Socket.close(handle); if (rv != Status.APR_SUCCESS) { throwException(rv); } } /** * {@inheritDoc} */ @Override protected boolean finishConnect(Long handle) throws Exception { Poll.remove(pollset, handle); requests.remove(handle); if (failedHandles.remove(handle)) { int rv = Socket.recvb(handle, dummyBuffer, 0, 1); throwException(rv); throw new InternalError("Shouldn't reach here."); } return true; } /** * {@inheritDoc} */ @Override protected Long newHandle(SocketAddress localAddress) throws Exception { long handle = Socket.create(Socket.APR_INET, Socket.SOCK_STREAM, Socket.APR_PROTO_TCP, pool); boolean success = false; try { int result = Socket.optSet(handle, Socket.APR_SO_NONBLOCK, 1); if (result != Status.APR_SUCCESS) { throwException(result); } result = Socket.timeoutSet(handle, 0); if (result != Status.APR_SUCCESS) { throwException(result); } if (localAddress != null) { InetSocketAddress la = (InetSocketAddress) localAddress; long sa; if (la.getAddress() == null) { sa = Address.info(Address.APR_ANYADDR, Socket.APR_INET, la.getPort(), 0, pool); } else { sa = Address.info(la.getAddress().getHostAddress(), Socket.APR_INET, la.getPort(), 0, pool); } result = Socket.bind(handle, sa); if (result != Status.APR_SUCCESS) { throwException(result); } } success = true; return handle; } finally { if (!success) { int rv = Socket.close(handle); if (rv != Status.APR_SUCCESS) { throwException(rv); } } } } /** * {@inheritDoc} */ @Override protected AprSession newSession(IoProcessor processor, Long handle) throws Exception { return new AprSocketSession(this, processor, handle); } /** * {@inheritDoc} */ @Override protected void register(Long handle, ConnectionRequest request) throws Exception { int rv = Poll.add(pollset, handle, Poll.APR_POLLOUT); if (rv != Status.APR_SUCCESS) { throwException(rv); } requests.put(handle, request); } /** * {@inheritDoc} */ @Override protected int select(int timeout) throws Exception { int rv = Poll.poll(pollset, timeout * 1000, polledSockets, false); if (rv <= 0) { if (rv != APR_TIMEUP_ERROR) { throwException(rv); } rv = Poll.maintain(pollset, polledSockets, true); if (rv > 0) { for (int i = 0; i < rv; i++) { Poll.add(pollset, polledSockets[i], Poll.APR_POLLOUT); } } else if (rv < 0) { throwException(rv); } return 0; } else { rv <<= 1; if (!polledHandles.isEmpty()) { polledHandles.clear(); } for (int i = 0; i < rv; i++) { long flag = polledSockets[i]; long socket = polledSockets[++i]; if (socket == wakeupSocket) { synchronized (wakeupLock) { Poll.remove(pollset, wakeupSocket); toBeWakenUp = false; } continue; } polledHandles.add(socket); if ((flag & Poll.APR_POLLOUT) == 0) { failedHandles.add(socket); } } return polledHandles.size(); } } /** * {@inheritDoc} */ @Override protected Iterator selectedHandles() { return polledHandles.iterator(); } /** * {@inheritDoc} */ @Override protected void wakeup() { if (toBeWakenUp) { return; } // Add a dummy socket to the pollset. synchronized (wakeupLock) { toBeWakenUp = true; Poll.add(pollset, wakeupSocket, Poll.APR_POLLOUT); } } /** * {@inheritDoc} */ public TransportMetadata getTransportMetadata() { return AprSocketSession.METADATA; } /** * {@inheritDoc} */ @Override public SocketSessionConfig getSessionConfig() { return (SocketSessionConfig) super.getSessionConfig(); } /** * {@inheritDoc} */ @Override public InetSocketAddress getDefaultRemoteAddress() { return (InetSocketAddress) super.getDefaultRemoteAddress(); } /** * {@inheritDoc} */ public void setDefaultRemoteAddress(InetSocketAddress defaultRemoteAddress) { super.setDefaultRemoteAddress(defaultRemoteAddress); } /** * transform an APR error number in a more fancy exception * @param code APR error code * @throws IOException the produced exception for the given APR error number */ private void throwException(int code) throws IOException { throw new IOException(org.apache.tomcat.jni.Error.strerror(-code) + " (code: " + code + ")"); } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/socket/apr/AprSocketSession.javamina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/socket/apr/AprSocket0000644000175000017500000001445012032276013032656 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.apr; import java.net.InetSocketAddress; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.service.DefaultTransportMetadata; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.IoService; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionConfig; import org.apache.mina.transport.socket.AbstractSocketSessionConfig; import org.apache.mina.transport.socket.SocketSessionConfig; import org.apache.tomcat.jni.Socket; /** * An {@link IoSession} for APR TCP socket based session. * It's implementing the usual common features for {@SocketSession}. * * @author Apache MINA Project */ class AprSocketSession extends AprSession { static final TransportMetadata METADATA = new DefaultTransportMetadata("apr", "socket", false, true, InetSocketAddress.class, SocketSessionConfig.class, IoBuffer.class); /** * Create an instance of {@link AprSocketSession}. * * {@inheritDoc} */ AprSocketSession(IoService service, IoProcessor processor, long descriptor) throws Exception { super(service, processor, descriptor); config = new SessionConfigImpl(); this.config.setAll(service.getSessionConfig()); } /** * {@inheritDoc} */ public SocketSessionConfig getConfig() { return (SocketSessionConfig) config; } /** * {@inheritDoc} */ public TransportMetadata getTransportMetadata() { return METADATA; } /** * The implementation for the {@link IoSessionConfig} related to APR TCP socket. * @author Apache MINA Project */ private class SessionConfigImpl extends AbstractSocketSessionConfig { /** * {@inheritDoc} */ public boolean isKeepAlive() { try { return Socket.optGet(getDescriptor(), Socket.APR_SO_KEEPALIVE) == 1; } catch (Exception e) { throw new RuntimeIoException("Failed to get SO_KEEPALIVE.", e); } } /** * {@inheritDoc} */ public void setKeepAlive(boolean on) { Socket.optSet(getDescriptor(), Socket.APR_SO_KEEPALIVE, on ? 1 : 0); } /** * {@inheritDoc} * not supported for the moment */ public boolean isOobInline() { return false; } /** * {@inheritDoc} * not supported for the moment */ public void setOobInline(boolean on) { } /** * {@inheritDoc} */ public boolean isReuseAddress() { try { return Socket.optGet(getDescriptor(), Socket.APR_SO_REUSEADDR) == 1; } catch (Exception e) { throw new RuntimeIoException("Failed to get SO_REUSEADDR.", e); } } /** * {@inheritDoc} */ public void setReuseAddress(boolean on) { Socket.optSet(getDescriptor(), Socket.APR_SO_REUSEADDR, on ? 1 : 0); } /** * {@inheritDoc} */ public int getSoLinger() { try { return Socket.optGet(getDescriptor(), Socket.APR_SO_LINGER); } catch (Exception e) { throw new RuntimeIoException("Failed to get SO_LINGER.", e); } } /** * {@inheritDoc} */ public void setSoLinger(int linger) { // TODO: Figure out how to disable this. Socket.optSet(getDescriptor(), Socket.APR_SO_LINGER, linger); } /** * {@inheritDoc} */ public boolean isTcpNoDelay() { try { return Socket.optGet(getDescriptor(), Socket.APR_TCP_NODELAY) == 1; } catch (Exception e) { throw new RuntimeIoException("Failed to get TCP_NODELAY.", e); } } /** * {@inheritDoc} */ public void setTcpNoDelay(boolean on) { Socket.optSet(getDescriptor(), Socket.APR_TCP_NODELAY, on ? 1 : 0); } /** * {@inheritDoc} */ public int getTrafficClass() { return 0; } /** * {@inheritDoc} */ public void setTrafficClass(int tc) { } /** * {@inheritDoc} */ public int getSendBufferSize() { try { return Socket.optGet(getDescriptor(), Socket.APR_SO_SNDBUF); } catch (Exception e) { throw new RuntimeException("APR Exception", e); } } /** * {@inheritDoc} */ public void setSendBufferSize(int size) { Socket.optSet(getDescriptor(), Socket.APR_SO_SNDBUF, size); } /** * {@inheritDoc} */ public int getReceiveBufferSize() { try { return Socket.optGet(getDescriptor(), Socket.APR_SO_RCVBUF); } catch (Exception e) { throw new RuntimeException("APR Exception", e); } } /** * {@inheritDoc} */ public void setReceiveBufferSize(int size) { Socket.optSet(getDescriptor(), Socket.APR_SO_RCVBUF, size); } } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/socket/apr/AprIoProcessor.javamina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/socket/apr/AprIoProc0000644000175000017500000003367212032276013032630 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.apr; import java.io.IOException; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.file.FileRegion; import org.apache.mina.core.polling.AbstractPollingIoProcessor; import org.apache.mina.core.session.SessionState; import org.apache.tomcat.jni.File; import org.apache.tomcat.jni.Poll; import org.apache.tomcat.jni.Pool; import org.apache.tomcat.jni.Socket; import org.apache.tomcat.jni.Status; /** * The class in charge of processing socket level IO events for the * {@link AprSocketConnector} * * @author Apache MINA Project */ public final class AprIoProcessor extends AbstractPollingIoProcessor { private static final int POLLSET_SIZE = 1024; private final Map allSessions = new HashMap(POLLSET_SIZE); private final Object wakeupLock = new Object(); private final long wakeupSocket; private volatile boolean toBeWakenUp; private final long pool; private final long bufferPool; // memory pool private final long pollset; // socket poller private final long[] polledSockets = new long[POLLSET_SIZE << 1]; private final Queue polledSessions = new ConcurrentLinkedQueue(); /** * Create a new instance of {@link AprIoProcessor} with a given Exector for * handling I/Os events. * * @param executor * the {@link Executor} for handling I/O events */ public AprIoProcessor(Executor executor) { super(executor); // initialize a memory pool for APR functions pool = Pool.create(AprLibrary.getInstance().getRootPool()); bufferPool = Pool.create(AprLibrary.getInstance().getRootPool()); try { wakeupSocket = Socket.create(Socket.APR_INET, Socket.SOCK_DGRAM, Socket.APR_PROTO_UDP, pool); } catch (RuntimeException e) { throw e; } catch (Error e) { throw e; } catch (Exception e) { throw new RuntimeIoException("Failed to create a wakeup socket.", e); } boolean success = false; long newPollset; try { newPollset = Poll.create(POLLSET_SIZE, pool, Poll.APR_POLLSET_THREADSAFE, Long.MAX_VALUE); if (newPollset == 0) { newPollset = Poll.create(62, pool, Poll.APR_POLLSET_THREADSAFE, Long.MAX_VALUE); } pollset = newPollset; if (pollset < 0) { if (Status.APR_STATUS_IS_ENOTIMPL(-(int) pollset)) { throw new RuntimeIoException("Thread-safe pollset is not supported in this platform."); } } success = true; } catch (RuntimeException e) { throw e; } catch (Error e) { throw e; } catch (Exception e) { throw new RuntimeIoException("Failed to create a pollset.", e); } finally { if (!success) { dispose(); } } } /** * {@inheritDoc} */ @Override protected void doDispose() { Poll.destroy(pollset); Socket.close(wakeupSocket); Pool.destroy(bufferPool); Pool.destroy(pool); } /** * {@inheritDoc} */ @Override protected int select() throws Exception { return select(Integer.MAX_VALUE); } /** * {@inheritDoc} */ @Override protected int select(long timeout) throws Exception { int rv = Poll.poll(pollset, 1000 * timeout, polledSockets, false); if (rv <= 0) { if (rv != -120001) { throwException(rv); } rv = Poll.maintain(pollset, polledSockets, true); if (rv > 0) { for (int i = 0; i < rv; i++) { long socket = polledSockets[i]; AprSession session = allSessions.get(socket); if (session == null) { continue; } int flag = (session.isInterestedInRead() ? Poll.APR_POLLIN : 0) | (session.isInterestedInWrite() ? Poll.APR_POLLOUT : 0); Poll.add(pollset, socket, flag); } } else if (rv < 0) { throwException(rv); } return 0; } else { rv <<= 1; if (!polledSessions.isEmpty()) { polledSessions.clear(); } for (int i = 0; i < rv; i++) { long flag = polledSockets[i]; long socket = polledSockets[++i]; if (socket == wakeupSocket) { synchronized (wakeupLock) { Poll.remove(pollset, wakeupSocket); toBeWakenUp = false; wakeupCalled.set(true); } continue; } AprSession session = allSessions.get(socket); if (session == null) { continue; } session.setReadable((flag & Poll.APR_POLLIN) != 0); session.setWritable((flag & Poll.APR_POLLOUT) != 0); polledSessions.add(session); } return polledSessions.size(); } } /** * {@inheritDoc} */ @Override protected boolean isSelectorEmpty() { return allSessions.isEmpty(); } /** * {@inheritDoc} */ @Override protected void wakeup() { if (toBeWakenUp) { return; } // Add a dummy socket to the pollset. synchronized (wakeupLock) { toBeWakenUp = true; Poll.add(pollset, wakeupSocket, Poll.APR_POLLOUT); } } /** * {@inheritDoc} */ @Override protected Iterator allSessions() { return allSessions.values().iterator(); } /** * {@inheritDoc} */ @Override protected Iterator selectedSessions() { return polledSessions.iterator(); } @Override protected void init(AprSession session) throws Exception { long s = session.getDescriptor(); Socket.optSet(s, Socket.APR_SO_NONBLOCK, 1); Socket.timeoutSet(s, 0); int rv = Poll.add(pollset, s, Poll.APR_POLLIN); if (rv != Status.APR_SUCCESS) { throwException(rv); } session.setInterestedInRead(true); allSessions.put(s, session); } /** * {@inheritDoc} */ @Override protected void destroy(AprSession session) throws Exception { if (allSessions.remove(session.getDescriptor()) == null) { // Already destroyed. return; } int ret = Poll.remove(pollset, session.getDescriptor()); try { if (ret != Status.APR_SUCCESS) { throwException(ret); } } finally { ret = Socket.close(session.getDescriptor()); // destroying the session because it won't be reused // after this point Socket.destroy(session.getDescriptor()); session.setDescriptor(0); if (ret != Status.APR_SUCCESS) { throwException(ret); } } } /** * {@inheritDoc} */ @Override protected SessionState getState(AprSession session) { long socket = session.getDescriptor(); if (socket != 0) { return SessionState.OPENED; } else if (allSessions.get(socket) != null) { return SessionState.OPENING; // will occur ? } else { return SessionState.CLOSING; } } /** * {@inheritDoc} */ @Override protected boolean isReadable(AprSession session) { return session.isReadable(); } /** * {@inheritDoc} */ @Override protected boolean isWritable(AprSession session) { return session.isWritable(); } /** * {@inheritDoc} */ @Override protected boolean isInterestedInRead(AprSession session) { return session.isInterestedInRead(); } /** * {@inheritDoc} */ @Override protected boolean isInterestedInWrite(AprSession session) { return session.isInterestedInWrite(); } /** * {@inheritDoc} */ @Override protected void setInterestedInRead(AprSession session, boolean isInterested) throws Exception { if (session.isInterestedInRead() == isInterested) { return; } int rv = Poll.remove(pollset, session.getDescriptor()); if (rv != Status.APR_SUCCESS) { throwException(rv); } int flags = (isInterested ? Poll.APR_POLLIN : 0) | (session.isInterestedInWrite() ? Poll.APR_POLLOUT : 0); rv = Poll.add(pollset, session.getDescriptor(), flags); if (rv == Status.APR_SUCCESS) { session.setInterestedInRead(isInterested); } else { throwException(rv); } } /** * {@inheritDoc} */ @Override protected void setInterestedInWrite(AprSession session, boolean isInterested) throws Exception { if (session.isInterestedInWrite() == isInterested) { return; } int rv = Poll.remove(pollset, session.getDescriptor()); if (rv != Status.APR_SUCCESS) { throwException(rv); } int flags = (session.isInterestedInRead() ? Poll.APR_POLLIN : 0) | (isInterested ? Poll.APR_POLLOUT : 0); rv = Poll.add(pollset, session.getDescriptor(), flags); if (rv == Status.APR_SUCCESS) { session.setInterestedInWrite(isInterested); } else { throwException(rv); } } /** * {@inheritDoc} */ @Override protected int read(AprSession session, IoBuffer buffer) throws Exception { int bytes; int capacity = buffer.remaining(); // Using Socket.recv() directly causes memory leak. :-( ByteBuffer b = Pool.alloc(bufferPool, capacity); try { bytes = Socket.recvb(session.getDescriptor(), b, 0, capacity); if (bytes > 0) { b.position(0); b.limit(bytes); buffer.put(b); } else if (bytes < 0) { if (Status.APR_STATUS_IS_EOF(-bytes)) { bytes = -1; } else if (Status.APR_STATUS_IS_EAGAIN(-bytes)) { bytes = 0; } else { throwException(bytes); } } } finally { Pool.clear(bufferPool); } return bytes; } /** * {@inheritDoc} */ @Override protected int write(AprSession session, IoBuffer buf, int length) throws Exception { int writtenBytes; if (buf.isDirect()) { writtenBytes = Socket.sendb(session.getDescriptor(), buf.buf(), buf.position(), length); } else { writtenBytes = Socket.send(session.getDescriptor(), buf.array(), buf.position(), length); if (writtenBytes > 0) { buf.skip(writtenBytes); } } if (writtenBytes < 0) { if (Status.APR_STATUS_IS_EAGAIN(-writtenBytes)) { writtenBytes = 0; } else if (Status.APR_STATUS_IS_EOF(-writtenBytes)) { writtenBytes = 0; } else { throwException(writtenBytes); } } return writtenBytes; } /** * {@inheritDoc} */ @Override protected int transferFile(AprSession session, FileRegion region, int length) throws Exception { if (region.getFilename() == null) { throw new UnsupportedOperationException(); } long fd = File.open(region.getFilename(), File.APR_FOPEN_READ | File.APR_FOPEN_SENDFILE_ENABLED | File.APR_FOPEN_BINARY, 0, Socket.pool(session.getDescriptor())); long numWritten = Socket.sendfilen(session.getDescriptor(), fd, region.getPosition(), length, 0); File.close(fd); if (numWritten < 0) { if (numWritten == -Status.EAGAIN) { return 0; } throw new IOException(org.apache.tomcat.jni.Error.strerror((int) -numWritten) + " (code: " + numWritten + ")"); } return (int) numWritten; } private void throwException(int code) throws IOException { throw new IOException(org.apache.tomcat.jni.Error.strerror(-code) + " (code: " + code + ")"); } /** * {@inheritDoc} */ @Override protected void registerNewSelector() { // Do nothing } /** * {@inheritDoc} */ @Override protected boolean isBrokenConnection() throws IOException { // Here, we assume that this is the case. return true; } }././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/socket/apr/AprSocketAcceptor.javamina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/socket/apr/AprSocket0000644000175000017500000003006512032276013032656 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.apr; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.Iterator; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.polling.AbstractPollingIoAcceptor; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.IoService; import org.apache.mina.core.service.SimpleIoProcessorPool; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.transport.socket.DefaultSocketSessionConfig; import org.apache.mina.transport.socket.SocketAcceptor; import org.apache.mina.transport.socket.SocketSessionConfig; import org.apache.tomcat.jni.Address; import org.apache.tomcat.jni.Poll; import org.apache.tomcat.jni.Pool; import org.apache.tomcat.jni.Socket; import org.apache.tomcat.jni.Status; /** * {@link IoAcceptor} for APR based socket transport (TCP/IP). * * @author Apache MINA Project */ public final class AprSocketAcceptor extends AbstractPollingIoAcceptor implements SocketAcceptor { /** * This constant is deduced from the APR code. It is used when the timeout * has expired while doing a poll() operation. */ private static final int APR_TIMEUP_ERROR = -120001; private static final int POLLSET_SIZE = 1024; private final Object wakeupLock = new Object(); private volatile long wakeupSocket; private volatile boolean toBeWakenUp; private volatile long pool; private volatile long pollset; // socket poller private final long[] polledSockets = new long[POLLSET_SIZE << 1]; private final Queue polledHandles = new ConcurrentLinkedQueue(); /** * Constructor for {@link AprSocketAcceptor} using default parameters (multiple thread model). */ public AprSocketAcceptor() { super(new DefaultSocketSessionConfig(), AprIoProcessor.class); ((DefaultSocketSessionConfig) getSessionConfig()).init(this); } /** * Constructor for {@link AprSocketAcceptor} using default parameters, and * given number of {@link AprIoProcessor} for multithreading I/O operations. * * @param processorCount the number of processor to create and place in a * {@link SimpleIoProcessorPool} */ public AprSocketAcceptor(int processorCount) { super(new DefaultSocketSessionConfig(), AprIoProcessor.class, processorCount); ((DefaultSocketSessionConfig) getSessionConfig()).init(this); } /** * Constructor for {@link AprSocketAcceptor} with default configuration but a * specific {@link AprIoProcessor}, useful for sharing the same processor over multiple * {@link IoService} of the same type. * @param processor the processor to use for managing I/O events */ public AprSocketAcceptor(IoProcessor processor) { super(new DefaultSocketSessionConfig(), processor); ((DefaultSocketSessionConfig) getSessionConfig()).init(this); } /** * Constructor for {@link AprSocketAcceptor} with a given {@link Executor} for handling * connection events and a given {@link AprIoProcessor} for handling I/O events, useful for * sharing the same processor and executor over multiple {@link IoService} of the same type. * @param executor the executor for connection * @param processor the processor for I/O operations */ public AprSocketAcceptor(Executor executor, IoProcessor processor) { super(new DefaultSocketSessionConfig(), executor, processor); ((DefaultSocketSessionConfig) getSessionConfig()).init(this); } /** * {@inheritDoc} */ @Override protected AprSession accept(IoProcessor processor, Long handle) throws Exception { long s = Socket.accept(handle); boolean success = false; try { AprSession result = new AprSocketSession(this, processor, s); success = true; return result; } finally { if (!success) { Socket.close(s); } } } /** * {@inheritDoc} */ @Override protected Long open(SocketAddress localAddress) throws Exception { InetSocketAddress la = (InetSocketAddress) localAddress; long handle = Socket.create(Socket.APR_INET, Socket.SOCK_STREAM, Socket.APR_PROTO_TCP, pool); boolean success = false; try { int result = Socket.optSet(handle, Socket.APR_SO_NONBLOCK, 1); if (result != Status.APR_SUCCESS) { throwException(result); } result = Socket.timeoutSet(handle, 0); if (result != Status.APR_SUCCESS) { throwException(result); } // Configure the server socket, result = Socket.optSet(handle, Socket.APR_SO_REUSEADDR, isReuseAddress() ? 1 : 0); if (result != Status.APR_SUCCESS) { throwException(result); } result = Socket.optSet(handle, Socket.APR_SO_RCVBUF, getSessionConfig().getReceiveBufferSize()); if (result != Status.APR_SUCCESS) { throwException(result); } // and bind. long sa; if (la != null) { if (la.getAddress() == null) { sa = Address.info(Address.APR_ANYADDR, Socket.APR_INET, la.getPort(), 0, pool); } else { sa = Address.info(la.getAddress().getHostAddress(), Socket.APR_INET, la.getPort(), 0, pool); } } else { sa = Address.info(Address.APR_ANYADDR, Socket.APR_INET, 0, 0, pool); } result = Socket.bind(handle, sa); if (result != Status.APR_SUCCESS) { throwException(result); } result = Socket.listen(handle, getBacklog()); if (result != Status.APR_SUCCESS) { throwException(result); } result = Poll.add(pollset, handle, Poll.APR_POLLIN); if (result != Status.APR_SUCCESS) { throwException(result); } success = true; } finally { if (!success) { close(handle); } } return handle; } /** * {@inheritDoc} */ @Override protected void init() throws Exception { // initialize a memory pool for APR functions pool = Pool.create(AprLibrary.getInstance().getRootPool()); wakeupSocket = Socket.create(Socket.APR_INET, Socket.SOCK_DGRAM, Socket.APR_PROTO_UDP, pool); pollset = Poll.create(POLLSET_SIZE, pool, Poll.APR_POLLSET_THREADSAFE, Long.MAX_VALUE); if (pollset <= 0) { pollset = Poll.create(62, pool, Poll.APR_POLLSET_THREADSAFE, Long.MAX_VALUE); } if (pollset <= 0) { if (Status.APR_STATUS_IS_ENOTIMPL(-(int) pollset)) { throw new RuntimeIoException("Thread-safe pollset is not supported in this platform."); } } } /** * {@inheritDoc} */ @Override protected void destroy() throws Exception { if (wakeupSocket > 0) { Socket.close(wakeupSocket); } if (pollset > 0) { Poll.destroy(pollset); } if (pool > 0) { Pool.destroy(pool); } } /** * {@inheritDoc} */ @Override protected SocketAddress localAddress(Long handle) throws Exception { long la = Address.get(Socket.APR_LOCAL, handle); return new InetSocketAddress(Address.getip(la), Address.getInfo(la).port); } /** * {@inheritDoc} */ @Override protected int select() throws Exception { int rv = Poll.poll(pollset, Integer.MAX_VALUE, polledSockets, false); if (rv <= 0) { // We have had an error. It can simply be that we have reached // the timeout (very unlikely, as we have set it to MAX_INTEGER) if (rv != APR_TIMEUP_ERROR) { // It's not a timeout being exceeded. Throw the error throwException(rv); } rv = Poll.maintain(pollset, polledSockets, true); if (rv > 0) { for (int i = 0; i < rv; i++) { Poll.add(pollset, polledSockets[i], Poll.APR_POLLIN); } } else if (rv < 0) { throwException(rv); } return 0; } else { rv <<= 1; if (!polledHandles.isEmpty()) { polledHandles.clear(); } for (int i = 0; i < rv; i++) { long flag = polledSockets[i]; long socket = polledSockets[++i]; if (socket == wakeupSocket) { synchronized (wakeupLock) { Poll.remove(pollset, wakeupSocket); toBeWakenUp = false; } continue; } if ((flag & Poll.APR_POLLIN) != 0) { polledHandles.add(socket); } } return polledHandles.size(); } } /** * {@inheritDoc} */ @Override protected Iterator selectedHandles() { return polledHandles.iterator(); } /** * {@inheritDoc} */ @Override protected void close(Long handle) throws Exception { Poll.remove(pollset, handle); int result = Socket.close(handle); if (result != Status.APR_SUCCESS) { throwException(result); } } /** * {@inheritDoc} */ @Override protected void wakeup() { if (toBeWakenUp) { return; } // Add a dummy socket to the pollset. synchronized (wakeupLock) { toBeWakenUp = true; Poll.add(pollset, wakeupSocket, Poll.APR_POLLOUT); } } /** * {@inheritDoc} */ @Override public InetSocketAddress getLocalAddress() { return (InetSocketAddress) super.getLocalAddress(); } /** * {@inheritDoc} */ @Override public InetSocketAddress getDefaultLocalAddress() { return (InetSocketAddress) super.getDefaultLocalAddress(); } /** * {@inheritDoc} */ public void setDefaultLocalAddress(InetSocketAddress localAddress) { super.setDefaultLocalAddress(localAddress); } /** * {@inheritDoc} */ public TransportMetadata getTransportMetadata() { return AprSocketSession.METADATA; } /** * {@inheritDoc} */ @Override public SocketSessionConfig getSessionConfig() { return (SocketSessionConfig) super.getSessionConfig(); } /** * Convert an APR code into an Exception with the corresponding message * @param code error number * @throws IOException the generated exception */ private void throwException(int code) throws IOException { throw new IOException(org.apache.tomcat.jni.Error.strerror(-code) + " (code: " + code + ")"); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/socket/apr/AprDatagramSession.javamina2-2.0.7.orig/src/mina-transport-apr/src/main/java/org/apache/mina/transport/socket/apr/AprDatagr0000644000175000017500000001136212032276013032627 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.apr; import java.net.InetSocketAddress; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.service.DefaultTransportMetadata; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.IoService; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.core.session.IoSession; import org.apache.mina.transport.socket.AbstractDatagramSessionConfig; import org.apache.mina.transport.socket.DatagramSessionConfig; import org.apache.tomcat.jni.Socket; /** * An {@link IoSession} for APR UDP datagram based session. * It's implementing the usual common features for {@link DatagramSessionConfig}. * * @author Apache MINA Project */ class AprDatagramSession extends AprSession { static final TransportMetadata METADATA = new DefaultTransportMetadata("apr", "datagram", true, false, InetSocketAddress.class, DatagramSessionConfig.class, IoBuffer.class); /** * Create an instance of {@link AprDatagramSession}. * * {@inheritDoc} */ AprDatagramSession(IoService service, IoProcessor processor, long descriptor, InetSocketAddress remoteAddress) throws Exception { super(service, processor, descriptor, remoteAddress); config = new SessionConfigImpl(); this.config.setAll(service.getSessionConfig()); } /** * {@inheritDoc} */ public DatagramSessionConfig getConfig() { return (DatagramSessionConfig) config; } /** * {@inheritDoc} */ public TransportMetadata getTransportMetadata() { return METADATA; } /** * The implementation for the {@link org.apache.mina.core.session.IoSessionConfig} related to APR UDP socket. * @author Apache MINA Project */ private class SessionConfigImpl extends AbstractDatagramSessionConfig { /** * {@inheritDoc} */ public boolean isReuseAddress() { try { return Socket.optGet(getDescriptor(), Socket.APR_SO_REUSEADDR) == 1; } catch (Exception e) { throw new RuntimeIoException("Failed to get SO_REUSEADDR.", e); } } /** * {@inheritDoc} */ public void setReuseAddress(boolean on) { Socket.optSet(getDescriptor(), Socket.APR_SO_REUSEADDR, on ? 1 : 0); } /** * {@inheritDoc} */ public int getTrafficClass() { return 0; } /** * {@inheritDoc} */ public void setTrafficClass(int tc) { } /** * {@inheritDoc} */ public int getSendBufferSize() { try { return Socket.optGet(getDescriptor(), Socket.APR_SO_SNDBUF); } catch (Exception e) { throw new RuntimeException("APR Exception", e); } } /** * {@inheritDoc} */ public void setSendBufferSize(int size) { Socket.optSet(getDescriptor(), Socket.APR_SO_SNDBUF, size); } /** * {@inheritDoc} */ public int getReceiveBufferSize() { try { return Socket.optGet(getDescriptor(), Socket.APR_SO_RCVBUF); } catch (Exception e) { throw new RuntimeException("APR Exception", e); } } /** * {@inheritDoc} */ public void setReceiveBufferSize(int size) { Socket.optSet(getDescriptor(), Socket.APR_SO_RCVBUF, size); } /** * {@inheritDoc} */ public boolean isBroadcast() { return false; } /** * {@inheritDoc} */ public void setBroadcast(boolean broadcast) { } } } mina2-2.0.7.orig/src/mina-integration-xbean/0000755000175000017500000000000012162575507020156 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/pom.xml.releaseBackup0000644000175000017500000000777512033674301024245 0ustar ebourgebourg org.apache.mina mina-parent 2.0.7-SNAPSHOT 4.0.0 mina-integration-xbean Apache MINA XBean Integration This module generates an XML scheme file for the MINA Spring configuration namespace. This XSD is referenced by Spring configuration files using MINA components to have a much less verbose configuration. When used with the XBean application context loader the same old Spring ApplictionContext is generated from this more intuitive and terse configuration file. http://maven.apache.org ${project.groupId} mina-integration-beans ${project.version} bundle ${project.groupId} mina-core ${project.version} sources ${project.groupId} mina-core ${project.version} bundle org.springframework spring org.apache.xbean xbean-spring org.apache.xbean maven-xbean-plugin http://mina.apache.org/config/1.0 target/xbean/${project.artifactId}.xsd mapping org.codehaus.mojo build-helper-maven-plugin attach-artifacts package attach-artifact ${basedir}/target/xbean/${project.artifactId}.xsd xsd ${basedir}/target/xbean/${project.artifactId}.xsd.html xsd.html mina2-2.0.7.orig/src/mina-integration-xbean/pom.xml0000644000175000017500000000776412033674306021503 0ustar ebourgebourg org.apache.mina mina-parent 2.0.7 4.0.0 mina-integration-xbean Apache MINA XBean Integration This module generates an XML scheme file for the MINA Spring configuration namespace. This XSD is referenced by Spring configuration files using MINA components to have a much less verbose configuration. When used with the XBean application context loader the same old Spring ApplictionContext is generated from this more intuitive and terse configuration file. http://maven.apache.org ${project.groupId} mina-integration-beans ${project.version} bundle ${project.groupId} mina-core ${project.version} sources ${project.groupId} mina-core ${project.version} bundle org.springframework spring org.apache.xbean xbean-spring org.apache.xbean maven-xbean-plugin http://mina.apache.org/config/1.0 target/xbean/${project.artifactId}.xsd mapping org.codehaus.mojo build-helper-maven-plugin attach-artifacts package attach-artifact ${basedir}/target/xbean/${project.artifactId}.xsd xsd ${basedir}/target/xbean/${project.artifactId}.xsd.html xsd.html mina2-2.0.7.orig/src/mina-integration-xbean/src/0000755000175000017500000000000012032276013020727 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/test/0000755000175000017500000000000012032276013021706 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/test/java/0000755000175000017500000000000012032276013022627 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/test/java/org/0000755000175000017500000000000012032276013023416 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/test/java/org/apache/0000755000175000017500000000000012032276013024637 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/test/java/org/apache/mina/0000755000175000017500000000000012032276013025563 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/test/java/org/apache/mina/integration/0000755000175000017500000000000012032276013030106 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/test/java/org/apache/mina/integration/xbean/0000755000175000017500000000000012162575507031221 5ustar ebourgebourg././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-xbean/src/test/java/org/apache/mina/integration/xbean/SpringXBeanTest.javamina2-2.0.7.orig/src/mina-integration-xbean/src/test/java/org/apache/mina/integration/xbean/SpringXB0000644000175000017500000001155412032276013032630 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.mina.integration.xbean; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import org.apache.mina.transport.socket.nio.NioDatagramAcceptor; import org.apache.xbean.spring.context.FileSystemXmlApplicationContext; import org.junit.Test; import org.springframework.context.ApplicationContext; import java.io.File; import java.net.InetSocketAddress; import java.net.URL; /** * TODO : Add documentation * @author Apache MINA Project */ public class SpringXBeanTest { /** * Checks to see we can easily configure a NIO based DatagramAcceptor * using XBean-Spring. Tests various configuration settings for the * NIO based DatagramAcceptor. */ @Test public void testNioDatagramAcceptor() throws Exception { ClassLoader classLoader = this.getClass().getClassLoader(); URL configURL = classLoader.getResource("org/apache/mina/integration/xbean/datagramAcceptor.xml"); File configF = new File(configURL.toURI()); ApplicationContext factory = new FileSystemXmlApplicationContext(configF.toURI().toURL().toString()); // test default without any properties NioDatagramAcceptor acceptor0 = (NioDatagramAcceptor) factory.getBean("datagramAcceptor0"); assertNotNull("acceptor0 should not be null", acceptor0); assertTrue( "Default constructor for NioDatagramAcceptor should have true value for closeOnDeactivation property", acceptor0.isCloseOnDeactivation()); // test setting the port and IP for the acceptor NioDatagramAcceptor acceptor1 = (NioDatagramAcceptor) factory.getBean("datagramAcceptor1"); assertNotNull("acceptor1 should not be null", acceptor1); assertEquals("192.168.0.1", acceptor1.getDefaultLocalAddress().getAddress().getHostAddress()); assertEquals(110, acceptor1.getDefaultLocalAddress().getPort()); // test creating with executor and some primitive properties NioDatagramAcceptor acceptor2 = (NioDatagramAcceptor) factory.getBean("datagramAcceptor2"); assertNotNull(acceptor2); assertFalse(acceptor2.isCloseOnDeactivation()); assertFalse("NioDatagramAcceptor should have false value for closeOnDeactivation property", acceptor2.isCloseOnDeactivation()); // test creating with multiple addresses NioDatagramAcceptor acceptor3 = (NioDatagramAcceptor) factory.getBean("datagramAcceptor3"); assertNotNull(acceptor3); assertEquals(3, acceptor3.getDefaultLocalAddresses().size()); InetSocketAddress address1 = (InetSocketAddress) acceptor3.getDefaultLocalAddresses().get(0); assertEquals("192.168.0.1", address1.getAddress().getHostAddress()); assertEquals(10001, address1.getPort()); InetSocketAddress address2 = (InetSocketAddress) acceptor3.getDefaultLocalAddresses().get(1); assertEquals("192.168.0.2", address2.getAddress().getHostAddress()); assertEquals(10002, address2.getPort()); InetSocketAddress address3 = (InetSocketAddress) acceptor3.getDefaultLocalAddresses().get(2); assertEquals("192.168.0.3", address3.getAddress().getHostAddress()); assertEquals(10003, address3.getPort()); // test with multiple default addresses // NioDatagramAcceptor acceptor3 = ( NioDatagramAcceptor ) factory.getBean( "datagramAcceptor3" ); // assertNotNull( acceptor3 ); // assertEquals( 3, acceptor3.getDefaultLocalAddresses().size() ); // // SocketAddress address0 = acceptor3.getDefaultLocalAddresses().get( 0 ); // assertNotNull( address0 ); // // SocketAddress address1 = acceptor3.getDefaultLocalAddresses().get( 1 ); // assertNotNull( address1 ); // // SocketAddress address2 = acceptor3.getDefaultLocalAddresses().get( 2 ); // assertNotNull( address2 ); } } mina2-2.0.7.orig/src/mina-integration-xbean/src/test/resources/0000755000175000017500000000000012032276013023720 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/test/resources/org/0000755000175000017500000000000012032276013024507 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/test/resources/org/apache/0000755000175000017500000000000012032276013025730 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/test/resources/org/apache/mina/0000755000175000017500000000000012032276013026654 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/test/resources/org/apache/mina/integration/0000755000175000017500000000000012032276013031177 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/test/resources/org/apache/mina/integration/xbean/0000755000175000017500000000000012162575507032312 5ustar ebourgebourg././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-xbean/src/test/resources/org/apache/mina/integration/xbean/datagramAcceptor.xmlmina2-2.0.7.orig/src/mina-integration-xbean/src/test/resources/org/apache/mina/integration/xbean/dat0000644000175000017500000000417312032276013032774 0ustar ebourgebourg 192.168.0.1:10001 192.168.0.2:10002 192.168.0.3:10003 mina2-2.0.7.orig/src/mina-integration-xbean/src/main/0000755000175000017500000000000012032276013021653 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/main/java/0000755000175000017500000000000012032276013022574 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/main/java/org/0000755000175000017500000000000012032276013023363 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/main/java/org/apache/0000755000175000017500000000000012032276013024604 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/main/java/org/apache/mina/0000755000175000017500000000000012032276013025530 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/main/java/org/apache/mina/integration/0000755000175000017500000000000012032276013030053 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-xbean/src/main/java/org/apache/mina/integration/xbean/0000755000175000017500000000000012162575507031166 5ustar ebourgebourg././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-xbean/src/main/java/org/apache/mina/integration/xbean/MinaPropertyEditorRegistrar.javamina2-2.0.7.orig/src/mina-integration-xbean/src/main/java/org/apache/mina/integration/xbean/MinaProp0000644000175000017500000000610212032276013032617 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.xbean; import java.beans.PropertyEditor; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import org.apache.mina.integration.beans.InetAddressEditor; import org.apache.mina.integration.beans.InetSocketAddressEditor; import org.apache.mina.integration.beans.VmPipeAddressEditor; import org.apache.mina.transport.vmpipe.VmPipeAddress; import org.springframework.beans.PropertyEditorRegistrar; import org.springframework.beans.PropertyEditorRegistry; /** * A custom Spring {@link PropertyEditorRegistrar} implementation which * registers by default all the {@link PropertyEditor} implementations in the * MINA Integration Beans module. * * @author Apache MINA Project */ public class MinaPropertyEditorRegistrar implements PropertyEditorRegistrar { /** * Registers custom {@link PropertyEditor}s in the MINA Integration Beans * module. * * Note: I did not know just how useful the rest of the property editors * were or if they were redundant and replicated existing functionality of * default editors packaged into Spring. So presently we're only * registering editors for the following classes which are not found in * Spring: * *
    *
  • java.net.InetAddress
  • *
  • java.net.InetSocketAddress
  • *
  • org.apache.mina.core.session.TrafficMask
  • *
  • org.apache.mina.integration.beans.VmPipeAddressEditor
  • *
* * @see org.springframework.beans.PropertyEditorRegistrar# * registerCustomEditors(org.springframework.beans.PropertyEditorRegistry) */ public void registerCustomEditors(PropertyEditorRegistry registry) { // it is expected that new PropertyEditor instances are created registry.registerCustomEditor(InetAddress.class, new InetAddressEditor()); registry.registerCustomEditor(InetSocketAddress.class, new InetSocketAddressEditor()); registry.registerCustomEditor(SocketAddress.class, new InetSocketAddressEditor()); registry.registerCustomEditor(VmPipeAddress.class, new VmPipeAddressEditor()); // registry.registerCustomEditor( Boolean.class, new BooleanEditor() ); } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-xbean/src/main/java/org/apache/mina/integration/xbean/SocketAddressFactory.javamina2-2.0.7.orig/src/mina-integration-xbean/src/main/java/org/apache/mina/integration/xbean/SocketAd0000644000175000017500000000300712032276013032570 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.xbean; import java.net.SocketAddress; import org.apache.mina.integration.beans.InetSocketAddressEditor; /** * Workaround for dealing with inability to annotate java docs of JDK * socket address classes. * * @author Apache MINA Project * @org.apache.xbean.XBean element="socketAddress" contentProperty="value" */ public class SocketAddressFactory { /** * @org.apache.xbean.FactoryMethod */ public static SocketAddress create(String value) { InetSocketAddressEditor editor = new InetSocketAddressEditor(); editor.setAsText(value); return (SocketAddress) editor.getValue(); } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-xbean/src/main/java/org/apache/mina/integration/xbean/StandardThreadPool.javamina2-2.0.7.orig/src/mina-integration-xbean/src/main/java/org/apache/mina/integration/xbean/Standard0000644000175000017500000000351612032276013032640 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.mina.integration.xbean; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * @org.apache.xbean.XBean * @author Apache MINA Project */ public class StandardThreadPool implements Executor { private final ExecutorService delegate; public StandardThreadPool(int maxThreads) { delegate = Executors.newFixedThreadPool(maxThreads); } public void execute(Runnable command) { delegate.execute(command); } /** * TODO wont this hang if some tasks are sufficiently badly behaved? * @org.apache.xbean.DestroyMethod */ public void stop() { delegate.shutdown(); for (;;) { try { if (delegate.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS)) { break; } } catch (InterruptedException e) { //ignore } } } } mina2-2.0.7.orig/src/mina-integration-jmx/0000755000175000017500000000000012162575507017657 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-jmx/pom.xml.releaseBackup0000644000175000017500000000433212033674301023730 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7-SNAPSHOT mina-integration-jmx Apache MINA JMX Integration bundle ${project.groupId}.integration.jmx ${project.groupId}.integration.jmx ${project.groupId} mina-core ${project.version} bundle ${project.groupId} mina-integration-beans ${project.version} bundle ${project.groupId} mina-integration-ognl ${project.version} bundle ognl ognl mina2-2.0.7.orig/src/mina-integration-jmx/pom.xml0000644000175000017500000000432112033674306021166 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7 mina-integration-jmx Apache MINA JMX Integration bundle ${project.groupId}.integration.jmx ${project.groupId}.integration.jmx ${project.groupId} mina-core ${project.version} bundle ${project.groupId} mina-integration-beans ${project.version} bundle ${project.groupId} mina-integration-ognl ${project.version} bundle ognl ognl mina2-2.0.7.orig/src/mina-integration-jmx/src/0000755000175000017500000000000012032276013020430 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-jmx/src/main/0000755000175000017500000000000012032276014021355 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-jmx/src/main/java/0000755000175000017500000000000012032276013022275 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-jmx/src/main/java/org/0000755000175000017500000000000012032276013023064 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-jmx/src/main/java/org/apache/0000755000175000017500000000000012032276013024305 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-jmx/src/main/java/org/apache/mina/0000755000175000017500000000000012032276013025231 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-jmx/src/main/java/org/apache/mina/integration/0000755000175000017500000000000012032276013027554 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-jmx/src/main/java/org/apache/mina/integration/jmx/0000755000175000017500000000000012162575507030370 5ustar ebourgebourg././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-jmx/src/main/java/org/apache/mina/integration/jmx/IoServiceMBean.javamina2-2.0.7.orig/src/mina-integration-jmx/src/main/java/org/apache/mina/integration/jmx/IoServiceMBe0000644000175000017500000001264612032276014032563 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.mina.integration.jmx; import java.net.SocketAddress; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import javax.management.MBeanOperationInfo; import javax.management.MBeanParameterInfo; import javax.management.ObjectName; import javax.management.modelmbean.ModelMBeanOperationInfo; import ognl.Ognl; import org.apache.mina.core.service.IoService; import org.apache.mina.core.session.IoSession; import org.apache.mina.integration.ognl.IoSessionFinder; /** * A JMX MBean wrapper for an {@link IoSession}. * * @author Apache MINA Project */ public class IoServiceMBean extends ObjectMBean { static String getSessionIdAsString(long l) { // ID in MINA is a unsigned 32-bit integer. String id = Long.toHexString(l).toUpperCase(); while (id.length() < 8) { id = '0' + id; // padding } id = "0x" + id; return id; } public IoServiceMBean(IoService source) { super(source); } @Override protected Object invoke0(String name, Object[] params, String[] signature) throws Exception { if (name.equals("findSessions")) { IoSessionFinder finder = new IoSessionFinder((String) params[0]); return finder.find(getSource().getManagedSessions().values()); } if (name.equals("findAndRegisterSessions")) { IoSessionFinder finder = new IoSessionFinder((String) params[0]); Set registeredSessions = new LinkedHashSet(); for (IoSession s : finder.find(getSource().getManagedSessions().values())) { try { getServer().registerMBean( new IoSessionMBean(s), new ObjectName(getName().getDomain() + ":type=session,name=" + getSessionIdAsString(s.getId()))); registeredSessions.add(s); } catch (Exception e) { LOGGER.warn("Failed to register a session as a MBean: " + s, e); } } return registeredSessions; } if (name.equals("findAndProcessSessions")) { IoSessionFinder finder = new IoSessionFinder((String) params[0]); String command = (String) params[1]; Object expr = Ognl.parseExpression(command); Set matches = finder.find(getSource().getManagedSessions().values()); for (IoSession s : matches) { try { Ognl.getValue(expr, s); } catch (Exception e) { LOGGER.warn("Failed to execute '" + command + "' for: " + s, e); } } return matches; } return super.invoke0(name, params, signature); } @Override protected void addExtraOperations(List operations) { operations.add(new ModelMBeanOperationInfo("findSessions", "findSessions", new MBeanParameterInfo[] { new MBeanParameterInfo("ognlQuery", String.class.getName(), "a boolean OGNL expression") }, Set.class.getName(), MBeanOperationInfo.INFO)); operations.add(new ModelMBeanOperationInfo("findAndRegisterSessions", "findAndRegisterSessions", new MBeanParameterInfo[] { new MBeanParameterInfo("ognlQuery", String.class.getName(), "a boolean OGNL expression") }, Set.class.getName(), MBeanOperationInfo.ACTION_INFO)); operations.add(new ModelMBeanOperationInfo("findAndProcessSessions", "findAndProcessSessions", new MBeanParameterInfo[] { new MBeanParameterInfo("ognlQuery", String.class.getName(), "a boolean OGNL expression"), new MBeanParameterInfo("ognlCommand", String.class.getName(), "an OGNL expression that modifies the state of the sessions in the match result") }, Set.class.getName(), MBeanOperationInfo.ACTION_INFO)); } @Override protected boolean isOperation(String methodName, Class[] paramTypes) { // Ignore some IoServide methods. if (methodName.matches("(newSession|broadcast|(add|remove)Listener)")) { return false; } if ((methodName.equals("bind") || methodName.equals("unbind")) && (paramTypes.length > 1 || paramTypes.length == 1 && !SocketAddress.class.isAssignableFrom(paramTypes[0]))) { return false; } return super.isOperation(methodName, paramTypes); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-jmx/src/main/java/org/apache/mina/integration/jmx/IoSessionMBean.javamina2-2.0.7.orig/src/mina-integration-jmx/src/main/java/org/apache/mina/integration/jmx/IoSessionMBe0000644000175000017500000001624412032276014032604 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.mina.integration.jmx; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.management.MBeanException; import javax.management.MBeanParameterInfo; import javax.management.ObjectName; import javax.management.modelmbean.ModelMBeanAttributeInfo; import javax.management.modelmbean.ModelMBeanOperationInfo; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.session.IoSession; /** * A JMX MBean wrapper for an {@link IoSession}. * * @author Apache MINA Project */ public class IoSessionMBean extends ObjectMBean { public IoSessionMBean(IoSession source) { super(source); } @Override protected Object getAttribute0(String fqan) throws Exception { if (fqan.equals("attributes")) { Map answer = new LinkedHashMap(); for (Object key : getSource().getAttributeKeys()) { answer.put(String.valueOf(key), String.valueOf(getSource().getAttribute(key))); } return answer; } return super.getAttribute0(fqan); } @Override protected Object invoke0(String name, Object[] params, String[] signature) throws Exception { if (name.equals("addFilterFirst")) { String filterName = (String) params[0]; ObjectName filterRef = (ObjectName) params[1]; IoFilter filter = getFilter(filterRef); getSource().getFilterChain().addFirst(filterName, filter); return null; } if (name.equals("addFilterLast")) { String filterName = (String) params[0]; ObjectName filterRef = (ObjectName) params[1]; IoFilter filter = getFilter(filterRef); getSource().getFilterChain().addLast(filterName, filter); return null; } if (name.equals("addFilterBefore")) { String filterBaseName = (String) params[0]; String filterName = (String) params[1]; ObjectName filterRef = (ObjectName) params[2]; IoFilter filter = getFilter(filterRef); getSource().getFilterChain().addBefore(filterBaseName, filterName, filter); return null; } if (name.equals("addFilterAfter")) { String filterBaseName = (String) params[0]; String filterName = (String) params[1]; ObjectName filterRef = (ObjectName) params[2]; IoFilter filter = getFilter(filterRef); getSource().getFilterChain().addAfter(filterBaseName, filterName, filter); return null; } if (name.equals("removeFilter")) { String filterName = (String) params[0]; getSource().getFilterChain().remove(filterName); return null; } return super.invoke0(name, params, signature); } private IoFilter getFilter(ObjectName filterRef) throws MBeanException { Object object = ObjectMBean.getSource(filterRef); if (object == null) { throw new MBeanException(new IllegalArgumentException("MBean not found: " + filterRef)); } if (!(object instanceof IoFilter)) { throw new MBeanException(new IllegalArgumentException("MBean '" + filterRef + "' is not an IoFilter.")); } return (IoFilter) object; } @Override protected void addExtraAttributes(List attributes) { attributes .add(new ModelMBeanAttributeInfo("attributes", Map.class.getName(), "attributes", true, false, false)); } @Override protected void addExtraOperations(List operations) { operations.add(new ModelMBeanOperationInfo("addFilterFirst", "addFilterFirst", new MBeanParameterInfo[] { new MBeanParameterInfo("name", String.class.getName(), "the new filter name"), new MBeanParameterInfo("filter", ObjectName.class.getName(), "the ObjectName reference to the filter") }, void.class.getName(), ModelMBeanOperationInfo.ACTION)); operations.add(new ModelMBeanOperationInfo("addFilterLast", "addFilterLast", new MBeanParameterInfo[] { new MBeanParameterInfo("name", String.class.getName(), "the new filter name"), new MBeanParameterInfo("filter", ObjectName.class.getName(), "the ObjectName reference to the filter") }, void.class.getName(), ModelMBeanOperationInfo.ACTION)); operations.add(new ModelMBeanOperationInfo("addFilterBefore", "addFilterBefore", new MBeanParameterInfo[] { new MBeanParameterInfo("baseName", String.class.getName(), "the next filter name"), new MBeanParameterInfo("name", String.class.getName(), "the new filter name"), new MBeanParameterInfo("filter", ObjectName.class.getName(), "the ObjectName reference to the filter") }, void.class.getName(), ModelMBeanOperationInfo.ACTION)); operations.add(new ModelMBeanOperationInfo("addFilterAfter", "addFilterAfter", new MBeanParameterInfo[] { new MBeanParameterInfo("baseName", String.class.getName(), "the previous filter name"), new MBeanParameterInfo("name", String.class.getName(), "the new filter name"), new MBeanParameterInfo("filter", ObjectName.class.getName(), "the ObjectName reference to the filter") }, void.class.getName(), ModelMBeanOperationInfo.ACTION)); operations.add(new ModelMBeanOperationInfo("removeFilter", "removeFilter", new MBeanParameterInfo[] { new MBeanParameterInfo("name", String.class.getName(), "the name of the filter to be removed"), }, void.class.getName(), ModelMBeanOperationInfo.ACTION)); } @Override protected boolean isOperation(String methodName, Class[] paramTypes) { // Ignore some IoSession methods. if (methodName.matches("(write|read|(remove|replace|contains)Attribute)")) { return false; } return super.isOperation(methodName, paramTypes); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-jmx/src/main/java/org/apache/mina/integration/jmx/ObjectMBean.javamina2-2.0.7.orig/src/mina-integration-jmx/src/main/java/org/apache/mina/integration/jmx/ObjectMBean.0000644000175000017500000010560612032276014032475 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.mina.integration.jmx; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.beans.PropertyEditor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.SocketAddress; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadPoolExecutor; import javax.management.Attribute; import javax.management.AttributeChangeNotification; import javax.management.AttributeList; import javax.management.AttributeNotFoundException; import javax.management.InstanceNotFoundException; import javax.management.ListenerNotFoundException; import javax.management.MBeanException; import javax.management.MBeanInfo; import javax.management.MBeanNotificationInfo; import javax.management.MBeanParameterInfo; import javax.management.MBeanRegistration; import javax.management.MBeanServer; import javax.management.Notification; import javax.management.NotificationFilter; import javax.management.NotificationListener; import javax.management.ObjectName; import javax.management.ReflectionException; import javax.management.RuntimeOperationsException; import javax.management.modelmbean.InvalidTargetObjectTypeException; import javax.management.modelmbean.ModelMBean; import javax.management.modelmbean.ModelMBeanAttributeInfo; import javax.management.modelmbean.ModelMBeanConstructorInfo; import javax.management.modelmbean.ModelMBeanInfo; import javax.management.modelmbean.ModelMBeanInfoSupport; import javax.management.modelmbean.ModelMBeanNotificationInfo; import javax.management.modelmbean.ModelMBeanOperationInfo; import ognl.ExpressionSyntaxException; import ognl.InappropriateExpressionException; import ognl.NoSuchPropertyException; import ognl.Ognl; import ognl.OgnlContext; import ognl.OgnlException; import ognl.OgnlRuntime; import ognl.TypeConverter; import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.filterchain.IoFilterChainBuilder; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoService; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionDataStructureFactory; import org.apache.mina.filter.executor.ExecutorFilter; import org.apache.mina.integration.beans.CollectionEditor; import org.apache.mina.integration.beans.ListEditor; import org.apache.mina.integration.beans.MapEditor; import org.apache.mina.integration.beans.PropertyEditorFactory; import org.apache.mina.integration.beans.SetEditor; import org.apache.mina.integration.ognl.IoFilterPropertyAccessor; import org.apache.mina.integration.ognl.IoServicePropertyAccessor; import org.apache.mina.integration.ognl.IoSessionPropertyAccessor; import org.apache.mina.integration.ognl.PropertyTypeConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A {@link ModelMBean} wrapper implementation for a POJO. * * @author Apache MINA Project * * @param the type of the managed object */ public class ObjectMBean implements ModelMBean, MBeanRegistration { private static final Map sources = new ConcurrentHashMap(); public static Object getSource(ObjectName oname) { return sources.get(oname); } static { OgnlRuntime.setPropertyAccessor(IoService.class, new IoServicePropertyAccessor()); OgnlRuntime.setPropertyAccessor(IoSession.class, new IoSessionPropertyAccessor()); OgnlRuntime.setPropertyAccessor(IoFilter.class, new IoFilterPropertyAccessor()); } protected final static Logger LOGGER = LoggerFactory.getLogger(ObjectMBean.class); private final T source; private final TransportMetadata transportMetadata; private final MBeanInfo info; private final Map propertyDescriptors = new HashMap(); private final TypeConverter typeConverter = new OgnlTypeConverter(); private volatile MBeanServer server; private volatile ObjectName name; /** * Creates a new instance with the specified POJO. */ public ObjectMBean(T source) { if (source == null) { throw new IllegalArgumentException("source"); } this.source = source; if (source instanceof IoService) { transportMetadata = ((IoService) source).getTransportMetadata(); } else if (source instanceof IoSession) { transportMetadata = ((IoSession) source).getTransportMetadata(); } else { transportMetadata = null; } this.info = createModelMBeanInfo(source); } public final Object getAttribute(String fqan) throws AttributeNotFoundException, MBeanException, ReflectionException { try { return convertValue(source.getClass(), fqan, getAttribute0(fqan), false); } catch (AttributeNotFoundException e) { // Do nothing } catch (Throwable e) { throwMBeanException(e); } // Check if the attribute exist, if not throw an exception PropertyDescriptor pdesc = propertyDescriptors.get(fqan); if (pdesc == null) { throwMBeanException(new IllegalArgumentException("Unknown attribute: " + fqan)); } try { Object parent = getParent(fqan); boolean writable = isWritable(source.getClass(), pdesc); return convertValue(parent.getClass(), getLeafAttributeName(fqan), getAttribute(source, fqan, pdesc.getPropertyType()), writable); } catch (Throwable e) { throwMBeanException(e); } throw new IllegalStateException(); } public final void setAttribute(Attribute attribute) throws AttributeNotFoundException, MBeanException, ReflectionException { String aname = attribute.getName(); Object avalue = attribute.getValue(); try { setAttribute0(aname, avalue); } catch (AttributeNotFoundException e) { // Do nothing } catch (Throwable e) { throwMBeanException(e); } PropertyDescriptor pdesc = propertyDescriptors.get(aname); if (pdesc == null) { throwMBeanException(new IllegalArgumentException("Unknown attribute: " + aname)); } try { PropertyEditor e = getPropertyEditor(getParent(aname).getClass(), pdesc.getName(), pdesc.getPropertyType()); e.setAsText((String) avalue); OgnlContext ctx = (OgnlContext) Ognl.createDefaultContext(source); ctx.setTypeConverter(typeConverter); Ognl.setValue(aname, ctx, source, e.getValue()); } catch (Throwable e) { throwMBeanException(e); } } public final Object invoke(String name, Object params[], String signature[]) throws MBeanException, ReflectionException { // Handle synthetic operations first. if (name.equals("unregisterMBean")) { try { server.unregisterMBean(this.name); return null; } catch (InstanceNotFoundException e) { throwMBeanException(e); } } try { return convertValue(null, null, invoke0(name, params, signature), false); } catch (NoSuchMethodException e) { // Do nothing } catch (Throwable e) { throwMBeanException(e); } // And then try reflection. Class[] paramTypes = new Class[signature.length]; for (int i = 0; i < paramTypes.length; i++) { try { paramTypes[i] = getAttributeClass(signature[i]); } catch (ClassNotFoundException e) { throwMBeanException(e); } PropertyEditor e = getPropertyEditor(source.getClass(), "p" + i, paramTypes[i]); if (e == null) { throwMBeanException(new RuntimeException("Conversion failure: " + params[i])); } e.setValue(params[i]); params[i] = e.getAsText(); } try { // Find the right method. for (Method m : source.getClass().getMethods()) { if (!m.getName().equalsIgnoreCase(name)) { continue; } Class[] methodParamTypes = m.getParameterTypes(); if (methodParamTypes.length != params.length) { continue; } Object[] convertedParams = new Object[params.length]; for (int i = 0; i < params.length; i++) { if (Iterable.class.isAssignableFrom(methodParamTypes[i])) { // Generics are not supported. convertedParams = null; break; } PropertyEditor e = getPropertyEditor(source.getClass(), "p" + i, methodParamTypes[i]); if (e == null) { convertedParams = null; break; } e.setAsText((String) params[i]); convertedParams[i] = e.getValue(); } if (convertedParams == null) { continue; } return convertValue(m.getReturnType(), "returnValue", m.invoke(source, convertedParams), false); } // No methods matched. throw new IllegalArgumentException("Failed to find a matching operation: " + name); } catch (Throwable e) { throwMBeanException(e); } throw new IllegalStateException(); } public final T getSource() { return source; } public final MBeanServer getServer() { return server; } public final ObjectName getName() { return name; } public final MBeanInfo getMBeanInfo() { return info; } public final AttributeList getAttributes(String names[]) { AttributeList answer = new AttributeList(); for (int i = 0; i < names.length; i++) { try { answer.add(new Attribute(names[i], getAttribute(names[i]))); } catch (Exception e) { // Ignore. } } return answer; } public final AttributeList setAttributes(AttributeList attributes) { // Prepare and return our response, eating all exceptions String names[] = new String[attributes.size()]; int n = 0; Iterator items = attributes.iterator(); while (items.hasNext()) { Attribute item = (Attribute) items.next(); names[n++] = item.getName(); try { setAttribute(item); } catch (Exception e) { // Ignore all exceptions } } return getAttributes(names); } public final void setManagedResource(Object resource, String type) throws InstanceNotFoundException, InvalidTargetObjectTypeException, MBeanException { throw new RuntimeOperationsException(new UnsupportedOperationException()); } public final void setModelMBeanInfo(ModelMBeanInfo info) throws MBeanException { throw new RuntimeOperationsException(new UnsupportedOperationException()); } @Override public final String toString() { return (source == null ? "" : source.toString()); } public void addAttributeChangeNotificationListener(NotificationListener listener, String name, Object handback) { // Do nothing } public void removeAttributeChangeNotificationListener(NotificationListener listener, String name) throws ListenerNotFoundException { // Do nothing } public void sendAttributeChangeNotification(AttributeChangeNotification notification) throws MBeanException { throw new RuntimeOperationsException(new UnsupportedOperationException()); } public void sendAttributeChangeNotification(Attribute oldValue, Attribute newValue) throws MBeanException { throw new RuntimeOperationsException(new UnsupportedOperationException()); } public void sendNotification(Notification notification) throws MBeanException { throw new RuntimeOperationsException(new UnsupportedOperationException()); } public void sendNotification(String message) throws MBeanException { throw new RuntimeOperationsException(new UnsupportedOperationException()); } public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException { // Do nothing } public MBeanNotificationInfo[] getNotificationInfo() { return new MBeanNotificationInfo[0]; } public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { // Do nothing } public void load() throws InstanceNotFoundException, MBeanException, RuntimeOperationsException { throw new RuntimeOperationsException(new UnsupportedOperationException()); } public void store() throws InstanceNotFoundException, MBeanException, RuntimeOperationsException { throw new RuntimeOperationsException(new UnsupportedOperationException()); } public final ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { this.server = server; this.name = name; return name; } public final void postRegister(Boolean registrationDone) { if (registrationDone) { sources.put(name, source); } } public final void preDeregister() throws Exception { // Do nothing } public final void postDeregister() { sources.remove(name); this.server = null; this.name = null; } private MBeanInfo createModelMBeanInfo(T source) { String className = source.getClass().getName(); String description = ""; ModelMBeanConstructorInfo[] constructors = new ModelMBeanConstructorInfo[0]; ModelMBeanNotificationInfo[] notifications = new ModelMBeanNotificationInfo[0]; List attributes = new ArrayList(); List operations = new ArrayList(); addAttributes(attributes, source); addExtraAttributes(attributes); addOperations(operations, source); addExtraOperations(operations); operations.add(new ModelMBeanOperationInfo("unregisterMBean", "unregisterMBean", new MBeanParameterInfo[0], void.class.getName(), ModelMBeanOperationInfo.ACTION)); return new ModelMBeanInfoSupport(className, description, attributes.toArray(new ModelMBeanAttributeInfo[attributes.size()]), constructors, operations.toArray(new ModelMBeanOperationInfo[operations.size()]), notifications); } private void addAttributes(List attributes, Object object) { addAttributes(attributes, object, object.getClass(), ""); } private void addAttributes(List attributes, Object object, Class type, String prefix) { PropertyDescriptor[] pdescs; try { pdescs = Introspector.getBeanInfo(type).getPropertyDescriptors(); } catch (IntrospectionException e) { return; } for (PropertyDescriptor pdesc : pdescs) { // Ignore a write-only property. if (pdesc.getReadMethod() == null) { continue; } // Ignore unmanageable property. String attrName = pdesc.getName(); Class attrType = pdesc.getPropertyType(); if (attrName.equals("class")) { continue; } if (!isReadable(type, attrName)) { continue; } // Expand if possible. if (isExpandable(type, attrName)) { expandAttribute(attributes, object, prefix, pdesc); continue; } // Ordinary property. String fqan = prefix + attrName; boolean writable = isWritable(type, pdesc); attributes.add(new ModelMBeanAttributeInfo(fqan, convertType(object.getClass(), attrName, attrType, writable).getName(), pdesc.getShortDescription(), true, writable, false)); propertyDescriptors.put(fqan, pdesc); } } private boolean isWritable(Class type, PropertyDescriptor pdesc) { if (type == null) { throw new IllegalArgumentException("type"); } if (pdesc == null) { return false; } String attrName = pdesc.getName(); Class attrType = pdesc.getPropertyType(); boolean writable = (pdesc.getWriteMethod() != null) || isWritable(type, attrName); if (getPropertyEditor(type, attrName, attrType) == null) { writable = false; } return writable; } private void expandAttribute(List attributes, Object object, String prefix, PropertyDescriptor pdesc) { Object property; String attrName = pdesc.getName(); try { property = getAttribute(object, attrName, pdesc.getPropertyType()); } catch (Exception e) { LOGGER.debug("Unexpected exception.", e); return; } if (property == null) { return; } addAttributes(attributes, property, property.getClass(), prefix + attrName + '.'); } private void addOperations(List operations, Object object) { for (Method m : object.getClass().getMethods()) { String mname = m.getName(); // Ignore getters and setters. if (mname.startsWith("is") || mname.startsWith("get") || mname.startsWith("set")) { continue; } // Ignore Object methods. if (mname.matches("(wait|notify|notifyAll|toString|equals|compareTo|hashCode|clone)")) { continue; } // Ignore other user-defined non-operations. if (!isOperation(mname, m.getParameterTypes())) { continue; } List signature = new ArrayList(); int i = 1; for (Class paramType : m.getParameterTypes()) { String paramName = "p" + (i++); if (getPropertyEditor(source.getClass(), paramName, paramType) == null) { continue; } signature.add(new MBeanParameterInfo(paramName, convertType(null, null, paramType, true).getName(), paramName)); } Class returnType = convertType(null, null, m.getReturnType(), false); operations.add(new ModelMBeanOperationInfo(m.getName(), m.getName(), signature .toArray(new MBeanParameterInfo[signature.size()]), returnType.getName(), ModelMBeanOperationInfo.ACTION)); } } private Object getParent(String fqan) throws OgnlException { Object parent; int dotIndex = fqan.lastIndexOf('.'); if (dotIndex < 0) { parent = source; } else { parent = getAttribute(source, fqan.substring(0, dotIndex), null); } return parent; } private String getLeafAttributeName(String fqan) { int dotIndex = fqan.lastIndexOf('.'); if (dotIndex < 0) { return fqan; } return fqan.substring(dotIndex + 1); } private Class getAttributeClass(String signature) throws ClassNotFoundException { if (signature.equals(Boolean.TYPE.getName())) { return Boolean.TYPE; } if (signature.equals(Byte.TYPE.getName())) { return Byte.TYPE; } if (signature.equals(Character.TYPE.getName())) { return Character.TYPE; } if (signature.equals(Double.TYPE.getName())) { return Double.TYPE; } if (signature.equals(Float.TYPE.getName())) { return Float.TYPE; } if (signature.equals(Integer.TYPE.getName())) { return Integer.TYPE; } if (signature.equals(Long.TYPE.getName())) { return Long.TYPE; } if (signature.equals(Short.TYPE.getName())) { return Short.TYPE; } try { ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (cl != null) { return cl.loadClass(signature); } } catch (ClassNotFoundException e) { // Do nothing } return Class.forName(signature); } private Object getAttribute(Object object, String fqan, Class attrType) throws OgnlException { Object property; OgnlContext ctx = (OgnlContext) Ognl.createDefaultContext(object); ctx.setTypeConverter(new OgnlTypeConverter()); if (attrType == null) { property = Ognl.getValue(fqan, ctx, object); } else { property = Ognl.getValue(fqan, ctx, object, attrType); } return property; } private Class convertType(Class type, String attrName, Class attrType, boolean writable) { if ((attrName != null) && ((attrType == Long.class) || (attrType == long.class))) { if (attrName.endsWith("Time") && (attrName.indexOf("Total") < 0) && (attrName.indexOf("Min") < 0) && (attrName.indexOf("Max") < 0) && (attrName.indexOf("Avg") < 0) && (attrName.indexOf("Average") < 0) && !propertyDescriptors.containsKey(attrName + "InMillis")) { return Date.class; } } if (IoFilterChain.class.isAssignableFrom(attrType)) { return Map.class; } if (IoFilterChainBuilder.class.isAssignableFrom(attrType)) { return Map.class; } if (!writable) { if (Collection.class.isAssignableFrom(attrType) || Map.class.isAssignableFrom(attrType)) { if (List.class.isAssignableFrom(attrType)) { return List.class; } if (Set.class.isAssignableFrom(attrType)) { return Set.class; } if (Map.class.isAssignableFrom(attrType)) { return Map.class; } return Collection.class; } if (attrType.isPrimitive() || Date.class.isAssignableFrom(attrType) || Boolean.class.isAssignableFrom(attrType) || Character.class.isAssignableFrom(attrType) || Number.class.isAssignableFrom(attrType)) { if ((attrName == null) || !attrName.endsWith("InMillis") || !propertyDescriptors.containsKey(attrName.substring(0, attrName.length() - 8))) { return attrType; } } } return String.class; } private Object convertValue(Class type, String attrName, Object v, boolean writable) { if (v == null) { return null; } if ((attrName != null) && (v instanceof Long)) { if (attrName.endsWith("Time") && (attrName.indexOf("Total") < 0) && (attrName.indexOf("Min") < 0) && (attrName.indexOf("Max") < 0) && (attrName.indexOf("Avg") < 0) && (attrName.indexOf("Average") < 0) && !propertyDescriptors.containsKey(attrName + "InMillis")) { long time = (Long) v; if (time <= 0) { return null; } return new Date((Long) v); } } if ((v instanceof IoSessionDataStructureFactory) || (v instanceof IoHandler)) { return v.getClass().getName(); } if (v instanceof IoFilterChainBuilder) { Map filterMapping = new LinkedHashMap(); if (v instanceof DefaultIoFilterChainBuilder) { for (IoFilterChain.Entry e : ((DefaultIoFilterChainBuilder) v).getAll()) { filterMapping.put(e.getName(), e.getFilter().getClass().getName()); } } else { filterMapping.put("Unknown builder type", v.getClass().getName()); } return filterMapping; } if (v instanceof IoFilterChain) { Map filterMapping = new LinkedHashMap(); for (IoFilterChain.Entry e : ((IoFilterChain) v).getAll()) { filterMapping.put(e.getName(), e.getFilter().getClass().getName()); } return filterMapping; } if (!writable) { if ((v instanceof Collection) || (v instanceof Map)) { if (v instanceof List) { return convertCollection(v, new ArrayList()); } if (v instanceof Set) { return convertCollection(v, new LinkedHashSet()); } if (v instanceof Map) { return convertCollection(v, new LinkedHashMap()); } return convertCollection(v, new ArrayList()); } if ((v instanceof Date) || (v instanceof Boolean) || (v instanceof Character) || (v instanceof Number)) { if ((attrName == null) || !attrName.endsWith("InMillis") || !propertyDescriptors.containsKey(attrName.substring(0, attrName.length() - 8))) { return v; } } } PropertyEditor editor = getPropertyEditor(type, attrName, v.getClass()); if (editor != null) { editor.setValue(v); return editor.getAsText(); } return v.toString(); } private Object convertCollection(Object src, Collection dst) { Collection srcCol = (Collection) src; for (Object e : srcCol) { Object convertedValue = convertValue(dst.getClass(), "element", e, false); if ((e != null) && (convertedValue == null)) { convertedValue = (e == null ? "" : e.toString()); } dst.add(convertedValue); } return dst; } private Object convertCollection(Object src, Map dst) { Map srcCol = (Map) src; for (Map.Entry e : srcCol.entrySet()) { Object convertedKey = convertValue(dst.getClass(), "key", e.getKey(), false); Object convertedValue = convertValue(dst.getClass(), "value", e.getValue(), false); if ((e.getKey() != null) && (convertedKey == null)) { convertedKey = e.getKey().toString(); } if ((e.getValue() != null) && (convertedValue == null)) { convertedKey = e.getValue().toString(); } dst.put(convertedKey, convertedValue); } return dst; } private void throwMBeanException(Throwable e) throws MBeanException { if (e instanceof OgnlException) { OgnlException ognle = (OgnlException) e; if (ognle.getReason() != null) { throwMBeanException(ognle.getReason()); } else { String message = ognle.getMessage(); if (e instanceof NoSuchPropertyException) { message = "No such property: " + message; } else if (e instanceof ExpressionSyntaxException) { message = "Illegal expression syntax: " + message; } else if (e instanceof InappropriateExpressionException) { message = "Inappropriate expression: " + message; } e = new IllegalArgumentException(ognle.getMessage()); e.setStackTrace(ognle.getStackTrace()); } } if (e instanceof InvocationTargetException) { throwMBeanException(e.getCause()); } LOGGER.warn("Unexpected exception.", e); if (e.getClass().getPackage().getName().matches("javax?\\..+")) { if (e instanceof Exception) { throw new MBeanException((Exception) e, e.getMessage()); } throw new MBeanException(new RuntimeException(e), e.getMessage()); } throw new MBeanException(new RuntimeException(e.getClass().getName() + ": " + e.getMessage()), e.getMessage()); } protected Object getAttribute0(String fqan) throws Exception { throw new AttributeNotFoundException(fqan); } protected void setAttribute0(String attrName, Object attrValue) throws Exception { throw new AttributeNotFoundException(attrName); } protected Object invoke0(String name, Object params[], String signature[]) throws Exception { throw new NoSuchMethodException(); } protected boolean isReadable(Class type, String attrName) { if (IoService.class.isAssignableFrom(type) && attrName.equals("filterChain")) { return false; } if (IoService.class.isAssignableFrom(type) && attrName.equals("localAddress")) { return false; } if (IoService.class.isAssignableFrom(type) && attrName.equals("defaultLocalAddress")) { return false; } if (IoSession.class.isAssignableFrom(type) && attrName.equals("attachment")) { return false; } if (IoSession.class.isAssignableFrom(type) && attrName.equals("attributeKeys")) { return false; } if (IoSession.class.isAssignableFrom(type) && attrName.equals("closeFuture")) { return false; } if (ThreadPoolExecutor.class.isAssignableFrom(type) && attrName.equals("queue")) { return false; } return true; } protected boolean isWritable(Class type, String attrName) { if (IoService.class.isAssignableFrom(type) && attrName.startsWith("defaultLocalAddress")) { return true; } return false; } protected Class getElementType(Class type, String attrName) { if ((transportMetadata != null) && IoAcceptor.class.isAssignableFrom(type) && "defaultLocalAddresses".equals(attrName)) { return transportMetadata.getAddressType(); } return String.class; } protected Class getMapKeyType(Class type, String attrName) { return String.class; } protected Class getMapValueType(Class type, String attrName) { return String.class; } protected boolean isExpandable(Class type, String attrName) { if (IoService.class.isAssignableFrom(type)) { if (attrName.equals("statistics") || attrName.equals("sessionConfig") || attrName.equals("transportMetadata") || attrName.equals("config") || attrName.equals("transportMetadata")) { return true; } } if (ExecutorFilter.class.isAssignableFrom(type) && attrName.equals("executor")) { return true; } if (ThreadPoolExecutor.class.isAssignableFrom(type) && attrName.equals("queueHandler")) { return true; } return false; } protected boolean isOperation(String methodName, Class[] paramTypes) { return true; } protected void addExtraAttributes(List attributes) { // Do nothing } protected void addExtraOperations(List operations) { // Do nothing } protected PropertyEditor getPropertyEditor(Class type, String attrName, Class attrType) { if (type == null) { throw new IllegalArgumentException("type"); } if (attrName == null) { throw new IllegalArgumentException("attrName"); } if ((transportMetadata != null) && (attrType == SocketAddress.class)) { attrType = transportMetadata.getAddressType(); } if (((attrType == Long.class) || (attrType == long.class))) { if (attrName.endsWith("Time") && (attrName.indexOf("Total") < 0) && (attrName.indexOf("Min") < 0) && (attrName.indexOf("Max") < 0) && (attrName.indexOf("Avg") < 0) && (attrName.indexOf("Average") < 0) && !propertyDescriptors.containsKey(attrName + "InMillis")) { return PropertyEditorFactory.getInstance(Date.class); } if (attrName.equals("id")) { return PropertyEditorFactory.getInstance(String.class); } } if (List.class.isAssignableFrom(attrType)) { return new ListEditor(getElementType(type, attrName)); } if (Set.class.isAssignableFrom(attrType)) { return new SetEditor(getElementType(type, attrName)); } if (Collection.class.isAssignableFrom(attrType)) { return new CollectionEditor(getElementType(type, attrName)); } if (Map.class.isAssignableFrom(attrType)) { return new MapEditor(getMapKeyType(type, attrName), getMapValueType(type, attrName)); } return PropertyEditorFactory.getInstance(attrType); } private class OgnlTypeConverter extends PropertyTypeConverter { @Override protected PropertyEditor getPropertyEditor(Class type, String attrName, Class attrType) { return ObjectMBean.this.getPropertyEditor(type, attrName, attrType); } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-jmx/src/main/java/org/apache/mina/integration/jmx/IoFilterMBean.javamina2-2.0.7.orig/src/mina-integration-jmx/src/main/java/org/apache/mina/integration/jmx/IoFilterMBea0000644000175000017500000000317612032276014032547 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.mina.integration.jmx; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.session.IoSession; /** * A JMX MBean wrapper for an {@link IoSession}. * * @author Apache MINA Project */ public class IoFilterMBean extends ObjectMBean { public IoFilterMBean(IoFilter source) { super(source); } @Override protected boolean isOperation(String methodName, Class[] paramTypes) { // Ignore some IoFilter methods. if (methodName.matches("(init|destroy|on(Pre|Post)(Add|Remove)|" + "session(Created|Opened|Idle|Closed)|" + "exceptionCaught|message(Received|Sent)|" + "filter(Close|Write|SetTrafficMask))")) { return false; } return super.isOperation(methodName, paramTypes); } } mina2-2.0.7.orig/src/mina-integration-jmx/src/main/java/org/apache/mina/integration/jmx/package.html0000644000175000017500000000544212032276014032641 0ustar ebourgebourg JMX (Java Management eXtension) integration.

Monitoring Your MINA Services and Sessions

Monitoring an IoService

acceptor = new SocketAcceptor();
       
try
{
    IoServiceManager iosm = new IoServiceManager(acceptor);
    MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();  
    ObjectName name = new ObjectName( "com.acme.test:type=IoServiceManager,name=MyMINAServer" );
    mbs.registerMBean( iosm, name );
}
catch( JMException e )
{
    logger.error( "JMX Exception: ", e );
}

Monitoring an IoSession

Each session is registered to MBean server individually.
acceptor.addListener( new IoServiceListener()
{
    public void serviceActivated( IoService service, SocketAddress serviceAddress, IoHandler handler, IoServiceConfig config )
    {
    }

    public void serviceDeactivated( IoService service, SocketAddress serviceAddress, IoHandler handler, IoServiceConfig config )
    {
    }

    public void sessionCreated( IoSession session )
    {
        try
        {
            IoSessionManager sessMgr = new IoSessionManager( session );
            MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();  
            ObjectName name = new ObjectName( "com.acme.test.session:type=IoSessionManager,name=" + session.getRemoteAddress().toString().replace( ':', '/' ) );
            mbs.registerMBean( sessMgr, name );
        }
        catch( JMException e )
        {
            logger.error( "JMX Exception: ", e );
        }      
    }

    public void sessionDestroyed( IoSession session )
    {
        try
        {
            ObjectName name = new ObjectName( "com.acme.test.session:type=IoSessionManager,name=" + session.getRemoteAddress().toString().replace( ':', '/' ) );
            ManagementFactory.getPlatformMBeanServer().unregisterMBean( name );
        }
        catch( JMException e )
        {
            logger.error( "JMX Exception: ", e );
        }      
    }
});
mina2-2.0.7.orig/src/mina-integration-jmx/src/main/resources/0000755000175000017500000000000012032276014023367 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-ognl/0000755000175000017500000000000012162575507020020 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-ognl/pom.xml.releaseBackup0000644000175000017500000000423412033674301024072 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7-SNAPSHOT mina-integration-ognl Apache MINA OGNL Integration bundle ${project.groupId}.integration.ognl ${project.groupId}.integration.ognl ${project.groupId} mina-core ${project.version} bundle ${project.groupId} mina-integration-beans ${project.version} bundle ognl ognl jboss javassist runtime mina2-2.0.7.orig/src/mina-integration-ognl/pom.xml0000644000175000017500000000422312033674306021330 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7 mina-integration-ognl Apache MINA OGNL Integration bundle ${project.groupId}.integration.ognl ${project.groupId}.integration.ognl ${project.groupId} mina-core ${project.version} bundle ${project.groupId} mina-integration-beans ${project.version} bundle ognl ognl jboss javassist runtime mina2-2.0.7.orig/src/mina-integration-ognl/src/0000755000175000017500000000000012032276014020572 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-ognl/src/test/0000755000175000017500000000000012032276014021551 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-ognl/src/test/java/0000755000175000017500000000000012032276014022472 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-ognl/src/main/0000755000175000017500000000000012032276014021516 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/0000755000175000017500000000000012032276014022437 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/0000755000175000017500000000000012032276014023226 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/apache/0000755000175000017500000000000012032276014024447 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/apache/mina/0000755000175000017500000000000012032276014025373 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/apache/mina/integration/0000755000175000017500000000000012032276014027716 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/apache/mina/integration/ognl/0000755000175000017500000000000012162575507030672 5ustar ebourgebourg././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/apache/mina/integration/ognl/IoFilterPropertyAccessor.javamina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/apache/mina/integration/ognl/IoFilterPr0000644000175000017500000000351312032276014032621 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.mina.integration.ognl; import ognl.OgnlContext; import ognl.OgnlException; import ognl.OgnlRuntime; import ognl.PropertyAccessor; import org.apache.mina.core.filterchain.IoFilter; /** * An OGNL {@link PropertyAccessor} for {@link IoFilter}. * * @author Apache MINA Project */ public class IoFilterPropertyAccessor extends AbstractPropertyAccessor { @Override protected Object getProperty0(OgnlContext context, Object target, String name) throws OgnlException { return OgnlRuntime.NotFound; } @Override protected boolean hasGetProperty0(OgnlContext context, Object target, String name) throws OgnlException { return false; } @Override protected boolean hasSetProperty0(OgnlContext context, Object target, String name) throws OgnlException { return false; } @Override protected Object setProperty0(OgnlContext context, Object target, String name, Object value) throws OgnlException { return OgnlRuntime.NotFound; } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/apache/mina/integration/ognl/IoSessionFinder.javamina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/apache/mina/integration/ognl/IoSessionF0000644000175000017500000000617112032276014032626 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.mina.integration.ognl; import java.util.LinkedHashSet; import java.util.Set; import ognl.Ognl; import ognl.OgnlContext; import ognl.OgnlException; import ognl.TypeConverter; import org.apache.mina.core.session.IoSession; /** * Finds {@link IoSession}s that match a boolean OGNL expression. * * @author Apache MINA Project */ public class IoSessionFinder { private final String query; private final TypeConverter typeConverter = new PropertyTypeConverter(); private final Object expression; /** * Creates a new instance with the specified OGNL expression that returns * a boolean value (e.g. "id == 0x12345678"). */ public IoSessionFinder(String query) { if (query == null) { throw new IllegalArgumentException("query"); } query = query.trim(); if (query.length() == 0) { throw new IllegalArgumentException("query is empty."); } this.query = query; try { expression = Ognl.parseExpression(query); } catch (OgnlException e) { throw new IllegalArgumentException("query: " + query); } } /** * Finds a {@link Set} of {@link IoSession}s that matches the query * from the specified sessions and returns the matches. * @throws OgnlException if failed to evaluate the OGNL expression */ public Set find(Iterable sessions) throws OgnlException { if (sessions == null) { throw new IllegalArgumentException("sessions"); } Set answer = new LinkedHashSet(); for (IoSession s : sessions) { OgnlContext context = (OgnlContext) Ognl.createDefaultContext(s); context.setTypeConverter(typeConverter); context.put(AbstractPropertyAccessor.READ_ONLY_MODE, true); context.put(AbstractPropertyAccessor.QUERY, query); Object result = Ognl.getValue(expression, context, s); if (result instanceof Boolean) { if (((Boolean) result).booleanValue()) { answer.add(s); } } else { throw new OgnlException("Query didn't return a boolean value: " + query); } } return answer; } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/apache/mina/integration/ognl/PropertyTypeConverter.javamina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/apache/mina/integration/ognl/PropertyTy0000644000175000017500000000626412032276014032751 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.mina.integration.ognl; import java.beans.PropertyEditor; import java.lang.reflect.Member; import java.util.Map; import ognl.OgnlContext; import ognl.TypeConverter; import org.apache.mina.integration.beans.PropertyEditorFactory; /** * {@link PropertyEditor}-based implementation of OGNL {@link TypeConverter}. * This converter uses the {@link PropertyEditor} implementations in * mina-integration-beans module to perform conversion. To use this * converter: *

 * OgnlContext ctx = Ognl.createDefaultContext(root);
 * ctx.put(OgnlContext.TYPE_CONVERTER_CONTEXT_KEY, new PropertyTypeConverter());
 * 
* You can also override {@link #getPropertyEditor(Class, String, Class)} * method to have more control over how an appropriate {@link PropertyEditor} * is chosen. * * @author Apache MINA Project */ public class PropertyTypeConverter implements TypeConverter { @SuppressWarnings("unchecked") public Object convertValue(Map ctx, Object target, Member member, String attrName, Object value, Class toType) { if (value == null) { return null; } if (attrName == null) { // I don't know why but OGNL gives null attrName almost always. // Fortunately, we can get the actual attrName with a tiny hack. OgnlContext ognlCtx = (OgnlContext) ctx; attrName = ognlCtx.getCurrentNode().toString().replaceAll("[\" \']+", ""); } if (toType.isAssignableFrom(value.getClass())) { return value; } PropertyEditor e1 = getPropertyEditor(target.getClass(), attrName, value.getClass()); if (e1 == null) { throw new IllegalArgumentException("Can't convert " + value.getClass().getSimpleName() + " to " + String.class.getSimpleName()); } e1.setValue(value); PropertyEditor e2 = getPropertyEditor(target.getClass(), attrName, toType); if (e2 == null) { throw new IllegalArgumentException("Can't convert " + String.class.getSimpleName() + " to " + toType.getSimpleName()); } e2.setAsText(e1.getAsText()); return e2.getValue(); } protected PropertyEditor getPropertyEditor(Class type, String attrName, Class attrType) { return PropertyEditorFactory.getInstance(attrType); } }././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/apache/mina/integration/ognl/IoSessionPropertyAccessor.javamina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/apache/mina/integration/ognl/IoSessionP0000644000175000017500000000464412032276014032643 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.mina.integration.ognl; import java.util.Map; import java.util.TreeMap; import ognl.OgnlContext; import ognl.OgnlException; import ognl.OgnlRuntime; import ognl.PropertyAccessor; import org.apache.mina.core.session.IoSession; /** * An OGNL {@link PropertyAccessor} for {@link IoSession}. * * @author Apache MINA Project */ public class IoSessionPropertyAccessor extends AbstractPropertyAccessor { @Override protected Object getProperty0(OgnlContext context, Object target, String name) throws OgnlException { if (target instanceof IoSession && "attributes".equals(name)) { Map attributes = new TreeMap(); IoSession s = (IoSession) target; for (Object key : s.getAttributeKeys()) { Object value = s.getAttribute(key); if (value == null) { continue; } attributes.put(String.valueOf(key), value); } return attributes; } return OgnlRuntime.NotFound; } @Override protected boolean hasGetProperty0(OgnlContext context, Object target, String name) throws OgnlException { return target instanceof IoSession && "attributes".equals(name); } @Override protected boolean hasSetProperty0(OgnlContext context, Object target, String name) throws OgnlException { return false; } @Override protected Object setProperty0(OgnlContext context, Object target, String name, Object value) throws OgnlException { return OgnlRuntime.NotFound; } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/apache/mina/integration/ognl/IoServicePropertyAccessor.javamina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/apache/mina/integration/ognl/IoServiceP0000644000175000017500000000351212032276014032611 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.mina.integration.ognl; import ognl.OgnlContext; import ognl.OgnlException; import ognl.OgnlRuntime; import ognl.PropertyAccessor; import org.apache.mina.core.service.IoService; /** * An OGNL {@link PropertyAccessor} for {@link IoService}. * * @author Apache MINA Project */ public class IoServicePropertyAccessor extends AbstractPropertyAccessor { @Override protected Object getProperty0(OgnlContext context, Object target, String name) throws OgnlException { return OgnlRuntime.NotFound; } @Override protected boolean hasGetProperty0(OgnlContext context, Object target, String name) throws OgnlException { return false; } @Override protected boolean hasSetProperty0(OgnlContext context, Object target, String name) throws OgnlException { return false; } @Override protected Object setProperty0(OgnlContext context, Object target, String name, Object value) throws OgnlException { return OgnlRuntime.NotFound; } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/apache/mina/integration/ognl/AbstractPropertyAccessor.javamina2-2.0.7.orig/src/mina-integration-ognl/src/main/java/org/apache/mina/integration/ognl/AbstractPr0000644000175000017500000001067712032276014032660 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.mina.integration.ognl; import java.util.Map; import ognl.ObjectPropertyAccessor; import ognl.OgnlContext; import ognl.OgnlException; import ognl.OgnlRuntime; import ognl.PropertyAccessor; /** * An abstract OGNL {@link PropertyAccessor} for MINA constructs. * * @author Apache MINA Project */ @SuppressWarnings("unchecked") public abstract class AbstractPropertyAccessor extends ObjectPropertyAccessor { static final Object READ_ONLY_MODE = new Object(); static final Object QUERY = new Object(); @Override public final boolean hasGetProperty(OgnlContext context, Object target, Object oname) throws OgnlException { if (oname == null) { return false; } if (hasGetProperty0(context, target, oname.toString())) { return true; } else { return super.hasGetProperty(context, target, oname); } } @Override public final boolean hasSetProperty(OgnlContext context, Object target, Object oname) throws OgnlException { if (context.containsKey(READ_ONLY_MODE)) { // Return true to trigger setPossibleProperty to throw an exception. return true; } if (oname == null) { return false; } if (hasSetProperty0(context, target, oname.toString())) { return true; } else { return super.hasSetProperty(context, target, oname); } } @Override public final Object getPossibleProperty(Map context, Object target, String name) throws OgnlException { Object answer = getProperty0((OgnlContext) context, target, name); if (answer == OgnlRuntime.NotFound) { answer = super.getPossibleProperty(context, target, name); } return answer; } @Override public final Object setPossibleProperty(Map context, Object target, String name, Object value) throws OgnlException { if (context.containsKey(READ_ONLY_MODE)) { throw new OgnlException("Expression must be read-only: " + context.get(QUERY)); } Object answer = setProperty0((OgnlContext) context, target, name, value); if (answer == OgnlRuntime.NotFound) { answer = super.setPossibleProperty(context, target, name, value); } return answer; } protected abstract boolean hasGetProperty0(OgnlContext context, Object target, String name) throws OgnlException; protected abstract boolean hasSetProperty0(OgnlContext context, Object target, String name) throws OgnlException; protected abstract Object getProperty0(OgnlContext context, Object target, String name) throws OgnlException; protected abstract Object setProperty0(OgnlContext context, Object target, String name, Object value) throws OgnlException; // The following methods uses the four method above, so there's no need // to override them. @Override public final Object getProperty(Map context, Object target, Object oname) throws OgnlException { return super.getProperty(context, target, oname); } @Override public final boolean hasGetProperty(Map context, Object target, Object oname) throws OgnlException { return super.hasGetProperty(context, target, oname); } @Override public final boolean hasSetProperty(Map context, Object target, Object oname) throws OgnlException { return super.hasSetProperty(context, target, oname); } @Override public final void setProperty(Map context, Object target, Object oname, Object value) throws OgnlException { super.setProperty(context, target, oname, value); } } mina2-2.0.7.orig/src/release.properties0000644000175000017500000000627312033674306017356 0ustar ebourgebourg#release configuration #Sat Oct 06 02:18:14 CEST 2012 project.dev.org.apache.mina\:mina-transport-serial=2.0.8-SNAPSHOT completedPhase=generate-release-poms project.dev.org.apache.mina\:distribution=2.0.8-SNAPSHOT project.rel.org.apache.mina\:distribution=2.0.7 project.scm.org.apache.mina\:mina-statemachine.empty=true project.scm.org.apache.mina\:mina-integration-xbean.empty=true exec.additionalArguments=-Papache-release -P serial,apache-release,apache-release exec.snapshotReleasePluginAllowed=false project.scm.org.apache.mina\:mina-transport-serial.empty=true scm.tagBase=https\://svn.apache.org/repos/asf/mina/mina/tags scm.tag=2.0.7 project.rel.org.apache.mina\:mina-transport-serial=2.0.7 project.dev.org.apache.mina\:mina-http=2.0.8-SNAPSHOT project.rel.org.apache.mina\:mina-integration-beans=2.0.7 project.scm.org.apache.mina\:mina-parent.tag=HEAD project.rel.org.apache.mina\:mina-transport-apr=2.0.7 project.dev.org.apache.mina\:mina-integration-jmx=2.0.8-SNAPSHOT project.dev.org.apache.mina\:mina-integration-xbean=2.0.8-SNAPSHOT project.rel.org.apache.mina\:mina-parent=2.0.7 project.scm.org.apache.mina\:mina-parent.developerConnection=scm\:svn\:https\://svn.apache.org/repos/asf/mina/mina/branches/2.0 project.scm.org.apache.mina\:mina-transport-apr.empty=true project.dev.org.apache.mina\:mina-statemachine=2.0.8-SNAPSHOT project.rel.org.apache.mina\:mina-filter-compression=2.0.7 project.dev.org.apache.mina\:mina-filter-compression=2.0.8-SNAPSHOT remoteTagging=true project.scm.org.apache.mina\:mina-integration-jmx.empty=true project.scm.org.apache.mina\:mina-integration-beans.empty=true scm.url=scm\:svn\:https\://svn.apache.org/repos/asf/mina/mina/branches/2.0 project.scm.org.apache.mina\:mina-core.empty=true scm.commentPrefix=[maven-release-plugin] project.dev.org.apache.mina\:mina-core=2.0.8-SNAPSHOT project.scm.org.apache.mina\:mina-parent.url=http\://svn.apache.org/viewvc/mina/mina/tags/2.0.6 project.scm.org.apache.mina\:mina-example.empty=true project.dev.org.apache.mina\:mina-example=2.0.8-SNAPSHOT project.rel.org.apache.mina\:mina-http=2.0.7 project.rel.org.apache.mina\:mina-example=2.0.7 project.dev.org.apache.mina\:mina-integration-ognl=2.0.8-SNAPSHOT pushChanges=true project.dev.org.apache.mina\:mina-legal=2.0.8-SNAPSHOT project.scm.org.apache.mina\:mina-integration-ognl.empty=true project.scm.org.apache.mina\:mina-legal.empty=true project.scm.org.apache.mina\:mina-parent.connection=scm\:svn\:http\://svn.apache.org/repos/asf/mina/mina/tags/2.0.6 project.dev.org.apache.mina\:mina-integration-beans=2.0.8-SNAPSHOT project.dev.org.apache.mina\:mina-transport-apr=2.0.8-SNAPSHOT project.rel.org.apache.mina\:mina-legal=2.0.7 project.scm.org.apache.mina\:mina-filter-compression.empty=true preparationGoals=clean install project.scm.org.apache.mina\:distribution.empty=true project.rel.org.apache.mina\:mina-integration-xbean=2.0.7 project.rel.org.apache.mina\:mina-statemachine=2.0.7 project.rel.org.apache.mina\:mina-integration-jmx=2.0.7 project.dev.org.apache.mina\:mina-parent=2.0.8-SNAPSHOT scm.tagNameFormat=@{project.artifactId}-@{project.version} project.scm.org.apache.mina\:mina-http.empty=true project.rel.org.apache.mina\:mina-integration-ognl=2.0.7 project.rel.org.apache.mina\:mina-core=2.0.7 mina2-2.0.7.orig/src/mina-core/0000755000175000017500000000000012162575507015470 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/pom.xml.releaseBackup0000644000175000017500000000334512033674301021544 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7-SNAPSHOT mina-core Apache MINA Core bundle ${project.groupId}.core ${project.groupId} org.easymock easymock org.easymock easymockclassextension mina2-2.0.7.orig/src/mina-core/pom.xml0000644000175000017500000000333412033674306017002 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7 mina-core Apache MINA Core bundle ${project.groupId}.core ${project.groupId} org.easymock easymock org.easymock easymockclassextension mina2-2.0.7.orig/src/mina-core/bin/0000755000175000017500000000000012162575507016240 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/0000755000175000017500000000000012032276017016245 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/0000755000175000017500000000000012032276017017224 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/0000755000175000017500000000000012032276017020145 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/testcase/0000755000175000017500000000000012162575507021772 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/testcase/MinaRegressionTest.java0000644000175000017500000001274612032276017026422 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package testcase; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.executor.ExecutorFilter; import org.apache.mina.filter.executor.OrderedThreadPoolExecutor; import org.apache.mina.transport.socket.SocketAcceptor; import org.apache.mina.transport.socket.SocketConnector; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import org.apache.mina.transport.socket.nio.NioSocketConnector; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.InetSocketAddress; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; /** * TODO : Add documentation * @author Apache MINA Project * */ public class MinaRegressionTest extends IoHandlerAdapter { private static final Logger logger = LoggerFactory.getLogger(MinaRegressionTest.class); public static final int MSG_SIZE = 5000; public static final int MSG_COUNT = 10; private static final int PORT = 23234; private static final int BUFFER_SIZE = 8192; private static final int TIMEOUT = 10000; public static final String OPEN = "open"; public SocketAcceptor acceptor; public SocketConnector connector; private final Object LOCK = new Object(); private static final ThreadFactory THREAD_FACTORY = new ThreadFactory() { public Thread newThread(final Runnable r) { return new Thread(null, r, "MinaThread", 64 * 1024); } }; private OrderedThreadPoolExecutor executor; public static AtomicInteger sent = new AtomicInteger(0); public MinaRegressionTest() throws IOException { executor = new OrderedThreadPoolExecutor(0, 1000, 60, TimeUnit.SECONDS, THREAD_FACTORY); acceptor = new NioSocketAcceptor(Runtime.getRuntime().availableProcessors() + 1); acceptor.setReuseAddress(true); acceptor.getSessionConfig().setReceiveBufferSize(BUFFER_SIZE); acceptor.getFilterChain().addLast("threadPool", new ExecutorFilter(executor)); acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new MyProtocolCodecFactory())); connector = new NioSocketConnector(Runtime.getRuntime().availableProcessors() + 1); connector.setConnectTimeoutMillis(TIMEOUT); connector.getSessionConfig().setSendBufferSize(BUFFER_SIZE); connector.getSessionConfig().setReuseAddress(true); } public void connect() throws Exception { final InetSocketAddress socketAddress = new InetSocketAddress("0.0.0.0", PORT); acceptor.setHandler(new MyIoHandler(LOCK)); acceptor.bind(socketAddress); connector.setHandler(this); final IoFutureListener listener = new IoFutureListener() { public void operationComplete(ConnectFuture future) { try { logger.info("Write message to session " + future.getSession().getId()); final IoSession s = future.getSession(); IoBuffer wb = IoBuffer.allocate(MSG_SIZE); wb.put(new byte[MSG_SIZE]); wb.flip(); s.write(wb); } catch (Exception e) { logger.error("Can't send message: {}", e.getMessage()); } } }; for (int i = 0; i < MSG_COUNT; i++) { ConnectFuture future = connector.connect(socketAddress); future.addListener(listener); } synchronized (LOCK) { LOCK.wait(50000); } connector.dispose(); acceptor.unbind(); acceptor.dispose(); executor.shutdownNow(); logger.info("Received: " + MyIoHandler.received.intValue()); logger.info("Sent: " + sent.intValue()); logger.info("FINISH"); } @Override public void exceptionCaught(IoSession session, Throwable cause) { if (!(cause instanceof IOException)) { logger.error("Exception: ", cause); } else { logger.info("I/O error: " + cause.getMessage()); } session.close(true); } @Override public void messageSent(IoSession session, Object message) throws Exception { sent.incrementAndGet(); } public static void main(String[] args) throws Exception { logger.info("START"); new MinaRegressionTest().connect(); } }mina2-2.0.7.orig/src/mina-core/src/test/java/testcase/MyResponseEncoder.java0000644000175000017500000000250212032276017026226 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package testcase; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolEncoder; import org.apache.mina.filter.codec.ProtocolEncoderOutput; /** * TODO: Document me ! * @author Apache MINA Project */ public class MyResponseEncoder implements ProtocolEncoder { public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { } public void dispose(IoSession session) throws Exception { } } mina2-2.0.7.orig/src/mina-core/src/test/java/testcase/MyRequestDecoder.java0000644000175000017500000000625512032276017026057 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package testcase; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.CumulativeProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static testcase.MinaRegressionTest.MSG_SIZE; import static testcase.MinaRegressionTest.OPEN; /** * TODO: Document me ! * @author Apache MINA Project */ public class MyRequestDecoder extends CumulativeProtocolDecoder { private static final Logger logger = LoggerFactory.getLogger(MyRequestDecoder.class); @Override protected boolean doDecode(final IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { if (!session.containsAttribute(OPEN)) { logger.error("!decoding for closed session {}", session.getId()); } new Thread(new Runnable() { public void run() { try { logger.debug("Sleep for 500 ms for session {}", session.getId()); Thread.sleep(500); logger.debug("Wake up now from a 500 ms sleep for session {}", session.getId()); } catch (InterruptedException ignore) { } session.close(true); } }).start(); // sleep so that session.close(true) is already called when decoding continues logger.debug("Sleep for 1000 ms for session {}", session.getId()); Thread.sleep(1000); logger.debug("Wake up now from a 1000 ms sleep for session {}", session.getId()); if (!session.containsAttribute(OPEN)) { logger.error("!session {} closed before decoding completes!", session.getId()); int i = 0; try { int j = 2 / i; } catch (Exception e) { //e.printStackTrace(); } } // no full message if (in.remaining() < MSG_SIZE) return false; logger.info("Done decoding for session {}", session.getId()); if (in.hasRemaining() && !session.isClosing() && session.isConnected()) { IoBuffer tmp = IoBuffer.allocate(in.remaining()); tmp.put(in); tmp.flip(); out.write(tmp); return true; } return false; } } mina2-2.0.7.orig/src/mina-core/src/test/java/testcase/MyIoHandler.java0000644000175000017500000000643112032276017025002 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package testcase; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static testcase.MinaRegressionTest.MSG_COUNT; import static testcase.MinaRegressionTest.OPEN; import java.io.IOException; import java.util.concurrent.atomic.AtomicInteger; /** * TODO: Document me ! * @author Apache MINA Project * */ public class MyIoHandler extends IoHandlerAdapter { private static final Logger logger = LoggerFactory.getLogger(MyIoHandler.class); public static AtomicInteger received = new AtomicInteger(0); public static AtomicInteger closed = new AtomicInteger(0); private final Object LOCK; public MyIoHandler(Object lock) { LOCK = lock; } @Override public void exceptionCaught(IoSession session, Throwable cause) { if (!(cause instanceof IOException)) { logger.error("Exception: ", cause); } else { logger.info("I/O error: " + cause.getMessage()); } session.close(true); } @Override public void sessionOpened(IoSession session) throws Exception { logger.info("Session " + session.getId() + " is opened"); session.resumeRead(); } @Override public void sessionCreated(IoSession session) throws Exception { logger.info("Creation of session " + session.getId()); session.setAttribute(OPEN); session.suspendRead(); } @Override public void sessionClosed(IoSession session) throws Exception { session.removeAttribute(OPEN); logger.info("{}> Session closed", session.getId()); final int clsd = closed.incrementAndGet(); if (clsd == MSG_COUNT) { synchronized (LOCK) { LOCK.notifyAll(); } } int i = 0; try { int j = 2 / i; } catch (Exception e) { //e.printStackTrace(); } } @Override public void messageReceived(IoSession session, Object message) throws Exception { IoBuffer msg = (IoBuffer) message; logger.info("MESSAGE: " + msg.remaining() + " on session " + session.getId()); final int rec = received.incrementAndGet(); if (rec == MSG_COUNT) { synchronized (LOCK) { LOCK.notifyAll(); } } session.close(true); } } mina2-2.0.7.orig/src/mina-core/src/test/java/testcase/MyProtocolCodecFactory.java0000644000175000017500000000304412032276017027221 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package testcase; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFactory; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolEncoder; /** * TODO: Document me * @author Apache MINA Project * */ public class MyProtocolCodecFactory implements ProtocolCodecFactory { private ProtocolDecoder decoder = new MyRequestDecoder(); private ProtocolEncoder encoder = new MyResponseEncoder(); public ProtocolDecoder getDecoder(IoSession sessionIn) throws Exception { return decoder; } public ProtocolEncoder getEncoder(IoSession sessionIn) throws Exception { return encoder; } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/0000755000175000017500000000000012032276014020731 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/0000755000175000017500000000000012032276014022152 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/0000755000175000017500000000000012032276016023100 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/proxy/0000755000175000017500000000000012162575507024274 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/proxy/NTLMTest.java0000644000175000017500000002515512032276014026544 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy; import static org.apache.mina.proxy.utils.ByteUtilities.asHex; import static org.junit.Assert.assertEquals; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Security; import org.apache.mina.proxy.handlers.http.ntlm.NTLMResponses; import org.apache.mina.proxy.handlers.http.ntlm.NTLMUtilities; import org.apache.mina.proxy.utils.ByteUtilities; import org.apache.mina.proxy.utils.MD4Provider; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * NTLMTest.java - JUNIT tests of the NTLM authentication mechanism. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class NTLMTest { private final static Logger logger = LoggerFactory.getLogger(NTLMTest.class); static { if (Security.getProvider("MINA") == null) { Security.addProvider(new MD4Provider()); } } /** * Tests bytes manipulations. */ @Test public void testEncoding() throws UnsupportedEncodingException { assertEquals("d204", asHex(ByteUtilities.writeShort((short) 1234))); assertEquals("d2040000", asHex(ByteUtilities.writeInt(1234))); assertEquals("01000000", asHex(ByteUtilities.writeInt((short) 1))); assertEquals("4e544c4d53535000", asHex(NTLMUtilities.NTLM_SIGNATURE)); assertEquals("680065006c006c006f00", asHex(ByteUtilities.getUTFStringAsByteArray("hello"))); assertEquals("48454c4c4f", asHex(ByteUtilities.getOEMStringAsByteArray("HELLO"))); } /** * Tests conversions to and from network byte order. */ @Test public void testMethods() { byte[] buf = new byte[4]; ByteUtilities.intToNetworkByteOrder(1234, buf, 0, 4); assertEquals("000004d2", asHex(buf)); assertEquals(1234, ByteUtilities.networkByteOrderToInt(buf, 0, 4)); } /** * Tests security buffers. */ @Test public void testSecurityBuffer() { byte[] secBuf = new byte[8]; NTLMUtilities.writeSecurityBuffer((short) 1234, (short) 1234, 4321, secBuf, 0); assertEquals("d204d204e1100000", asHex(secBuf)); } /** * Tests creating a type 1 message. */ @Test public void testType1Message() { int customFlags = NTLMUtilities.FLAG_NEGOTIATE_UNICODE | NTLMUtilities.FLAG_NEGOTIATE_OEM | NTLMUtilities.FLAG_NEGOTIATE_NTLM | NTLMUtilities.FLAG_REQUEST_SERVER_AUTH_REALM | NTLMUtilities.FLAG_NEGOTIATE_DOMAIN_SUPPLIED | NTLMUtilities.FLAG_NEGOTIATE_WORKSTATION_SUPPLIED; byte[] osVer = new byte[8]; NTLMUtilities.writeOSVersion((byte) 5, (byte) 0, (short) 2195, osVer, 0); String msgType1 = asHex(NTLMUtilities.createType1Message("WORKSTATION", "DOMAIN", customFlags, osVer)); assertEquals("4e544c4d53535000010000000732000006000600330000000b000b0028000000" + "050093080000000f574f524b53544154494f4e444f4d41494e", msgType1); assertEquals("050093080000000f", asHex(osVer)); //Microsoft Windows XP [version 5.1.2600] String os = System.getProperty("os.name"); if (os != null && os.toUpperCase().contains("WINDOWS") && "5.1".equals(System.getProperty("os.version"))) { String hex = asHex(NTLMUtilities.getOsVersion()); assertEquals("0501", hex.substring(0, 4)); assertEquals(16, hex.length()); } } /** * Tests creating a type 3 message. * WARNING: Will silently fail if no MD4 digest provider is available. */ @Test public void testType3Message() throws Exception { try { MessageDigest.getInstance("MD4"); } catch (NoSuchAlgorithmException ex) { logger.warn("No MD4 digest provider found !"); return; } int flags = 0x00000001 | 0x00000200 | 0x00010000 | 0x00800000; String msg = "4e544c4d53535000020000000c000c003000000001028100" + "0123456789abcdef0000000000000000620062003c000000" + "44004f004d00410049004e0002000c0044004f004d004100" + "49004e0001000c0053004500520056004500520004001400" + "64006f006d00610069006e002e0063006f006d0003002200" + "7300650072007600650072002e0064006f006d0061006900" + "6e002e0063006f006d0000000000"; byte[] challengePacket = ByteUtilities.asByteArray(msg); int serverFlags = NTLMUtilities.extractFlagsFromType2Message(challengePacket); assertEquals(flags, serverFlags); NTLMUtilities.printTargetInformationBlockFromType2Message(challengePacket, serverFlags, new PrintWriter( System.out, true)); byte[] osVer = new byte[8]; NTLMUtilities.writeOSVersion((byte) 5, (byte) 0, (short) 2195, osVer, 0); byte[] challenge = NTLMUtilities.extractChallengeFromType2Message(challengePacket); assertEquals("0123456789abcdef", asHex(challenge)); String expectedTargetInfoBlock = "02000c0044004f004d00410049004e00" + "01000c00530045005200560045005200" + "0400140064006f006d00610069006e00" + "2e0063006f006d000300220073006500" + "72007600650072002e0064006f006d00" + "610069006e002e0063006f006d000000" + "0000"; byte[] targetInfo = NTLMUtilities.extractTargetInfoFromType2Message(challengePacket, null); assertEquals(expectedTargetInfoBlock, asHex(targetInfo)); assertEquals("DOMAIN", NTLMUtilities.extractTargetNameFromType2Message(challengePacket, new Integer(serverFlags))); serverFlags = 0x00000001 | 0x00000200; String msgType3 = asHex(NTLMUtilities.createType3Message("user", "SecREt01", challenge, "DOMAIN", "WORKSTATION", serverFlags, null)); String expected = "4e544c4d5353500003000000180018006a00000018001800" + "820000000c000c0040000000080008004c00000016001600" + "54000000000000009a0000000102000044004f004d004100" + "49004e00750073006500720057004f0052004b0053005400" + "4100540049004f004e00c337cd5cbd44fc9782a667af6d42" + "7c6de67c20c2d3e77c5625a98c1c31e81847466b29b2df46" + "80f39958fb8c213a9cc6"; assertEquals(expected, msgType3); } /** * Tests flags manipulations. */ @Test public void testFlags() { int flags = NTLMUtilities.FLAG_NEGOTIATE_UNICODE | NTLMUtilities.FLAG_REQUEST_SERVER_AUTH_REALM | NTLMUtilities.FLAG_NEGOTIATE_NTLM | NTLMUtilities.FLAG_NEGOTIATE_ALWAYS_SIGN; int flags2 = NTLMUtilities.FLAG_NEGOTIATE_UNICODE | NTLMUtilities.FLAG_REQUEST_SERVER_AUTH_REALM | NTLMUtilities.FLAG_NEGOTIATE_NTLM; assertEquals(flags2, flags & (~NTLMUtilities.FLAG_NEGOTIATE_ALWAYS_SIGN)); assertEquals(flags2, flags2 & (~NTLMUtilities.FLAG_NEGOTIATE_ALWAYS_SIGN)); assertEquals("05820000", asHex(ByteUtilities.writeInt(flags))); byte[] testFlags = ByteUtilities.asByteArray("7F808182"); assertEquals("7f808182", asHex(testFlags)); ByteUtilities.changeByteEndianess(testFlags, 0, 4); assertEquals("807f8281", asHex(testFlags)); ByteUtilities.changeByteEndianess(testFlags, 0, 4); ByteUtilities.changeWordEndianess(testFlags, 0, 4); assertEquals("8281807f", asHex(testFlags)); } /** * Tests response computing. * WARNING: Will silently fail if no MD4 digest provider is available. */ @Test public void testResponses() throws Exception { try { MessageDigest.getInstance("MD4"); } catch (NoSuchAlgorithmException ex) { logger.warn("No MD4 digest provider found !"); return; } String LMResponse = "c337cd5cbd44fc9782a667af6d427c6de67c20c2d3e77c56"; assertEquals(LMResponse, asHex(NTLMResponses.getLMResponse("SecREt01", ByteUtilities.asByteArray("0123456789abcdef")))); String NTLMResponse = "25a98c1c31e81847466b29b2df4680f39958fb8c213a9cc6"; assertEquals(NTLMResponse, asHex(NTLMResponses.getNTLMResponse("SecREt01", ByteUtilities.asByteArray("0123456789abcdef")))); String LMv2Response = "d6e6152ea25d03b7c6ba6629c2d6aaf0ffffff0011223344"; assertEquals( LMv2Response, asHex(NTLMResponses.getLMv2Response("DOMAIN", "user", "SecREt01", ByteUtilities.asByteArray("0123456789abcdef"), ByteUtilities.asByteArray("ffffff0011223344")))); String NTLM2Response = "10d550832d12b2ccb79d5ad1f4eed3df82aca4c3681dd455"; assertEquals(NTLM2Response, asHex(NTLMResponses.getNTLM2SessionResponse("SecREt01", ByteUtilities.asByteArray("0123456789abcdef"), ByteUtilities.asByteArray("ffffff0011223344")))); String NTLMv2Response = "cbabbca713eb795d04c97abc01ee4983" + "01010000000000000090d336b734c301" + "ffffff00112233440000000002000c00" + "44004f004d00410049004e0001000c00" + "53004500520056004500520004001400" + "64006f006d00610069006e002e006300" + "6f006d00030022007300650072007600" + "650072002e0064006f006d0061006900" + "6e002e0063006f006d00000000000000" + "0000"; String targetInformation = "02000c0044004f004d00410049004e00" + "01000c00530045005200560045005200" + "0400140064006f006d00610069006e00" + "2e0063006f006d000300220073006500" + "72007600650072002e0064006f006d00" + "610069006e002e0063006f006d000000" + "0000"; assertEquals(NTLMv2Response, asHex(NTLMResponses.getNTLMv2Response("DOMAIN", "user", "SecREt01", ByteUtilities.asByteArray(targetInformation), ByteUtilities.asByteArray("0123456789abcdef"), ByteUtilities.asByteArray("ffffff0011223344"), 1055844000000L))); } }mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/proxy/MD4Test.java0000644000175000017500000000751712032276014026360 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy; import static org.apache.mina.proxy.utils.ByteUtilities.asHex; import static org.junit.Assert.assertEquals; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; import org.apache.mina.proxy.utils.MD4Provider; import org.junit.Before; import org.junit.Test; /** * MD4Test.java - JUnit testcase that tests the rfc 1320 test suite. * @see RFC 1320 * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class MD4Test { /** * {@inheritDoc} */ @Before public void setUp() throws Exception { if (Security.getProvider(MD4Provider.PROVIDER_NAME) == null) { System.out.print("Adding MINA provider..."); Security.addProvider(new MD4Provider()); //System.out.println(" [Ok]"); } } /** * Test suite for the MD4 algorithm. */ @Test public void testRFCVectors() throws NoSuchAlgorithmException, NoSuchProviderException { MessageDigest md4 = MessageDigest.getInstance("MD4", MD4Provider.PROVIDER_NAME); doTest(md4, "31d6cfe0d16ae931b73c59d7e0c089c0", ""); doTest(md4, "bde52cb31de33e46245e05fbdbd6fb24", "a"); doTest(md4, "a448017aaf21d8525fc10ae87aa6729d", "abc"); doTest(md4, "d9130a8164549fe818874806e1c7014b", "message digest"); doTest(md4, "d79e1c308aa5bbcdeea8ed63df412da9", "abcdefghijklmnopqrstuvwxyz"); doTest(md4, "043f8582f241db351ce627e153e7f0e4", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); doTest(md4, "e33b4ddc9c38f2199c3e7b164fcc0536", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"); } /** * Original test vector found on wikipedia(en) * and wikipedia(fr) */ @Test public void testWikipediaVectors() throws NoSuchAlgorithmException, NoSuchProviderException { MessageDigest md4 = MessageDigest.getInstance("MD4", MD4Provider.PROVIDER_NAME); doTest(md4, "b94e66e0817dd34dc7858a0c131d4079", "Wikipedia, l'encyclopedie libre et gratuite"); doTest(md4, "1bee69a46ba811185c194762abaeae90", "The quick brown fox jumps over the lazy dog"); doTest(md4, "b86e130ce7028da59e672d56ad0113df", "The quick brown fox jumps over the lazy cog"); } /** * Performs md4 digesting on the provided test vector and verifies that the * result equals to the expected result. * * @param md4 the md4 message digester * @param expected the expected hex formatted string * @param testVector the string message */ private static void doTest(MessageDigest md4, String expected, String testVector) { String result = asHex(md4.digest(testVector.getBytes())); assertEquals(expected, result); } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/proxy/HttpAuthTest.java0000644000175000017500000000740312032276014027527 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy; import static org.junit.Assert.assertEquals; import java.util.HashMap; import org.apache.mina.core.session.DummySession; import org.apache.mina.proxy.handlers.http.basic.HttpBasicAuthLogicHandler; import org.apache.mina.proxy.handlers.http.digest.DigestUtilities; import org.junit.Test; /** * HttpAuthTest.java - JUNIT tests of the HTTP Basic & Digest authentication mechanisms. * See RFC 2617 . * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class HttpAuthTest { /** * The charset in use. */ private final static String CHARSET_IN_USE = "ISO-8859-1"; /** * Tests Basic authentication mechanism. */ @Test public void testBasicAuthResponse() { String USER = "Aladdin"; String PWD = "open sesame"; assertEquals("QWxhZGRpbjpvcGVuIHNlc2FtZQ==", HttpBasicAuthLogicHandler.createAuthorization(USER, PWD)); } /** * Tests Http Digest authentication mechanism. */ @Test public void testDigestAuthResponse() { String USER = "Mufasa"; String PWD = "Circle Of Life"; String METHOD = "GET"; HashMap map = new HashMap(); map.put("realm", "testrealm@host.com"); map.put("qop", "auth"); map.put("nc", "00000001"); map.put("cnonce", "0a4f113b"); map.put("nonce", "dcd98b7102dd2f0e8b11d0f600bfb0c093"); map.put("opaque", "5ccc069c403ebaf9f0171e9517f40e41"); map.put("uri", "/dir/index.html"); map.put("username", USER); String response = null; try { response = DigestUtilities.computeResponseValue(new DummySession(), map, METHOD, PWD, CHARSET_IN_USE, null); assertEquals("6629fae49393a05397450978507c4ef1", response); writeResponse(map, response); } catch (Exception e) { //e.printStackTrace(); } } /** * Pretty prints the digest response header . * * @param map the map holding the authentication parameters * @param response the built digest response string */ private void writeResponse(HashMap map, String response) { map.put("response", response); StringBuilder sb = new StringBuilder("Digest "); boolean addSeparator = false; for (String key : map.keySet()) { if (addSeparator) { sb.append(",\n\t\t\t "); } else { addSeparator = true; } boolean quotedValue = !"qop".equals(key) && !"nc".equals(key); sb.append(key); if (quotedValue) { sb.append("=\"").append(map.get(key)).append('\"'); } else { sb.append('=').append(map.get(key)); } } //System.out.println("Proxy-Authorization: " + sb.toString()); } }mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/core/0000755000175000017500000000000012162575507024043 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/core/service/0000755000175000017500000000000012162575507025503 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/core/service/AbstractIoServiceTest.java0000644000175000017500000001453412032276015032555 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.service; import junit.framework.Assert; import org.apache.mina.core.future.CloseFuture; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.IoFuture; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import org.apache.mina.transport.socket.nio.NioSocketConnector; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; /** * test the AbstractIoService * * @author Apache MINA Project */ public class AbstractIoServiceTest { private static final int PORT = 9123; @Test public void testDispose() throws IOException, InterruptedException { List threadsBefore = getThreadNames(); final IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast("logger", new LoggingFilter()); acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8")))); acceptor.setHandler(new ServerHandler()); acceptor.getSessionConfig().setReadBufferSize(2048); acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10); acceptor.bind(new InetSocketAddress(PORT)); System.out.println("Server running ..."); final NioSocketConnector connector = new NioSocketConnector(); // Set connect timeout. connector.setConnectTimeoutMillis(30 * 1000L); connector.setHandler(new ClientHandler()); connector.getFilterChain().addLast("logger", new LoggingFilter()); connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8")))); // Start communication. ConnectFuture cf = connector.connect(new InetSocketAddress("localhost", 9123)); cf.awaitUninterruptibly(); IoSession session = cf.getSession(); // send a message session.write("Hello World!\r"); // wait until response is received CountDownLatch latch = (CountDownLatch) session.getAttribute("latch"); latch.await(); // close the session CloseFuture closeFuture = session.close(false); System.out.println("session.close called"); //Thread.sleep(5); // wait for session close and then dispose the connector closeFuture.addListener(new IoFutureListener() { public void operationComplete(IoFuture future) { System.out.println("managed session count=" + connector.getManagedSessionCount()); System.out.println("Disposing connector ..."); connector.dispose(true); System.out.println("Disposing connector ... *finished*"); } }); closeFuture.awaitUninterruptibly(); acceptor.dispose(true); List threadsAfter = getThreadNames(); System.out.println("threadsBefore = " + threadsBefore); System.out.println("threadsAfter = " + threadsAfter); // Assert.assertEquals(threadsBefore, threadsAfter); } public static class ClientHandler extends IoHandlerAdapter { private static final Logger LOGGER = LoggerFactory.getLogger("CLIENT"); @Override public void sessionCreated(IoSession session) throws Exception { session.setAttribute("latch", new CountDownLatch(1)); } @Override public void messageReceived(IoSession session, Object message) throws Exception { LOGGER.info("client: messageReceived(" + session + ", " + message + ")"); CountDownLatch latch = (CountDownLatch) session.getAttribute("latch"); latch.countDown(); } @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { LOGGER.warn("exceptionCaught:", cause); } } public static class ServerHandler extends IoHandlerAdapter { private static final Logger LOGGER = LoggerFactory.getLogger("SERVER"); @Override public void messageReceived(IoSession session, Object message) throws Exception { LOGGER.info("server: messageReceived(" + session + ", " + message + ")"); session.write(message.toString()); } @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { LOGGER.warn("exceptionCaught:", cause); } } public static void main(String[] args) throws IOException, InterruptedException { new AbstractIoServiceTest().testDispose(); } private List getThreadNames() { List list = new ArrayList(); int active = Thread.activeCount(); Thread[] threads = new Thread[active]; Thread.enumerate(threads); for (Thread thread : threads) { try { String name = thread.getName(); list.add(name); } catch (NullPointerException ignore) { } } return list; } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/core/FutureTest.java0000644000175000017500000001727712032276016027023 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core; import java.io.IOException; import org.apache.mina.core.future.DefaultCloseFuture; import org.apache.mina.core.future.DefaultConnectFuture; import org.apache.mina.core.future.DefaultWriteFuture; import org.apache.mina.core.future.IoFuture; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.session.DummySession; import org.apache.mina.core.session.IoSession; import org.junit.Test; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; /** * Tests {@link IoFuture} implementations. * * @author Apache MINA Project */ public class FutureTest { @Test public void testCloseFuture() throws Exception { DefaultCloseFuture future = new DefaultCloseFuture(null); assertFalse(future.isDone()); assertFalse(future.isClosed()); TestThread thread = new TestThread(future); thread.start(); future.setClosed(); thread.join(); assertTrue(thread.success); assertTrue(future.isDone()); assertTrue(future.isClosed()); } @Test public void testConnectFuture() throws Exception { DefaultConnectFuture future = new DefaultConnectFuture(); assertFalse(future.isDone()); assertFalse(future.isConnected()); assertNull(future.getSession()); assertNull(future.getException()); TestThread thread = new TestThread(future); thread.start(); IoSession session = new DummySession(); future.setSession(session); thread.join(); assertTrue(thread.success); assertTrue(future.isDone()); assertTrue(future.isConnected()); assertEquals(session, future.getSession()); assertNull(future.getException()); future = new DefaultConnectFuture(); thread = new TestThread(future); thread.start(); future.setException(new IOException()); thread.join(); assertTrue(thread.success); assertTrue(future.isDone()); assertFalse(future.isConnected()); assertTrue(future.getException() instanceof IOException); try { future.getSession(); fail("IOException should be thrown."); } catch (Exception e) { // Signifies a successful test execution assertTrue(true); } } @Test public void testWriteFuture() throws Exception { DefaultWriteFuture future = new DefaultWriteFuture(null); assertFalse(future.isDone()); assertFalse(future.isWritten()); TestThread thread = new TestThread(future); thread.start(); future.setWritten(); thread.join(); assertTrue(thread.success); assertTrue(future.isDone()); assertTrue(future.isWritten()); future = new DefaultWriteFuture(null); thread = new TestThread(future); thread.start(); future.setException(new Exception()); thread.join(); assertTrue(thread.success); assertTrue(future.isDone()); assertFalse(future.isWritten()); assertTrue(future.getException().getClass() == Exception.class); } @Test public void testAddListener() throws Exception { DefaultCloseFuture future = new DefaultCloseFuture(null); assertFalse(future.isDone()); assertFalse(future.isClosed()); TestListener listener1 = new TestListener(); TestListener listener2 = new TestListener(); future.addListener(listener1); future.addListener(listener2); TestThread thread = new TestThread(future); thread.start(); future.setClosed(); thread.join(); assertTrue(thread.success); assertTrue(future.isDone()); assertTrue(future.isClosed()); assertSame(future, listener1.notifiedFuture); assertSame(future, listener2.notifiedFuture); } @Test public void testLateAddListener() throws Exception { DefaultCloseFuture future = new DefaultCloseFuture(null); assertFalse(future.isDone()); assertFalse(future.isClosed()); TestThread thread = new TestThread(future); thread.start(); future.setClosed(); thread.join(); assertTrue(thread.success); assertTrue(future.isDone()); assertTrue(future.isClosed()); TestListener listener = new TestListener(); future.addListener(listener); assertSame(future, listener.notifiedFuture); } @Test public void testRemoveListener1() throws Exception { DefaultCloseFuture future = new DefaultCloseFuture(null); assertFalse(future.isDone()); assertFalse(future.isClosed()); TestListener listener1 = new TestListener(); TestListener listener2 = new TestListener(); future.addListener(listener1); future.addListener(listener2); future.removeListener(listener1); TestThread thread = new TestThread(future); thread.start(); future.setClosed(); thread.join(); assertTrue(thread.success); assertTrue(future.isDone()); assertTrue(future.isClosed()); assertSame(null, listener1.notifiedFuture); assertSame(future, listener2.notifiedFuture); } @Test public void testRemoveListener2() throws Exception { DefaultCloseFuture future = new DefaultCloseFuture(null); assertFalse(future.isDone()); assertFalse(future.isClosed()); TestListener listener1 = new TestListener(); TestListener listener2 = new TestListener(); future.addListener(listener1); future.addListener(listener2); future.removeListener(listener2); TestThread thread = new TestThread(future); thread.start(); future.setClosed(); thread.join(); assertTrue(thread.success); assertTrue(future.isDone()); assertTrue(future.isClosed()); assertSame(future, listener1.notifiedFuture); assertSame(null, listener2.notifiedFuture); } private static class TestThread extends Thread { private final IoFuture future; boolean success; public TestThread(IoFuture future) { this.future = future; } @Override public void run() { success = future.awaitUninterruptibly(10000); } } private static class TestListener implements IoFutureListener { IoFuture notifiedFuture; /** * Default constructor */ public TestListener() { super(); } public void operationComplete(IoFuture future) { this.notifiedFuture = future; } } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/core/buffer/0000755000175000017500000000000012162575507025314 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/core/buffer/IoBufferTest.java0000644000175000017500000013042512032276015030511 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.buffer; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.nio.BufferOverflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.ReadOnlyBufferException; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.util.ArrayList; import java.util.Date; import java.util.EnumSet; import java.util.List; import org.apache.mina.util.Bar; import org.junit.Test; /** * Tests {@link IoBuffer}. * * @author Apache MINA Project */ public class IoBufferTest { private static interface NonserializableInterface { } public static class NonserializableClass { } @Test public void testNormalizeCapacity() { // A few sanity checks assertEquals(Integer.MAX_VALUE, IoBufferImpl.normalizeCapacity(-10)); assertEquals(0, IoBufferImpl.normalizeCapacity(0)); assertEquals(Integer.MAX_VALUE, IoBufferImpl.normalizeCapacity(Integer.MAX_VALUE)); assertEquals(Integer.MAX_VALUE, IoBufferImpl.normalizeCapacity(Integer.MIN_VALUE)); assertEquals(Integer.MAX_VALUE, IoBufferImpl.normalizeCapacity(Integer.MAX_VALUE - 10)); // A sanity check test for all the powers of 2 for (int i = 0; i < 30; i++) { int n = 1 << i; assertEquals(n, IoBufferImpl.normalizeCapacity(n)); if (i > 1) { // test that n - 1 will be normalized to n (notice that n = 2^i) assertEquals(n, IoBufferImpl.normalizeCapacity(n - 1)); } // test that n + 1 will be normalized to 2^(i + 1) assertEquals(n << 1, IoBufferImpl.normalizeCapacity(n + 1)); } // The first performance test measures the time to normalize integers // from 0 to 2^27 (it tests 2^27 integers) long time = System.currentTimeMillis(); for (int i = 0; i < 1 << 27; i++) { int n = IoBufferImpl.normalizeCapacity(i); // do a simple superfluous test to prevent possible compiler or JVM // optimizations of not executing non used code/variables if (n == -1) { System.out.println("n should never be -1"); } } long time2 = System.currentTimeMillis(); //System.out.println("Time for performance test 1: " + (time2 - time) + "ms"); // The second performance test measures the time to normalize integers // from Integer.MAX_VALUE to Integer.MAX_VALUE - 2^27 (it tests 2^27 // integers) time = System.currentTimeMillis(); for (int i = Integer.MAX_VALUE; i > Integer.MAX_VALUE - (1 << 27); i--) { int n = IoBufferImpl.normalizeCapacity(i); // do a simple superfluous test to prevent possible compiler or JVM // optimizations of not executing non used code/variables if (n == -1) { System.out.println("n should never be -1"); } } time2 = System.currentTimeMillis(); //System.out.println("Time for performance test 2: " + (time2 - time) + "ms"); } @Test public void autoExpand() { IoBuffer buffer = IoBuffer.allocate(8, false); buffer.setAutoExpand(true); assertTrue("Should AutoExpand", buffer.isAutoExpand()); IoBuffer slice = buffer.slice(); assertFalse("Should *NOT* AutoExpand", buffer.isAutoExpand()); assertFalse("Should *NOT* AutoExpand", slice.isAutoExpand()); } /** * This class extends the AbstractIoBuffer class to have direct access to * the protected IoBuffer.normalizeCapacity() method and to expose it for * the tests. */ private static class IoBufferImpl extends AbstractIoBuffer { public static int normalizeCapacity(int requestedCapacity) { return IoBuffer.normalizeCapacity(requestedCapacity); } protected IoBufferImpl(AbstractIoBuffer parent) { super(parent); } protected IoBuffer asReadOnlyBuffer0() { return null; } protected void buf(ByteBuffer newBuf) { } protected IoBuffer duplicate0() { return null; } protected IoBuffer slice0() { return null; } public byte[] array() { return null; } public int arrayOffset() { return 0; } public ByteBuffer buf() { return null; } public void free() { } public boolean hasArray() { return false; } } @Test public void testObjectSerialization() throws Exception { IoBuffer buf = IoBuffer.allocate(16); buf.setAutoExpand(true); List o = new ArrayList(); o.add(new Date()); o.add(long.class); // Test writing an object. buf.putObject(o); // Test reading an object. buf.clear(); Object o2 = buf.getObject(); assertEquals(o, o2); // This assertion is just to make sure that deserialization occurred. assertNotSame(o, o2); } @Test public void testNonserializableClass() throws Exception { Class c = NonserializableClass.class; IoBuffer buffer = IoBuffer.allocate(16); buffer.setAutoExpand(true); buffer.putObject(c); buffer.flip(); Object o = buffer.getObject(); assertEquals(c, o); assertSame(c, o); } @Test public void testNonserializableInterface() throws Exception { Class c = NonserializableInterface.class; IoBuffer buffer = IoBuffer.allocate(16); buffer.setAutoExpand(true); buffer.putObject(c); buffer.flip(); Object o = buffer.getObject(); assertEquals(c, o); assertSame(c, o); } @Test public void testAllocate() throws Exception { for (int i = 10; i < 1048576 * 2; i = i * 11 / 10) // increase by 10% { IoBuffer buf = IoBuffer.allocate(i); assertEquals(0, buf.position()); assertEquals(buf.capacity(), buf.remaining()); assertTrue(buf.capacity() >= i); assertTrue(buf.capacity() < i * 2); } } @Test public void testAutoExpand() throws Exception { IoBuffer buf = IoBuffer.allocate(1); buf.put((byte) 0); try { buf.put((byte) 0); fail("Buffer can't auto expand, with autoExpand property set at false"); } catch (BufferOverflowException e) { // Expected Exception as auto expand property is false assertTrue(true); } buf.setAutoExpand(true); buf.put((byte) 0); assertEquals(2, buf.position()); assertEquals(2, buf.limit()); assertEquals(2, buf.capacity()); buf.setAutoExpand(false); try { buf.put(3, (byte) 0); fail("Buffer can't auto expand, with autoExpand property set at false"); } catch (IndexOutOfBoundsException e) { // Expected Exception as auto expand property is false assertTrue(true); } buf.setAutoExpand(true); buf.put(3, (byte) 0); assertEquals(2, buf.position()); assertEquals(4, buf.limit()); assertEquals(4, buf.capacity()); // Make sure the buffer is doubled up. buf = IoBuffer.allocate(1).setAutoExpand(true); int lastCapacity = buf.capacity(); for (int i = 0; i < 1048576; i++) { buf.put((byte) 0); if (lastCapacity != buf.capacity()) { assertEquals(lastCapacity * 2, buf.capacity()); lastCapacity = buf.capacity(); } } } @Test public void testAutoExpandMark() throws Exception { IoBuffer buf = IoBuffer.allocate(4).setAutoExpand(true); buf.put((byte) 0); buf.put((byte) 0); buf.put((byte) 0); // Position should be 3 when we reset this buffer. buf.mark(); // Overflow it buf.put((byte) 0); buf.put((byte) 0); assertEquals(5, buf.position()); buf.reset(); assertEquals(3, buf.position()); } @Test public void testAutoShrink() throws Exception { IoBuffer buf = IoBuffer.allocate(8).setAutoShrink(true); // Make sure the buffer doesn't shrink too much (less than the initial // capacity.) buf.sweep((byte) 1); buf.fill(7); buf.compact(); assertEquals(8, buf.capacity()); assertEquals(1, buf.position()); assertEquals(8, buf.limit()); buf.clear(); assertEquals(1, buf.get()); // Expand the buffer. buf.capacity(32).clear(); assertEquals(32, buf.capacity()); // Make sure the buffer shrinks when only 1/4 is being used. buf.sweep((byte) 1); buf.fill(24); buf.compact(); assertEquals(16, buf.capacity()); assertEquals(8, buf.position()); assertEquals(16, buf.limit()); buf.clear(); for (int i = 0; i < 8; i++) { assertEquals(1, buf.get()); } // Expand the buffer. buf.capacity(32).clear(); assertEquals(32, buf.capacity()); // Make sure the buffer shrinks when only 1/8 is being used. buf.sweep((byte) 1); buf.fill(28); buf.compact(); assertEquals(8, buf.capacity()); assertEquals(4, buf.position()); assertEquals(8, buf.limit()); buf.clear(); for (int i = 0; i < 4; i++) { assertEquals(1, buf.get()); } // Expand the buffer. buf.capacity(32).clear(); assertEquals(32, buf.capacity()); // Make sure the buffer shrinks when 0 byte is being used. buf.fill(32); buf.compact(); assertEquals(8, buf.capacity()); assertEquals(0, buf.position()); assertEquals(8, buf.limit()); // Expand the buffer. buf.capacity(32).clear(); assertEquals(32, buf.capacity()); // Make sure the buffer doesn't shrink when more than 1/4 is being used. buf.sweep((byte) 1); buf.fill(23); buf.compact(); assertEquals(32, buf.capacity()); assertEquals(9, buf.position()); assertEquals(32, buf.limit()); buf.clear(); for (int i = 0; i < 9; i++) { assertEquals(1, buf.get()); } } @Test public void testGetString() throws Exception { IoBuffer buf = IoBuffer.allocate(16); CharsetDecoder decoder; Charset charset = Charset.forName("UTF-8"); buf.clear(); buf.putString("hello", charset.newEncoder()); buf.put((byte) 0); buf.flip(); assertEquals("hello", buf.getString(charset.newDecoder())); buf.clear(); buf.putString("hello", charset.newEncoder()); buf.flip(); assertEquals("hello", buf.getString(charset.newDecoder())); decoder = Charset.forName("ISO-8859-1").newDecoder(); buf.clear(); buf.put((byte) 'A'); buf.put((byte) 'B'); buf.put((byte) 'C'); buf.put((byte) 0); buf.position(0); assertEquals("ABC", buf.getString(decoder)); assertEquals(4, buf.position()); buf.position(0); buf.limit(1); assertEquals("A", buf.getString(decoder)); assertEquals(1, buf.position()); buf.clear(); assertEquals("ABC", buf.getString(10, decoder)); assertEquals(10, buf.position()); buf.clear(); assertEquals("A", buf.getString(1, decoder)); assertEquals(1, buf.position()); // Test a trailing garbage buf.clear(); buf.put((byte) 'A'); buf.put((byte) 'B'); buf.put((byte) 0); buf.put((byte) 'C'); buf.position(0); assertEquals("AB", buf.getString(4, decoder)); assertEquals(4, buf.position()); buf.clear(); buf.fillAndReset(buf.limit()); decoder = Charset.forName("UTF-16").newDecoder(); buf.put((byte) 0); buf.put((byte) 'A'); buf.put((byte) 0); buf.put((byte) 'B'); buf.put((byte) 0); buf.put((byte) 'C'); buf.put((byte) 0); buf.put((byte) 0); buf.position(0); assertEquals("ABC", buf.getString(decoder)); assertEquals(8, buf.position()); buf.position(0); buf.limit(2); assertEquals("A", buf.getString(decoder)); assertEquals(2, buf.position()); buf.position(0); buf.limit(3); assertEquals("A", buf.getString(decoder)); assertEquals(2, buf.position()); buf.clear(); assertEquals("ABC", buf.getString(10, decoder)); assertEquals(10, buf.position()); buf.clear(); assertEquals("A", buf.getString(2, decoder)); assertEquals(2, buf.position()); buf.clear(); try { buf.getString(1, decoder); fail(); } catch (IllegalArgumentException e) { // Expected an Exception, signifies test success assertTrue(true); } // Test getting strings from an empty buffer. buf.clear(); buf.limit(0); assertEquals("", buf.getString(decoder)); assertEquals("", buf.getString(2, decoder)); // Test getting strings from non-empty buffer which is filled with 0x00 buf.clear(); buf.putInt(0); buf.clear(); buf.limit(4); assertEquals("", buf.getString(decoder)); assertEquals(2, buf.position()); assertEquals(4, buf.limit()); buf.position(0); assertEquals("", buf.getString(2, decoder)); assertEquals(2, buf.position()); assertEquals(4, buf.limit()); } @Test public void testGetStringWithFailure() throws Exception { String test = "\u30b3\u30e1\u30f3\u30c8\u7de8\u96c6"; IoBuffer buffer = IoBuffer.wrap(test.getBytes("Shift_JIS")); // Make sure the limit doesn't change when an exception arose. int oldLimit = buffer.limit(); int oldPos = buffer.position(); try { buffer.getString(3, Charset.forName("ASCII").newDecoder()); fail(); } catch (Exception e) { assertEquals(oldLimit, buffer.limit()); assertEquals(oldPos, buffer.position()); } try { buffer.getString(Charset.forName("ASCII").newDecoder()); fail(); } catch (Exception e) { assertEquals(oldLimit, buffer.limit()); assertEquals(oldPos, buffer.position()); } } @Test public void testPutString() throws Exception { CharsetEncoder encoder; IoBuffer buf = IoBuffer.allocate(16); encoder = Charset.forName("ISO-8859-1").newEncoder(); buf.putString("ABC", encoder); assertEquals(3, buf.position()); buf.clear(); assertEquals('A', buf.get(0)); assertEquals('B', buf.get(1)); assertEquals('C', buf.get(2)); buf.putString("D", 5, encoder); assertEquals(5, buf.position()); buf.clear(); assertEquals('D', buf.get(0)); assertEquals(0, buf.get(1)); buf.putString("EFG", 2, encoder); assertEquals(2, buf.position()); buf.clear(); assertEquals('E', buf.get(0)); assertEquals('F', buf.get(1)); assertEquals('C', buf.get(2)); // C may not be overwritten // UTF-16: We specify byte order to omit BOM. encoder = Charset.forName("UTF-16BE").newEncoder(); buf.clear(); buf.putString("ABC", encoder); assertEquals(6, buf.position()); buf.clear(); assertEquals(0, buf.get(0)); assertEquals('A', buf.get(1)); assertEquals(0, buf.get(2)); assertEquals('B', buf.get(3)); assertEquals(0, buf.get(4)); assertEquals('C', buf.get(5)); buf.putString("D", 10, encoder); assertEquals(10, buf.position()); buf.clear(); assertEquals(0, buf.get(0)); assertEquals('D', buf.get(1)); assertEquals(0, buf.get(2)); assertEquals(0, buf.get(3)); buf.putString("EFG", 4, encoder); assertEquals(4, buf.position()); buf.clear(); assertEquals(0, buf.get(0)); assertEquals('E', buf.get(1)); assertEquals(0, buf.get(2)); assertEquals('F', buf.get(3)); assertEquals(0, buf.get(4)); // C may not be overwritten assertEquals('C', buf.get(5)); // C may not be overwritten // Test putting an emptry string buf.putString("", encoder); assertEquals(0, buf.position()); buf.putString("", 4, encoder); assertEquals(4, buf.position()); assertEquals(0, buf.get(0)); assertEquals(0, buf.get(1)); } @Test public void testGetPrefixedString() throws Exception { IoBuffer buf = IoBuffer.allocate(16); CharsetEncoder encoder; CharsetDecoder decoder; encoder = Charset.forName("ISO-8859-1").newEncoder(); decoder = Charset.forName("ISO-8859-1").newDecoder(); buf.putShort((short) 3); buf.putString("ABCD", encoder); buf.clear(); assertEquals("ABC", buf.getPrefixedString(decoder)); } @Test public void testPutPrefixedString() throws Exception { CharsetEncoder encoder; IoBuffer buf = IoBuffer.allocate(16); buf.fillAndReset(buf.remaining()); encoder = Charset.forName("ISO-8859-1").newEncoder(); // Without autoExpand buf.putPrefixedString("ABC", encoder); assertEquals(5, buf.position()); assertEquals(0, buf.get(0)); assertEquals(3, buf.get(1)); assertEquals('A', buf.get(2)); assertEquals('B', buf.get(3)); assertEquals('C', buf.get(4)); buf.clear(); try { buf.putPrefixedString("123456789012345", encoder); fail(); } catch (BufferOverflowException e) { // Expected an Exception, signifies test success assertTrue(true); } // With autoExpand buf.clear(); buf.setAutoExpand(true); buf.putPrefixedString("123456789012345", encoder); assertEquals(17, buf.position()); assertEquals(0, buf.get(0)); assertEquals(15, buf.get(1)); assertEquals('1', buf.get(2)); assertEquals('2', buf.get(3)); assertEquals('3', buf.get(4)); assertEquals('4', buf.get(5)); assertEquals('5', buf.get(6)); assertEquals('6', buf.get(7)); assertEquals('7', buf.get(8)); assertEquals('8', buf.get(9)); assertEquals('9', buf.get(10)); assertEquals('0', buf.get(11)); assertEquals('1', buf.get(12)); assertEquals('2', buf.get(13)); assertEquals('3', buf.get(14)); assertEquals('4', buf.get(15)); assertEquals('5', buf.get(16)); } @Test public void testPutPrefixedStringWithPrefixLength() throws Exception { CharsetEncoder encoder = Charset.forName("ISO-8859-1").newEncoder(); IoBuffer buf = IoBuffer.allocate(16).sweep().setAutoExpand(true); buf.putPrefixedString("A", 1, encoder); assertEquals(2, buf.position()); assertEquals(1, buf.get(0)); assertEquals('A', buf.get(1)); buf.sweep(); buf.putPrefixedString("A", 2, encoder); assertEquals(3, buf.position()); assertEquals(0, buf.get(0)); assertEquals(1, buf.get(1)); assertEquals('A', buf.get(2)); buf.sweep(); buf.putPrefixedString("A", 4, encoder); assertEquals(5, buf.position()); assertEquals(0, buf.get(0)); assertEquals(0, buf.get(1)); assertEquals(0, buf.get(2)); assertEquals(1, buf.get(3)); assertEquals('A', buf.get(4)); } @Test public void testPutPrefixedStringWithPadding() throws Exception { CharsetEncoder encoder = Charset.forName("ISO-8859-1").newEncoder(); IoBuffer buf = IoBuffer.allocate(16).sweep().setAutoExpand(true); buf.putPrefixedString("A", 1, 2, (byte) 32, encoder); assertEquals(3, buf.position()); assertEquals(2, buf.get(0)); assertEquals('A', buf.get(1)); assertEquals(' ', buf.get(2)); buf.sweep(); buf.putPrefixedString("A", 1, 4, (byte) 32, encoder); assertEquals(5, buf.position()); assertEquals(4, buf.get(0)); assertEquals('A', buf.get(1)); assertEquals(' ', buf.get(2)); assertEquals(' ', buf.get(3)); assertEquals(' ', buf.get(4)); } @Test public void testWideUtf8Characters() throws Exception { Runnable r = new Runnable() { public void run() { IoBuffer buffer = IoBuffer.allocate(1); buffer.setAutoExpand(true); Charset charset = Charset.forName("UTF-8"); CharsetEncoder encoder = charset.newEncoder(); for (int i = 0; i < 5; i++) { try { buffer.putString("\u89d2", encoder); buffer.putPrefixedString("\u89d2", encoder); } catch (CharacterCodingException e) { fail(e.getMessage()); } } } }; Thread t = new Thread(r); t.setDaemon(true); t.start(); for (int i = 0; i < 50; i++) { Thread.sleep(100); if (!t.isAlive()) { break; } } if (t.isAlive()) { t.interrupt(); fail("Went into endless loop trying to encode character"); } } @Test public void testInheritedObjectSerialization() throws Exception { IoBuffer buf = IoBuffer.allocate(16); buf.setAutoExpand(true); Bar expected = new Bar(); expected.setFooValue(0x12345678); expected.setBarValue(0x90ABCDEF); // Test writing an object. buf.putObject(expected); // Test reading an object. buf.clear(); Bar actual = (Bar) buf.getObject(); assertSame(Bar.class, actual.getClass()); assertEquals(expected.getFooValue(), actual.getFooValue()); assertEquals(expected.getBarValue(), actual.getBarValue()); // This assertion is just to make sure that deserialization occurred. assertNotSame(expected, actual); } @Test public void testSweepWithZeros() throws Exception { IoBuffer buf = IoBuffer.allocate(4); buf.putInt(0xdeadbeef); buf.clear(); assertEquals(0xdeadbeef, buf.getInt()); assertEquals(4, buf.position()); assertEquals(4, buf.limit()); buf.sweep(); assertEquals(0, buf.position()); assertEquals(4, buf.limit()); assertEquals(0x0, buf.getInt()); } @Test public void testSweepNonZeros() throws Exception { IoBuffer buf = IoBuffer.allocate(4); buf.putInt(0xdeadbeef); buf.clear(); assertEquals(0xdeadbeef, buf.getInt()); assertEquals(4, buf.position()); assertEquals(4, buf.limit()); buf.sweep((byte) 0x45); assertEquals(0, buf.position()); assertEquals(4, buf.limit()); assertEquals(0x45454545, buf.getInt()); } @Test public void testWrapNioBuffer() throws Exception { ByteBuffer nioBuf = ByteBuffer.allocate(10); nioBuf.position(3); nioBuf.limit(7); IoBuffer buf = IoBuffer.wrap(nioBuf); assertEquals(3, buf.position()); assertEquals(7, buf.limit()); assertEquals(10, buf.capacity()); } @Test public void testWrapSubArray() throws Exception { byte[] array = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; IoBuffer buf = IoBuffer.wrap(array, 3, 4); assertEquals(3, buf.position()); assertEquals(7, buf.limit()); assertEquals(10, buf.capacity()); buf.clear(); assertEquals(0, buf.position()); assertEquals(10, buf.limit()); assertEquals(10, buf.capacity()); } @Test public void testDuplicate() throws Exception { IoBuffer original; IoBuffer duplicate; // Test if the buffer is duplicated correctly. original = IoBuffer.allocate(16).sweep(); original.position(4); original.limit(10); duplicate = original.duplicate(); original.put(4, (byte) 127); assertEquals(4, duplicate.position()); assertEquals(10, duplicate.limit()); assertEquals(16, duplicate.capacity()); assertNotSame(original.buf(), duplicate.buf()); assertSame(original.buf().array(), duplicate.buf().array()); assertEquals(127, duplicate.get(4)); // Test a duplicate of a duplicate. original = IoBuffer.allocate(16); duplicate = original.duplicate().duplicate(); assertNotSame(original.buf(), duplicate.buf()); assertSame(original.buf().array(), duplicate.buf().array()); // Try to expand. original = IoBuffer.allocate(16); original.setAutoExpand(true); duplicate = original.duplicate(); assertFalse(original.isAutoExpand()); try { original.setAutoExpand(true); fail("Derived buffers and their parent can't be expanded"); } catch (IllegalStateException e) { // Expected an Exception, signifies test success assertTrue(true); } try { duplicate.setAutoExpand(true); fail("Derived buffers and their parent can't be expanded"); } catch (IllegalStateException e) { // Expected an Exception, signifies test success assertTrue(true); } } @Test public void testSlice() throws Exception { IoBuffer original; IoBuffer slice; // Test if the buffer is sliced correctly. original = IoBuffer.allocate(16).sweep(); original.position(4); original.limit(10); slice = original.slice(); original.put(4, (byte) 127); assertEquals(0, slice.position()); assertEquals(6, slice.limit()); assertEquals(6, slice.capacity()); assertNotSame(original.buf(), slice.buf()); assertEquals(127, slice.get(0)); } @Test public void testReadOnlyBuffer() throws Exception { IoBuffer original; IoBuffer duplicate; // Test if the buffer is duplicated correctly. original = IoBuffer.allocate(16).sweep(); original.position(4); original.limit(10); duplicate = original.asReadOnlyBuffer(); original.put(4, (byte) 127); assertEquals(4, duplicate.position()); assertEquals(10, duplicate.limit()); assertEquals(16, duplicate.capacity()); assertNotSame(original.buf(), duplicate.buf()); assertEquals(127, duplicate.get(4)); // Try to expand. try { original = IoBuffer.allocate(16); duplicate = original.asReadOnlyBuffer(); duplicate.putString("A very very very very looooooong string", Charset.forName("ISO-8859-1").newEncoder()); fail("ReadOnly buffer's can't be expanded"); } catch (ReadOnlyBufferException e) { // Expected an Exception, signifies test success assertTrue(true); } } @Test public void testGetUnsigned() throws Exception { IoBuffer buf = IoBuffer.allocate(16); buf.put((byte) 0xA4); buf.put((byte) 0xD0); buf.put((byte) 0xB3); buf.put((byte) 0xCD); buf.flip(); buf.order(ByteOrder.LITTLE_ENDIAN); buf.mark(); assertEquals(0xA4, buf.getUnsigned()); buf.reset(); assertEquals(0xD0A4, buf.getUnsignedShort()); buf.reset(); assertEquals(0xCDB3D0A4L, buf.getUnsignedInt()); } @Test public void testIndexOf() throws Exception { boolean direct = false; for (int i = 0; i < 2; i++, direct = !direct) { IoBuffer buf = IoBuffer.allocate(16, direct); buf.put((byte) 0x1); buf.put((byte) 0x2); buf.put((byte) 0x3); buf.put((byte) 0x4); buf.put((byte) 0x1); buf.put((byte) 0x2); buf.put((byte) 0x3); buf.put((byte) 0x4); buf.position(2); buf.limit(5); assertEquals(4, buf.indexOf((byte) 0x1)); assertEquals(-1, buf.indexOf((byte) 0x2)); assertEquals(2, buf.indexOf((byte) 0x3)); assertEquals(3, buf.indexOf((byte) 0x4)); } } // We need an enum with 64 values private static enum TestEnum { E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E28, E29, E30, E31, E32, E33, E34, E35, E36, E37, E38, E39, E40, E41, E42, E43, E44, E45, E46, E77, E48, E49, E50, E51, E52, E53, E54, E55, E56, E57, E58, E59, E60, E61, E62, E63, E64 } private static enum TooBigEnum { E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E28, E29, E30, E31, E32, E33, E34, E35, E36, E37, E38, E39, E40, E41, E42, E43, E44, E45, E46, E77, E48, E49, E50, E51, E52, E53, E54, E55, E56, E57, E58, E59, E60, E61, E62, E63, E64, E65 } @Test public void testPutEnumSet() { IoBuffer buf = IoBuffer.allocate(8); // Test empty set buf.putEnumSet(EnumSet.noneOf(TestEnum.class)); buf.flip(); assertEquals(0, buf.get()); buf.clear(); buf.putEnumSetShort(EnumSet.noneOf(TestEnum.class)); buf.flip(); assertEquals(0, buf.getShort()); buf.clear(); buf.putEnumSetInt(EnumSet.noneOf(TestEnum.class)); buf.flip(); assertEquals(0, buf.getInt()); buf.clear(); buf.putEnumSetLong(EnumSet.noneOf(TestEnum.class)); buf.flip(); assertEquals(0, buf.getLong()); // Test complete set buf.clear(); buf.putEnumSet(EnumSet.range(TestEnum.E1, TestEnum.E8)); buf.flip(); assertEquals((byte) -1, buf.get()); buf.clear(); buf.putEnumSetShort(EnumSet.range(TestEnum.E1, TestEnum.E16)); buf.flip(); assertEquals((short) -1, buf.getShort()); buf.clear(); buf.putEnumSetInt(EnumSet.range(TestEnum.E1, TestEnum.E32)); buf.flip(); assertEquals(-1, buf.getInt()); buf.clear(); buf.putEnumSetLong(EnumSet.allOf(TestEnum.class)); buf.flip(); assertEquals(-1L, buf.getLong()); // Test high bit set buf.clear(); buf.putEnumSet(EnumSet.of(TestEnum.E8)); buf.flip(); assertEquals(Byte.MIN_VALUE, buf.get()); buf.clear(); buf.putEnumSetShort(EnumSet.of(TestEnum.E16)); buf.flip(); assertEquals(Short.MIN_VALUE, buf.getShort()); buf.clear(); buf.putEnumSetInt(EnumSet.of(TestEnum.E32)); buf.flip(); assertEquals(Integer.MIN_VALUE, buf.getInt()); buf.clear(); buf.putEnumSetLong(EnumSet.of(TestEnum.E64)); buf.flip(); assertEquals(Long.MIN_VALUE, buf.getLong()); // Test high low bits set buf.clear(); buf.putEnumSet(EnumSet.of(TestEnum.E1, TestEnum.E8)); buf.flip(); assertEquals(Byte.MIN_VALUE + 1, buf.get()); buf.clear(); buf.putEnumSetShort(EnumSet.of(TestEnum.E1, TestEnum.E16)); buf.flip(); assertEquals(Short.MIN_VALUE + 1, buf.getShort()); buf.clear(); buf.putEnumSetInt(EnumSet.of(TestEnum.E1, TestEnum.E32)); buf.flip(); assertEquals(Integer.MIN_VALUE + 1, buf.getInt()); buf.clear(); buf.putEnumSetLong(EnumSet.of(TestEnum.E1, TestEnum.E64)); buf.flip(); assertEquals(Long.MIN_VALUE + 1, buf.getLong()); } @Test public void testGetEnumSet() { IoBuffer buf = IoBuffer.allocate(8); // Test empty set buf.put((byte) 0); buf.flip(); assertEquals(EnumSet.noneOf(TestEnum.class), buf.getEnumSet(TestEnum.class)); buf.clear(); buf.putShort((short) 0); buf.flip(); assertEquals(EnumSet.noneOf(TestEnum.class), buf.getEnumSet(TestEnum.class)); buf.clear(); buf.putInt(0); buf.flip(); assertEquals(EnumSet.noneOf(TestEnum.class), buf.getEnumSet(TestEnum.class)); buf.clear(); buf.putLong(0L); buf.flip(); assertEquals(EnumSet.noneOf(TestEnum.class), buf.getEnumSet(TestEnum.class)); // Test complete set buf.clear(); buf.put((byte) -1); buf.flip(); assertEquals(EnumSet.range(TestEnum.E1, TestEnum.E8), buf.getEnumSet(TestEnum.class)); buf.clear(); buf.putShort((short) -1); buf.flip(); assertEquals(EnumSet.range(TestEnum.E1, TestEnum.E16), buf.getEnumSetShort(TestEnum.class)); buf.clear(); buf.putInt(-1); buf.flip(); assertEquals(EnumSet.range(TestEnum.E1, TestEnum.E32), buf.getEnumSetInt(TestEnum.class)); buf.clear(); buf.putLong(-1L); buf.flip(); assertEquals(EnumSet.allOf(TestEnum.class), buf.getEnumSetLong(TestEnum.class)); // Test high bit set buf.clear(); buf.put(Byte.MIN_VALUE); buf.flip(); assertEquals(EnumSet.of(TestEnum.E8), buf.getEnumSet(TestEnum.class)); buf.clear(); buf.putShort(Short.MIN_VALUE); buf.flip(); assertEquals(EnumSet.of(TestEnum.E16), buf.getEnumSetShort(TestEnum.class)); buf.clear(); buf.putInt(Integer.MIN_VALUE); buf.flip(); assertEquals(EnumSet.of(TestEnum.E32), buf.getEnumSetInt(TestEnum.class)); buf.clear(); buf.putLong(Long.MIN_VALUE); buf.flip(); assertEquals(EnumSet.of(TestEnum.E64), buf.getEnumSetLong(TestEnum.class)); // Test high low bits set buf.clear(); byte b = Byte.MIN_VALUE + 1; buf.put(b); buf.flip(); assertEquals(EnumSet.of(TestEnum.E1, TestEnum.E8), buf.getEnumSet(TestEnum.class)); buf.clear(); short s = Short.MIN_VALUE + 1; buf.putShort(s); buf.flip(); assertEquals(EnumSet.of(TestEnum.E1, TestEnum.E16), buf.getEnumSetShort(TestEnum.class)); buf.clear(); buf.putInt(Integer.MIN_VALUE + 1); buf.flip(); assertEquals(EnumSet.of(TestEnum.E1, TestEnum.E32), buf.getEnumSetInt(TestEnum.class)); buf.clear(); buf.putLong(Long.MIN_VALUE + 1); buf.flip(); assertEquals(EnumSet.of(TestEnum.E1, TestEnum.E64), buf.getEnumSetLong(TestEnum.class)); } @Test public void testBitVectorOverFlow() { IoBuffer buf = IoBuffer.allocate(8); try { buf.putEnumSet(EnumSet.of(TestEnum.E9)); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException e) { // Expected an Exception, signifies test success assertTrue(true); } try { buf.putEnumSetShort(EnumSet.of(TestEnum.E17)); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException e) { // Expected an Exception, signifies test success assertTrue(true); } try { buf.putEnumSetInt(EnumSet.of(TestEnum.E33)); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException e) { // Expected an Exception, signifies test success assertTrue(true); } try { buf.putEnumSetLong(EnumSet.of(TooBigEnum.E65)); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException e) { // Expected an Exception, signifies test success assertTrue(true); } } @Test public void testGetPutEnum() { IoBuffer buf = IoBuffer.allocate(4); buf.putEnum(TestEnum.E64); buf.flip(); assertEquals(TestEnum.E64, buf.getEnum(TestEnum.class)); buf.clear(); buf.putEnumShort(TestEnum.E64); buf.flip(); assertEquals(TestEnum.E64, buf.getEnumShort(TestEnum.class)); buf.clear(); buf.putEnumInt(TestEnum.E64); buf.flip(); assertEquals(TestEnum.E64, buf.getEnumInt(TestEnum.class)); } @Test public void testGetMediumInt() { IoBuffer buf = IoBuffer.allocate(3); buf.put((byte) 0x01); buf.put((byte) 0x02); buf.put((byte) 0x03); assertEquals(3, buf.position()); buf.flip(); assertEquals(0x010203, buf.getMediumInt()); assertEquals(0x010203, buf.getMediumInt(0)); buf.flip(); assertEquals(0x010203, buf.getUnsignedMediumInt()); assertEquals(0x010203, buf.getUnsignedMediumInt(0)); buf.flip(); assertEquals(0x010203, buf.getUnsignedMediumInt()); buf.flip().order(ByteOrder.LITTLE_ENDIAN); assertEquals(0x030201, buf.getMediumInt()); assertEquals(0x030201, buf.getMediumInt(0)); // Test max medium int buf.flip().order(ByteOrder.BIG_ENDIAN); buf.put((byte) 0x7f); buf.put((byte) 0xff); buf.put((byte) 0xff); buf.flip(); assertEquals(0x7fffff, buf.getMediumInt()); assertEquals(0x7fffff, buf.getMediumInt(0)); // Test negative number buf.flip().order(ByteOrder.BIG_ENDIAN); buf.put((byte) 0xff); buf.put((byte) 0x02); buf.put((byte) 0x03); buf.flip(); assertEquals(0xffff0203, buf.getMediumInt()); assertEquals(0xffff0203, buf.getMediumInt(0)); buf.flip(); assertEquals(0x00ff0203, buf.getUnsignedMediumInt()); assertEquals(0x00ff0203, buf.getUnsignedMediumInt(0)); } @Test public void testPutMediumInt() { IoBuffer buf = IoBuffer.allocate(3); checkMediumInt(buf, 0); checkMediumInt(buf, 1); checkMediumInt(buf, -1); checkMediumInt(buf, 0x7fffff); } private void checkMediumInt(IoBuffer buf, int x) { buf.putMediumInt(x); assertEquals(3, buf.position()); buf.flip(); assertEquals(x, buf.getMediumInt()); assertEquals(3, buf.position()); buf.putMediumInt(0, x); assertEquals(3, buf.position()); assertEquals(x, buf.getMediumInt(0)); buf.flip(); } @Test public void testPutUnsigned() { IoBuffer buf = IoBuffer.allocate(4); byte b = (byte) 0x80; // We should get 0x0080 short s = (short) 0x8F81; // We should get 0x0081 int i = 0x8FFFFF82; // We should get 0x0082 long l = 0x8FFFFFFFFFFFFF83L; // We should get 0x0083 buf.mark(); // Put the unsigned bytes buf.putUnsigned(b); buf.putUnsigned(s); buf.putUnsigned(i); buf.putUnsigned(l); buf.reset(); // Read back the unsigned bytes assertEquals(0x0080, buf.getUnsigned()); assertEquals(0x0081, buf.getUnsigned()); assertEquals(0x0082, buf.getUnsigned()); assertEquals(0x0083, buf.getUnsigned()); } @Test public void testPutUnsignedIndex() { IoBuffer buf = IoBuffer.allocate(4); byte b = (byte) 0x80; // We should get 0x0080 short s = (short) 0x8F81; // We should get 0x0081 int i = 0x8FFFFF82; // We should get 0x0082 long l = 0x8FFFFFFFFFFFFF83L; // We should get 0x0083 buf.mark(); // Put the unsigned bytes buf.putUnsigned(3, b); buf.putUnsigned(2, s); buf.putUnsigned(1, i); buf.putUnsigned(0, l); buf.reset(); // Read back the unsigned bytes assertEquals(0x0083, buf.getUnsigned()); assertEquals(0x0082, buf.getUnsigned()); assertEquals(0x0081, buf.getUnsigned()); assertEquals(0x0080, buf.getUnsigned()); } @Test public void testPutUnsignedShort() { IoBuffer buf = IoBuffer.allocate(8); byte b = (byte) 0x80; // We should get 0x0080 short s = (short) 0x8181; // We should get 0x8181 int i = 0x82828282; // We should get 0x8282 long l = 0x8383838383838383L; // We should get 0x8383 buf.mark(); // Put the unsigned bytes buf.putUnsignedShort(b); buf.putUnsignedShort(s); buf.putUnsignedShort(i); buf.putUnsignedShort(l); buf.reset(); // Read back the unsigned bytes assertEquals(0x0080L, buf.getUnsignedShort()); assertEquals(0x8181L, buf.getUnsignedShort()); assertEquals(0x8282L, buf.getUnsignedShort()); assertEquals(0x8383L, buf.getUnsignedShort()); } @Test public void testPutUnsignedShortIndex() { IoBuffer buf = IoBuffer.allocate(8); byte b = (byte) 0x80; // We should get 0x00000080 short s = (short) 0x8181; // We should get 0x00008181 int i = 0x82828282; // We should get 0x82828282 long l = 0x8383838383838383L; // We should get 0x83838383 buf.mark(); // Put the unsigned shorts buf.putUnsignedShort(6, b); buf.putUnsignedShort(4, s); buf.putUnsignedShort(2, i); buf.putUnsignedShort(0, l); buf.reset(); // Read back the unsigned bytes assertEquals(0x8383L, buf.getUnsignedShort()); assertEquals(0x8282L, buf.getUnsignedShort()); assertEquals(0x8181L, buf.getUnsignedShort()); assertEquals(0x0080L, buf.getUnsignedShort()); } @Test public void testPutUnsignedInt() { IoBuffer buf = IoBuffer.allocate(16); byte b = (byte) 0x80; // We should get 0x00000080 short s = (short) 0x8181; // We should get 0x00008181 int i = 0x82828282; // We should get 0x82828282 long l = 0x8383838383838383L; // We should get 0x83838383 buf.mark(); // Put the unsigned bytes buf.putUnsignedInt(b); buf.putUnsignedInt(s); buf.putUnsignedInt(i); buf.putUnsignedInt(l); buf.reset(); // Read back the unsigned bytes assertEquals(0x0000000000000080L, buf.getUnsignedInt()); assertEquals(0x0000000000008181L, buf.getUnsignedInt()); assertEquals(0x0000000082828282L, buf.getUnsignedInt()); assertEquals(0x0000000083838383L, buf.getUnsignedInt()); } @Test public void testPutUnsignedIntIndex() { IoBuffer buf = IoBuffer.allocate(16); byte b = (byte) 0x80; // We should get 0x00000080 short s = (short) 0x8181; // We should get 0x00008181 int i = 0x82828282; // We should get 0x82828282 long l = 0x8383838383838383L; // We should get 0x83838383 buf.mark(); // Put the unsigned bytes buf.putUnsignedInt(12, b); buf.putUnsignedInt(8, s); buf.putUnsignedInt(4, i); buf.putUnsignedInt(0, l); buf.reset(); // Read back the unsigned bytes assertEquals(0x0000000083838383L, buf.getUnsignedInt()); assertEquals(0x0000000082828282L, buf.getUnsignedInt()); assertEquals(0x0000000000008181L, buf.getUnsignedInt()); assertEquals(0x0000000000000080L, buf.getUnsignedInt()); } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/core/IoFilterChainTest.java0000644000175000017500000002434212032276016030220 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core; import org.apache.mina.core.filterchain.DefaultIoFilterChain; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.filterchain.IoFilterChain.Entry; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.DummySession; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.DefaultWriteRequest; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.filter.util.NoopFilter; import org.junit.After; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; /** * Tests {@link DefaultIoFilterChain}. * * @author Apache MINA Project */ public class IoFilterChainTest { private DummySession dummySession; private IoFilterChain chain; String testResult; private final IoHandler handler = new IoHandlerAdapter() { @Override public void sessionCreated(IoSession session) { testResult += "HS0"; } @Override public void sessionOpened(IoSession session) { testResult += "HSO"; } @Override public void sessionClosed(IoSession session) { testResult += "HSC"; } @Override public void sessionIdle(IoSession session, IdleStatus status) { testResult += "HSI"; } @Override public void exceptionCaught(IoSession session, Throwable cause) { testResult += "HEC"; if (cause.getClass() != Exception.class) { //cause.printStackTrace(System.out); } } @Override public void messageReceived(IoSession session, Object message) { testResult += "HMR"; } @Override public void messageSent(IoSession session, Object message) { testResult += "HMS"; } }; @Before public void setUp() { dummySession = new DummySession(); dummySession.setHandler(handler); chain = dummySession.getFilterChain(); testResult = ""; } @After public void tearDown() { // Do nothing } @Test public void testAdd() throws Exception { chain.addFirst("A", new EventOrderTestFilter('A')); chain.addLast("B", new EventOrderTestFilter('A')); chain.addFirst("C", new EventOrderTestFilter('A')); chain.addLast("D", new EventOrderTestFilter('A')); chain.addBefore("B", "E", new EventOrderTestFilter('A')); chain.addBefore("C", "F", new EventOrderTestFilter('A')); chain.addAfter("B", "G", new EventOrderTestFilter('A')); chain.addAfter("D", "H", new EventOrderTestFilter('A')); String actual = ""; for (Entry e : chain.getAll()) { actual += e.getName(); } assertEquals("FCAEBGDH", actual); } @Test public void testGet() throws Exception { IoFilter filterA = new NoopFilter(); IoFilter filterB = new NoopFilter(); IoFilter filterC = new NoopFilter(); IoFilter filterD = new NoopFilter(); chain.addFirst("A", filterA); chain.addLast("B", filterB); chain.addBefore("B", "C", filterC); chain.addAfter("A", "D", filterD); assertSame(filterA, chain.get("A")); assertSame(filterB, chain.get("B")); assertSame(filterC, chain.get("C")); assertSame(filterD, chain.get("D")); } @Test public void testRemove() throws Exception { chain.addLast("A", new EventOrderTestFilter('A')); chain.addLast("B", new EventOrderTestFilter('A')); chain.addLast("C", new EventOrderTestFilter('A')); chain.addLast("D", new EventOrderTestFilter('A')); chain.addLast("E", new EventOrderTestFilter('A')); chain.remove("A"); chain.remove("E"); chain.remove("C"); chain.remove("B"); chain.remove("D"); assertEquals(0, chain.getAll().size()); } @Test public void testClear() throws Exception { chain.addLast("A", new EventOrderTestFilter('A')); chain.addLast("B", new EventOrderTestFilter('A')); chain.addLast("C", new EventOrderTestFilter('A')); chain.addLast("D", new EventOrderTestFilter('A')); chain.addLast("E", new EventOrderTestFilter('A')); chain.clear(); assertEquals(0, chain.getAll().size()); } @Test public void testToString() throws Exception { // When the chain is empty assertEquals("{ empty }", chain.toString()); // When there's one filter chain.addLast("A", new IoFilterAdapter() { @Override public String toString() { return "B"; } }); assertEquals("{ (A:B) }", chain.toString()); // When there are two chain.addLast("C", new IoFilterAdapter() { @Override public String toString() { return "D"; } }); assertEquals("{ (A:B), (C:D) }", chain.toString()); } @Test public void testDefault() { run("HS0 HSO HMR HMS HSI HEC HSC"); } @Test public void testChained() throws Exception { chain.addLast("A", new EventOrderTestFilter('A')); chain.addLast("B", new EventOrderTestFilter('B')); run("AS0 BS0 HS0" + "ASO BSO HSO" + "AMR BMR HMR" + "BFW AFW AMS BMS HMS" + "ASI BSI HSI" + "AEC BEC HEC" + "ASC BSC HSC"); } @Test public void testAddRemove() throws Exception { IoFilter filter = new AddRemoveTestFilter(); chain.addFirst("A", filter); assertEquals("ADDED", testResult); chain.remove("A"); assertEquals("ADDEDREMOVED", testResult); } private void run(String expectedResult) { chain.fireSessionCreated(); chain.fireSessionOpened(); chain.fireMessageReceived(new Object()); chain.fireFilterWrite(new DefaultWriteRequest(new Object())); chain.fireSessionIdle(IdleStatus.READER_IDLE); chain.fireExceptionCaught(new Exception()); chain.fireSessionClosed(); testResult = formatResult(testResult); String formatedExpectedResult = formatResult(expectedResult); assertEquals(formatedExpectedResult, testResult); } private String formatResult(String result) { String newResult = result.replaceAll("\\s", ""); StringBuilder buf = new StringBuilder(newResult.length() * 4 / 3); for (int i = 0; i < newResult.length(); i++) { buf.append(newResult.charAt(i)); if (i % 3 == 2) { buf.append(' '); } } return buf.toString(); } private class EventOrderTestFilter extends IoFilterAdapter { private final char id; EventOrderTestFilter(char id) { this.id = id; } @Override public void sessionCreated(NextFilter nextFilter, IoSession session) { testResult += id + "S0"; nextFilter.sessionCreated(session); } @Override public void sessionOpened(NextFilter nextFilter, IoSession session) { testResult += id + "SO"; nextFilter.sessionOpened(session); } @Override public void sessionClosed(NextFilter nextFilter, IoSession session) { testResult += id + "SC"; nextFilter.sessionClosed(session); } @Override public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) { testResult += id + "SI"; nextFilter.sessionIdle(session, status); } @Override public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) { testResult += id + "EC"; nextFilter.exceptionCaught(session, cause); } @Override public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) { testResult += id + "FW"; nextFilter.filterWrite(session, writeRequest); } @Override public void messageReceived(NextFilter nextFilter, IoSession session, Object message) { testResult += id + "MR"; nextFilter.messageReceived(session, message); } @Override public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) { testResult += id + "MS"; nextFilter.messageSent(session, writeRequest); } @Override public void filterClose(NextFilter nextFilter, IoSession session) throws Exception { nextFilter.filterClose(session); } } private class AddRemoveTestFilter extends IoFilterAdapter { /** * Default constructor */ public AddRemoveTestFilter() { super(); } @Override public void onPostAdd(IoFilterChain parent, String name, NextFilter nextFilter) { testResult += "ADDED"; } @Override public void onPostRemove(IoFilterChain parent, String name, NextFilter nextFilter) { testResult += "REMOVED"; } } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/core/IoServiceListenerSupportTest.java0000644000175000017500000002064312032276016032533 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core; import java.net.InetSocketAddress; import java.net.SocketAddress; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoService; import org.apache.mina.core.service.IoServiceListener; import org.apache.mina.core.service.IoServiceListenerSupport; import org.apache.mina.core.session.DummySession; import org.easymock.EasyMock; import org.junit.Test; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; /** * Tests {@link IoServiceListenerSupport}. * * @author Apache MINA Project */ public class IoServiceListenerSupportTest { private static final SocketAddress ADDRESS = new InetSocketAddress(8080); private final IoService mockService = EasyMock.createMock(IoService.class); @Test public void testServiceLifecycle() throws Exception { IoServiceListenerSupport support = new IoServiceListenerSupport(mockService); IoServiceListener listener = EasyMock.createStrictMock(IoServiceListener.class); // Test activation listener.serviceActivated(mockService); EasyMock.replay(listener); support.add(listener); support.fireServiceActivated(); EasyMock.verify(listener); // Test deactivation & other side effects EasyMock.reset(listener); listener.serviceDeactivated(mockService); EasyMock.replay(listener); //// Activate more than once support.fireServiceActivated(); //// Deactivate support.fireServiceDeactivated(); //// Deactivate more than once support.fireServiceDeactivated(); EasyMock.verify(listener); } @Test public void testSessionLifecycle() throws Exception { IoServiceListenerSupport support = new IoServiceListenerSupport(mockService); DummySession session = new DummySession(); session.setService(mockService); session.setLocalAddress(ADDRESS); IoHandler handler = EasyMock.createStrictMock(IoHandler.class); session.setHandler(handler); IoServiceListener listener = EasyMock.createStrictMock(IoServiceListener.class); // Test creation listener.sessionCreated(session); handler.sessionCreated(session); handler.sessionOpened(session); EasyMock.replay(listener); EasyMock.replay(handler); support.add(listener); support.fireSessionCreated(session); EasyMock.verify(listener); EasyMock.verify(handler); assertEquals(1, support.getManagedSessions().size()); assertSame(session, support.getManagedSessions().get(session.getId())); // Test destruction & other side effects EasyMock.reset(listener); EasyMock.reset(handler); handler.sessionClosed(session); listener.sessionDestroyed(session); EasyMock.replay(listener); //// Activate more than once support.fireSessionCreated(session); //// Deactivate support.fireSessionDestroyed(session); //// Deactivate more than once support.fireSessionDestroyed(session); EasyMock.verify(listener); assertTrue(session.isClosing()); assertEquals(0, support.getManagedSessions().size()); assertNull(support.getManagedSessions().get(session.getId())); } @Test public void testDisconnectOnUnbind() throws Exception { IoAcceptor acceptor = EasyMock.createStrictMock(IoAcceptor.class); final IoServiceListenerSupport support = new IoServiceListenerSupport(acceptor); final DummySession session = new DummySession(); session.setService(acceptor); session.setLocalAddress(ADDRESS); IoHandler handler = EasyMock.createStrictMock(IoHandler.class); session.setHandler(handler); final IoServiceListener listener = EasyMock.createStrictMock(IoServiceListener.class); // Activate a service and create a session. listener.serviceActivated(acceptor); listener.sessionCreated(session); handler.sessionCreated(session); handler.sessionOpened(session); EasyMock.replay(listener); EasyMock.replay(handler); support.add(listener); support.fireServiceActivated(); support.fireSessionCreated(session); EasyMock.verify(listener); EasyMock.verify(handler); // Deactivate a service and make sure the session is closed & destroyed. EasyMock.reset(listener); EasyMock.reset(handler); listener.serviceDeactivated(acceptor); EasyMock.expect(acceptor.isCloseOnDeactivation()).andReturn(true); listener.sessionDestroyed(session); handler.sessionClosed(session); EasyMock.replay(listener); EasyMock.replay(acceptor); EasyMock.replay(handler); new Thread() { // Emulate I/O service @Override public void run() { try { Thread.sleep(500); } catch (InterruptedException e) { //e.printStackTrace(); } // This synchronization block is a workaround for // the visibility problem of simultaneous EasyMock // state update. (not sure if it fixes the failing test yet.) synchronized (listener) { support.fireSessionDestroyed(session); } } }.start(); support.fireServiceDeactivated(); synchronized (listener) { EasyMock.verify(listener); } EasyMock.verify(acceptor); EasyMock.verify(handler); assertTrue(session.isClosing()); assertEquals(0, support.getManagedSessions().size()); assertNull(support.getManagedSessions().get(session.getId())); } @Test public void testConnectorActivation() throws Exception { IoConnector connector = EasyMock.createStrictMock(IoConnector.class); IoServiceListenerSupport support = new IoServiceListenerSupport(connector); final DummySession session = new DummySession(); session.setService(connector); session.setRemoteAddress(ADDRESS); IoHandler handler = EasyMock.createStrictMock(IoHandler.class); session.setHandler(handler); IoServiceListener listener = EasyMock.createStrictMock(IoServiceListener.class); // Creating a session should activate a service automatically. listener.serviceActivated(connector); listener.sessionCreated(session); handler.sessionCreated(session); handler.sessionOpened(session); EasyMock.replay(listener); EasyMock.replay(handler); support.add(listener); support.fireSessionCreated(session); EasyMock.verify(listener); EasyMock.verify(handler); // Destroying a session should deactivate a service automatically. EasyMock.reset(listener); EasyMock.reset(handler); listener.sessionDestroyed(session); handler.sessionClosed(session); listener.serviceDeactivated(connector); EasyMock.replay(listener); EasyMock.replay(handler); support.fireSessionDestroyed(session); EasyMock.verify(listener); EasyMock.verify(handler); assertEquals(0, support.getManagedSessions().size()); assertNull(support.getManagedSessions().get(session.getId())); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/core/DefaultIoFilterChainBuilderTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/core/DefaultIoFilterChainBuilderTest.ja0000644000175000017500000001134212032276016032501 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core; import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.filterchain.IoFilterChain.Entry; import org.apache.mina.filter.util.NoopFilter; import org.junit.After; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; /** * Tests {@link DefaultIoFilterChainBuilder}. * * @author Apache MINA Project */ public class DefaultIoFilterChainBuilderTest { @Before public void setUp() throws Exception { // Do nothing } @After public void tearDown() throws Exception { // Do nothing } @Test public void testAdd() throws Exception { DefaultIoFilterChainBuilder builder = new DefaultIoFilterChainBuilder(); builder.addFirst("A", new NoopFilter()); builder.addLast("B", new NoopFilter()); builder.addFirst("C", new NoopFilter()); builder.addLast("D", new NoopFilter()); builder.addBefore("B", "E", new NoopFilter()); builder.addBefore("C", "F", new NoopFilter()); builder.addAfter("B", "G", new NoopFilter()); builder.addAfter("D", "H", new NoopFilter()); String actual = ""; for (Entry e : builder.getAll()) { actual += e.getName(); } assertEquals("FCAEBGDH", actual); } @Test public void testGet() throws Exception { DefaultIoFilterChainBuilder builder = new DefaultIoFilterChainBuilder(); IoFilter filterA = new NoopFilter(); IoFilter filterB = new NoopFilter(); IoFilter filterC = new NoopFilter(); IoFilter filterD = new NoopFilter(); builder.addFirst("A", filterA); builder.addLast("B", filterB); builder.addBefore("B", "C", filterC); builder.addAfter("A", "D", filterD); assertSame(filterA, builder.get("A")); assertSame(filterB, builder.get("B")); assertSame(filterC, builder.get("C")); assertSame(filterD, builder.get("D")); } @Test public void testRemove() throws Exception { DefaultIoFilterChainBuilder builder = new DefaultIoFilterChainBuilder(); builder.addLast("A", new NoopFilter()); builder.addLast("B", new NoopFilter()); builder.addLast("C", new NoopFilter()); builder.addLast("D", new NoopFilter()); builder.addLast("E", new NoopFilter()); builder.remove("A"); builder.remove("E"); builder.remove("C"); builder.remove("B"); builder.remove("D"); assertEquals(0, builder.getAll().size()); } @Test public void testClear() throws Exception { DefaultIoFilterChainBuilder builder = new DefaultIoFilterChainBuilder(); builder.addLast("A", new NoopFilter()); builder.addLast("B", new NoopFilter()); builder.addLast("C", new NoopFilter()); builder.addLast("D", new NoopFilter()); builder.addLast("E", new NoopFilter()); builder.clear(); assertEquals(0, builder.getAll().size()); } @Test public void testToString() { DefaultIoFilterChainBuilder builder = new DefaultIoFilterChainBuilder(); // When the chain is empty assertEquals("{ empty }", builder.toString()); // When there's one filter builder.addLast("A", new IoFilterAdapter() { @Override public String toString() { return "B"; } }); assertEquals("{ (A:B) }", builder.toString()); // When there are two builder.addLast("C", new IoFilterAdapter() { @Override public String toString() { return "D"; } }); assertEquals("{ (A:B), (C:D) }", builder.toString()); } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/util/0000755000175000017500000000000012162575507024070 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/util/Bar.java0000644000175000017500000000254712032276017025435 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import org.apache.mina.core.buffer.IoBufferTest; /** * The subtype of {@link Foo}. It is used to test the serialization of inherited object * in {@link IoBufferTest}. * * @author Apache MINA Project */ public class Bar extends Foo { private static final long serialVersionUID = -7360624845308368521L; private int barValue; public int getBarValue() { return barValue; } public void setBarValue(int barValue) { this.barValue = barValue; } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/util/IoFilterImpl.java0000644000175000017500000000325112032276017027261 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.filterchain.IoFilterChain; /** * Bogus implementation of {@link IoFilter} to test * {@link IoFilterChain}. * * @author Apache MINA Project */ public class IoFilterImpl extends IoFilterAdapter { private final char c; public IoFilterImpl(char c) { this.c = c; } @Override public int hashCode() { return c; } @Override public boolean equals(Object o) { if (o == null) { return false; } if (!(o instanceof IoFilterImpl)) { return false; } return this.c == ((IoFilterImpl) o).c; } @Override public String toString() { return "" + c; } }mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/util/Foo.java0000644000175000017500000000262512032276017025451 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import java.io.Serializable; import org.apache.mina.core.buffer.IoBufferTest; /** * The parent class of {@link Bar}. It is used to test the serialization of inherited object * in {@link IoBufferTest}. * * @author Apache MINA Project */ public class Foo implements Serializable { private static final long serialVersionUID = 6467037996528575216L; private int fooValue; public int getFooValue() { return fooValue; } public void setFooValue(int fooValue) { this.fooValue = fooValue; } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/util/ExpiringMapTest.java0000644000175000017500000000344112032276017030006 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import static org.junit.Assert.assertNull; import org.junit.Before; import org.junit.Test; /** * Simple test that checks to see if the {@link ExpiringMap} can * properly clean up itself. * * @author Apache MINA Project */ public class ExpiringMapTest { private ExpiringMap theMap; /** * Create the map, populate it and then kick off * the Expirer, then sleep long enough so that the * Expirer can clean up the map. * * @throws java.lang.Exception */ @Before public void setUp() throws Exception { theMap = new ExpiringMap(1, 2); theMap.put("Apache", "MINA"); theMap.getExpirer().startExpiringIfNotStarted(); Thread.sleep(3000); } /** * Check to see if the map has been cleaned up. * */ @Test public void testGet() { assertNull(theMap.get("Apache")); } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/util/byteaccess/0000755000175000017500000000000012162575507026215 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/util/byteaccess/ByteAccessTest.java0000644000175000017500000004703512032276017031744 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util.byteaccess; import static org.easymock.EasyMock.createStrictControl; import static org.junit.Assert.assertEquals; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.util.byteaccess.ByteArray.Cursor; import org.apache.mina.util.byteaccess.CompositeByteArray.CursorListener; import org.apache.mina.util.byteaccess.CompositeByteArrayRelativeWriter.ChunkedExpander; import org.apache.mina.util.byteaccess.CompositeByteArrayRelativeWriter.Flusher; import org.easymock.IMocksControl; import org.junit.Test; /** * Tests classes in the byteaccess package. * * @author Apache MINA Project */ public class ByteAccessTest { private List operations = new ArrayList(); private void resetOperations() { operations.clear(); } private void assertOperationCountEquals(int expectedCount) { assertEquals("Operations: " + operations, expectedCount, operations.size()); } private void addOperation(String description) { operations.add(description); } @Test public void testBufferByteArray() throws Exception { ByteArray ba = getByteArrayFactory().create(1000); testAbsoluteReaderAndWriter(0, 1000, ba, ba); testAbsoluteReaderAndWriter(0, 1000, ba, ba); Cursor readCursor = ba.cursor(); Cursor writeCursor = ba.cursor(); testRelativeReaderAndWriter(1000, readCursor, writeCursor); } @Test public void testCompositeAddAndRemove() throws Exception { CompositeByteArray cba = new CompositeByteArray(); assertEquals(0, cba.first()); assertEquals(0, cba.last()); cba.addFirst(getByteArrayFactory().create(100)); assertEquals(-100, cba.first()); assertEquals(0, cba.last()); cba.addFirst(getByteArrayFactory().create(100)); assertEquals(-200, cba.first()); assertEquals(0, cba.last()); cba.addLast(getByteArrayFactory().create(100)); assertEquals(-200, cba.first()); assertEquals(100, cba.last()); cba.removeFirst(); assertEquals(-100, cba.first()); assertEquals(100, cba.last()); cba.addLast(getByteArrayFactory().create(100)); assertEquals(-100, cba.first()); assertEquals(200, cba.last()); cba.removeLast(); assertEquals(-100, cba.first()); assertEquals(100, cba.last()); cba.removeFirst(); assertEquals(0, cba.first()); assertEquals(100, cba.last()); cba.removeFirst(); assertEquals(100, cba.first()); assertEquals(100, cba.last()); cba.addLast(getByteArrayFactory().create(100)); assertEquals(100, cba.first()); assertEquals(200, cba.last()); } private BufferByteArray wrapString(String string) { byte[] bytes = string.getBytes(); IoBuffer bb = IoBuffer.wrap(bytes); BufferByteArray ba = new BufferByteArray(bb) { @Override public void free() { addOperation(this + ".free()"); // Nothing to do. } }; return ba; } private String toString(ByteArray ba) { IoBuffer bb = IoBuffer.allocate(ba.length()); ba.get(0, bb); byte[] bytes = bb.array(); String string = new String(bytes); return string; } @Test public void testCompositeStringJoin() throws Exception { ByteArray ba1 = wrapString("Hello"); ByteArray ba2 = wrapString("MINA"); ByteArray ba3 = wrapString("World"); CompositeByteArray cba = new CompositeByteArray(); cba.addLast(ba1); cba.addLast(ba2); cba.addLast(ba3); assertEquals("HelloMINAWorld", toString(cba)); } @Test public void testCompositeCursor() throws Exception { IMocksControl mc = createStrictControl(); ByteArray ba1 = getByteArrayFactory().create(10); ByteArray ba2 = getByteArrayFactory().create(10); ByteArray ba3 = getByteArrayFactory().create(10); CompositeByteArray cba = new CompositeByteArray(); cba.addLast(ba1); cba.addLast(ba2); cba.addLast(ba3); CursorListener cl = mc.createMock(CursorListener.class); mc.reset(); mc.replay(); Cursor cursor = cba.cursor(cl); mc.verify(); mc.reset(); cl.enteredFirstComponent(0, ba1); mc.replay(); cursor.get(); mc.verify(); mc.reset(); mc.replay(); cursor.setIndex(10); mc.verify(); mc.reset(); cl.enteredNextComponent(10, ba2); mc.replay(); cursor.put((byte) 55); mc.verify(); mc.reset(); mc.replay(); cursor.setIndex(9); mc.verify(); mc.reset(); cl.enteredPreviousComponent(0, ba1); cl.enteredNextComponent(10, ba2); mc.replay(); cursor.putInt(66); mc.verify(); mc.reset(); cl.enteredNextComponent(20, ba3); mc.replay(); cursor.setIndex(29); cursor.get(); mc.verify(); cba.removeLast(); // Force cursor to relocate itself. mc.reset(); cl.enteredLastComponent(10, ba2); mc.replay(); cursor.setIndex(15); cursor.get(); mc.verify(); mc.reset(); cl.enteredPreviousComponent(0, ba1); mc.replay(); cursor.setIndex(0); cursor.get(); mc.verify(); } @Test public void testCompositeByteArray() throws Exception { CompositeByteArray ba = new CompositeByteArray(); for (int i = 0; i < 1000; i += 100) { ba.addLast(getByteArrayFactory().create(100)); } resetOperations(); testAbsoluteReaderAndWriter(0, 1000, ba, ba); testAbsoluteReaderAndWriter(0, 1000, ba, ba); assertOperationCountEquals(0); Cursor readCursor = ba.cursor(); Cursor writeCursor = ba.cursor(); testRelativeReaderAndWriter(1000, readCursor, writeCursor); assertOperationCountEquals(0); } @Test public void testCompositeByteArrayRelativeReaderAndWriter() throws Exception { CompositeByteArray cba = new CompositeByteArray(); CompositeByteArrayRelativeReader cbarr = new CompositeByteArrayRelativeReader(cba, true); CompositeByteArrayRelativeWriter cbarw = new CompositeByteArrayRelativeWriter(cba, getExpander(100), getFlusher(), false); resetOperations(); testRelativeReaderAndWriter(10, cbarr, cbarw); assertOperationCountEquals(2); resetOperations(); testRelativeReaderAndWriter(100, cbarr, cbarw); assertOperationCountEquals(3); resetOperations(); testRelativeReaderAndWriter(1000, cbarr, cbarw); assertOperationCountEquals(30); resetOperations(); testRelativeReaderAndWriter(10000, cbarr, cbarw); assertOperationCountEquals(300); resetOperations(); testRelativeReaderAndWriter(90, cbarr, cbarw); assertOperationCountEquals(0); // Last free doesn't occur, since cursor only moves lazily. } @Test public void testCompositeByteArrayRelativeReaderAndWriterWithFlush() throws Exception { CompositeByteArray cba = new CompositeByteArray(); CompositeByteArrayRelativeReader cbarr = new CompositeByteArrayRelativeReader(cba, true); CompositeByteArrayRelativeWriter cbarw = new CompositeByteArrayRelativeWriter(cba, getExpander(100), getFlusher(), true); resetOperations(); testRelativeReaderAndWriter(10, cbarr, cbarw); assertOperationCountEquals(2); resetOperations(); testRelativeReaderAndWriter(100, cbarr, cbarw); assertOperationCountEquals(4); resetOperations(); testRelativeReaderAndWriter(1000, cbarr, cbarw); assertOperationCountEquals(40); resetOperations(); testRelativeReaderAndWriter(10000, cbarr, cbarw); assertOperationCountEquals(400); resetOperations(); testRelativeReaderAndWriter(90, cbarr, cbarw); assertOperationCountEquals(0); // Last free doesn't occur, since cursor only moves lazily. } @Test public void testCompositeRemoveTo() throws Exception { CompositeByteArray cba = new CompositeByteArray(); { // Remove nothing. resetOperations(); ByteArray removed = cba.removeTo(0); assertEquals(0, removed.first()); assertEquals(0, removed.last()); assertEquals(0, cba.first()); assertEquals(0, cba.last()); removed.free(); assertOperationCountEquals(0); } cba.addLast(getByteArrayFactory().create(100)); { // Remove nothing. resetOperations(); ByteArray removed = cba.removeTo(0); assertEquals(0, removed.first()); assertEquals(0, removed.last()); assertEquals(0, cba.first()); assertEquals(100, cba.last()); removed.free(); assertOperationCountEquals(0); } { // Remove entire component. resetOperations(); ByteArray removed = cba.removeTo(100); assertEquals(0, removed.first()); assertEquals(100, removed.last()); assertEquals(100, cba.first()); assertEquals(100, cba.last()); removed.free(); assertOperationCountEquals(1); } { // Remove nothing. resetOperations(); ByteArray removed = cba.removeTo(100); assertEquals(0, removed.first()); assertEquals(0, removed.last()); assertEquals(100, cba.first()); assertEquals(100, cba.last()); removed.free(); assertOperationCountEquals(0); } cba.addLast(getByteArrayFactory().create(100)); { // Remove nothing. resetOperations(); ByteArray removed = cba.removeTo(100); assertEquals(0, removed.first()); assertEquals(0, removed.last()); assertEquals(100, cba.first()); assertEquals(200, cba.last()); removed.free(); assertOperationCountEquals(0); } { // Remove half a component. resetOperations(); ByteArray removed = cba.removeTo(150); assertEquals(0, removed.first()); assertEquals(50, removed.last()); assertEquals(150, cba.first()); assertEquals(200, cba.last()); removed.free(); assertOperationCountEquals(0); // Doesn't free until component finished. } { // Remove nothing. resetOperations(); ByteArray removed = cba.removeTo(150); assertEquals(0, removed.first()); assertEquals(0, removed.last()); assertEquals(150, cba.first()); assertEquals(200, cba.last()); removed.free(); assertOperationCountEquals(0); } { // Remove other half. resetOperations(); ByteArray removed = cba.removeTo(200); assertEquals(0, removed.first()); assertEquals(50, removed.last()); assertEquals(200, cba.first()); assertEquals(200, cba.last()); removed.free(); assertOperationCountEquals(1); // Frees ByteArray behind both buffers. } } @Test public void testCompositeByteArraySlicing() { CompositeByteArray cba = new CompositeByteArray(); cba.addLast(getByteArrayFactory().create(10)); cba.addLast(getByteArrayFactory().create(10)); cba.addLast(getByteArrayFactory().create(10)); testByteArraySlicing(cba, 0, 30); testByteArraySlicing(cba, 5, 10); testByteArraySlicing(cba, 10, 20); testByteArraySlicing(cba, 1, 28); testByteArraySlicing(cba, 19, 2); } @Test public void testBufferByteArraySlicing() { ByteArray bba = getByteArrayFactory().create(30); testByteArraySlicing(bba, 0, 30); testByteArraySlicing(bba, 5, 10); testByteArraySlicing(bba, 10, 20); testByteArraySlicing(bba, 1, 28); testByteArraySlicing(bba, 19, 2); } private void testByteArraySlicing(ByteArray ba, int start, int length) { ByteArray slice = ba.slice(start, length); for (int i = 0; i < length; i++) { byte b1 = (byte) (i % 67); byte b2 = (byte) (i % 36); int sourceIndex = i + start; int sliceIndex = i; ba.put(sourceIndex, b1); assertEquals(b1, ba.get(sourceIndex)); assertEquals(b1, slice.get(sliceIndex)); slice.put(sliceIndex, b2); assertEquals(b2, ba.get(sourceIndex)); assertEquals(b2, slice.get(sliceIndex)); } } private ChunkedExpander getExpander(final int chunkSize) { return new ChunkedExpander(getByteArrayFactory(), chunkSize) { @Override public void expand(CompositeByteArray cba, int minSize) { addOperation("ChunkedExpander(" + chunkSize + ").expand(" + cba + "," + minSize + ")"); super.expand(cba, minSize); } }; } private Flusher getFlusher() { return new CompositeByteArrayRelativeWriter.Flusher() { public void flush(ByteArray ba) { addOperation("Flusher().flush(" + ba + ")"); ba.free(); } }; } private SimpleByteArrayFactory getByteArrayFactory() { return new SimpleByteArrayFactory() { @Override public ByteArray create(final int size) { if (size < 0) { throw new IllegalArgumentException("Buffer size must not be negative:" + size); } IoBuffer bb = IoBuffer.allocate(size); ByteArray ba = new BufferByteArray(bb) { @Override public void free() { addOperation(this + ".free()"); // Nothing to do. } }; addOperation("SimpleByteArrayFactory().create(" + size + ") = " + ba); return ba; } }; } private void testRelativeReaderAndWriter(int length, IoRelativeReader reader, IoRelativeWriter writer) { for (int i = 0; i < length; i++) { byte b = (byte) (i % 67); writer.put(b); assertEquals(b, reader.get()); } } private void testAbsoluteReaderAndWriter(int start, int length, IoAbsoluteReader reader, IoAbsoluteWriter writer) { for (int i = start; i < length; i++) { byte b = (byte) (i % 67); writer.put(i, b); assertEquals(b, reader.get(i)); } } @Test public void testByteArrayPrimitiveAccess() { ByteArray bbaBig = getByteArrayFactory().create(1000); bbaBig.order(ByteOrder.BIG_ENDIAN); testPrimitiveAccess(bbaBig.cursor(), bbaBig.cursor()); ByteArray bbaLittle = getByteArrayFactory().create(1000); bbaLittle.order(ByteOrder.LITTLE_ENDIAN); testPrimitiveAccess(bbaLittle.cursor(), bbaLittle.cursor()); } @Test public void testByteArrayBufferAccess() { ByteArray ba = getByteArrayFactory().create(1); ba.put(0, (byte) 99); IoBuffer bb = IoBuffer.allocate(2); bb.clear(); Cursor cursor = ba.cursor(); assertEquals(0, cursor.getIndex()); assertEquals(1, cursor.getRemaining()); assertEquals(0, bb.position()); assertEquals(2, bb.remaining()); cursor.get(bb); assertEquals(1, cursor.getIndex()); assertEquals(0, cursor.getRemaining()); assertEquals(1, bb.position()); assertEquals(1, bb.remaining()); } @Test public void testCompositeByteArrayPrimitiveAccess() { CompositeByteArray cbaBig = new CompositeByteArray(); cbaBig.order(ByteOrder.BIG_ENDIAN); for (int i = 0; i < 1000; i++) { ByteArray component = getByteArrayFactory().create(1); component.order(ByteOrder.BIG_ENDIAN); cbaBig.addLast(component); } testPrimitiveAccess(cbaBig.cursor(), cbaBig.cursor()); CompositeByteArray cbaLittle = new CompositeByteArray(); cbaLittle.order(ByteOrder.LITTLE_ENDIAN); for (int i = 0; i < 1000; i++) { ByteArray component = getByteArrayFactory().create(1); component.order(ByteOrder.LITTLE_ENDIAN); cbaLittle.addLast(component); } testPrimitiveAccess(cbaLittle.cursor(), cbaLittle.cursor()); } @Test public void testCompositeByteArrayWrapperPrimitiveAccess() { CompositeByteArray cbaBig = new CompositeByteArray(); cbaBig.order(ByteOrder.BIG_ENDIAN); for (int i = 0; i < 1000; i++) { ByteArray component = getByteArrayFactory().create(1); component.order(ByteOrder.BIG_ENDIAN); cbaBig.addLast(component); } testPrimitiveAccess(new CompositeByteArrayRelativeWriter(cbaBig, getExpander(10), getFlusher(), false), new CompositeByteArrayRelativeReader(cbaBig, true)); CompositeByteArray cbaLittle = new CompositeByteArray(); cbaLittle.order(ByteOrder.LITTLE_ENDIAN); for (int i = 0; i < 1000; i++) { ByteArray component = getByteArrayFactory().create(1); component.order(ByteOrder.LITTLE_ENDIAN); cbaLittle.addLast(component); } testPrimitiveAccess(new CompositeByteArrayRelativeWriter(cbaLittle, getExpander(10), getFlusher(), false), new CompositeByteArrayRelativeReader(cbaLittle, true)); } private void testPrimitiveAccess(IoRelativeWriter write, IoRelativeReader read) { byte b = (byte) 0x12; write.put(b); assertEquals(b, read.get()); short s = (short) 0x12; write.putShort(s); assertEquals(s, read.getShort()); int i = 0x12345678; write.putInt(i); assertEquals(i, read.getInt()); long l = 0x1234567890123456L; write.putLong(l); assertEquals(l, read.getLong()); float f = Float.intBitsToFloat(i); write.putFloat(f); assertEquals(f, read.getFloat(), 0); double d = Double.longBitsToDouble(l); write.putDouble(d); assertEquals(d, read.getDouble(), 0); char c = (char) 0x1234; write.putChar(c); assertEquals(c, read.getChar()); } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/util/CircularQueueTest.java0000644000175000017500000001564712032276017030347 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.Iterator; import org.junit.Before; import org.junit.Test; /** * Tests {@link org.apache.mina.util.CircularQueue} * * @author Apache MINA Project */ public class CircularQueueTest { private volatile int pushCount; private volatile int popCount; @Before public void setUp() { pushCount = 0; popCount = 0; } @Test public void testRotation() { CircularQueue q = new CircularQueue(); // DEFAULT_CAPACITY = 4 testRotation0(q); } @Test public void testExpandingRotation() { CircularQueue q = new CircularQueue(); // DEFAULT_CAPACITY = 4 for (int i = 0; i < 10; i++) { testRotation0(q); // make expansion happen int oldCapacity = q.capacity(); for (int j = q.capacity(); j >= 0; j--) { q.offer(new Integer(++pushCount)); } assertTrue(q.capacity() > oldCapacity); testRotation0(q); } } private void testRotation0(CircularQueue q) { for (int i = 0; i < q.capacity() * 7 / 4; i++) { q.offer(new Integer(++pushCount)); assertEquals(++popCount, q.poll().intValue()); } } @Test public void testRandomAddOnQueue() { CircularQueue q = new CircularQueue(); // Create a queue with 5 elements and capacity 8; for (int i = 0; i < 5; i++) { q.offer(new Integer(i)); } q.add(0, new Integer(100)); q.add(3, new Integer(200)); q.add(7, new Integer(300)); Iterator i = q.iterator(); assertEquals(8, q.size()); assertEquals(new Integer(100), i.next()); assertEquals(new Integer(0), i.next()); assertEquals(new Integer(1), i.next()); assertEquals(new Integer(200), i.next()); assertEquals(new Integer(2), i.next()); assertEquals(new Integer(3), i.next()); assertEquals(new Integer(4), i.next()); assertEquals(new Integer(300), i.next()); try { i.next(); fail(); } catch (Exception e) { // an exception signifies a successfull test case assertTrue(true); } } @Test public void testRandomAddOnRotatedQueue() { CircularQueue q = getRotatedQueue(); q.add(0, new Integer(100)); // addFirst q.add(2, new Integer(200)); q.add(4, new Integer(300)); q.add(10, new Integer(400)); q.add(12, new Integer(500)); // addLast Iterator i = q.iterator(); assertEquals(13, q.size()); assertEquals(new Integer(100), i.next()); assertEquals(new Integer(0), i.next()); assertEquals(new Integer(200), i.next()); assertEquals(new Integer(1), i.next()); assertEquals(new Integer(300), i.next()); assertEquals(new Integer(2), i.next()); assertEquals(new Integer(3), i.next()); assertEquals(new Integer(4), i.next()); assertEquals(new Integer(5), i.next()); assertEquals(new Integer(6), i.next()); assertEquals(new Integer(400), i.next()); assertEquals(new Integer(7), i.next()); assertEquals(new Integer(500), i.next()); try { i.next(); fail(); } catch (Exception e) { // an exception signifies a successfull test case assertTrue(true); } } @Test public void testRandomRemoveOnQueue() { CircularQueue q = new CircularQueue(); // Create a queue with 5 elements and capacity 8; for (int i = 0; i < 5; i++) { q.offer(new Integer(i)); } q.remove(0); q.remove(2); q.remove(2); Iterator i = q.iterator(); assertEquals(2, q.size()); assertEquals(new Integer(1), i.next()); assertEquals(new Integer(2), i.next()); try { i.next(); fail(); } catch (Exception e) { // an exception signifies a successfull test case assertTrue(true); } } @Test public void testRandomRemoveOnRotatedQueue() { CircularQueue q = getRotatedQueue(); q.remove(0); // removeFirst q.remove(2); // removeLast in the first half q.remove(2); // removeFirst in the first half q.remove(4); // removeLast Iterator i = q.iterator(); assertEquals(4, q.size()); assertEquals(new Integer(1), i.next()); assertEquals(new Integer(2), i.next()); assertEquals(new Integer(5), i.next()); assertEquals(new Integer(6), i.next()); try { i.next(); fail(); } catch (Exception e) { // an exception signifies a successfull test case assertTrue(true); } } @Test public void testExpandAndShrink() throws Exception { CircularQueue q = new CircularQueue(); for (int i = 0; i < 1024; i++) { q.offer(i); } assertEquals(1024, q.capacity()); for (int i = 0; i < 512; i++) { q.offer(i); q.poll(); } assertEquals(2048, q.capacity()); for (int i = 0; i < 1024; i++) { q.poll(); } assertEquals(4, q.capacity()); } private CircularQueue getRotatedQueue() { CircularQueue q = new CircularQueue(); // Ensure capacity: 16 for (int i = 0; i < 16; i++) { q.offer(new Integer(-1)); } q.clear(); // Rotate it for (int i = 0; i < 12; i++) { q.offer(new Integer(-1)); q.poll(); } // Now push items for (int i = 0; i < 8; i++) { q.offer(new Integer(i)); } return q; } }mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/0000755000175000017500000000000012032276015024364 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/executor/0000755000175000017500000000000012162575507026236 5ustar ebourgebourg././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/executor/ExecutorFilterRegressionTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/executor/ExecutorFilterRegressio0000644000175000017500000001163012032276015032775 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.executor; import static org.junit.Assert.assertEquals; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.session.DummySession; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * TODO Add documentation * * @author Apache MINA Project */ public class ExecutorFilterRegressionTest { private ExecutorFilter filter; public ExecutorFilterRegressionTest() { // Do nothing } @Before public void setUp() throws Exception { filter = new ExecutorFilter(8); } @After public void tearDown() throws Exception { ((ExecutorService) filter.getExecutor()).shutdown(); filter = null; } @Test public void testEventOrder() throws Throwable { final EventOrderChecker nextFilter = new EventOrderChecker(); final EventOrderCounter[] sessions = new EventOrderCounter[] { new EventOrderCounter(), new EventOrderCounter(), new EventOrderCounter(), new EventOrderCounter(), new EventOrderCounter(), new EventOrderCounter(), new EventOrderCounter(), new EventOrderCounter(), new EventOrderCounter(), new EventOrderCounter(), }; final int loop = 1000000; final int end = sessions.length - 1; final ExecutorFilter filter = this.filter; ExecutorService executor = (ExecutorService) filter.getExecutor(); //executor.setKeepAliveTime(3, TimeUnit.SECONDS); for (int i = 0; i < loop; i++) { Integer objI = new Integer(i); for (int j = end; j >= 0; j--) { filter.messageReceived(nextFilter, sessions[j], objI); } if (nextFilter.throwable != null) { throw nextFilter.throwable; } } executor.shutdown(); executor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); for (int i = end; i >= 0; i--) { assertEquals(loop - 1, sessions[i].lastCount.intValue()); } } private static class EventOrderCounter extends DummySession { Integer lastCount = null; /** * Default constructor */ public EventOrderCounter() { super(); } public synchronized void setLastCount(Integer newCount) { if (lastCount != null) { assertEquals(lastCount.intValue() + 1, newCount.intValue()); } lastCount = newCount; } } private static class EventOrderChecker implements NextFilter { Throwable throwable; /** * Default constructor */ public EventOrderChecker() { super(); } public void sessionOpened(IoSession session) { // Do nothing } public void sessionClosed(IoSession session) { // Do nothing } public void sessionIdle(IoSession session, IdleStatus status) { // Do nothing } public void exceptionCaught(IoSession session, Throwable cause) { // Do nothing } public void messageReceived(IoSession session, Object message) { try { ((EventOrderCounter) session).setLastCount((Integer) message); } catch (Throwable t) { if (this.throwable == null) { this.throwable = t; } } } public void messageSent(IoSession session, WriteRequest writeRequest) { // Do nothing } public void filterWrite(IoSession session, WriteRequest writeRequest) { // Do nothing } public void filterClose(IoSession session) { // Do nothing } public void sessionCreated(IoSession session) { // Do nothing } } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/logging/0000755000175000017500000000000012162575507026026 5ustar ebourgebourg././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/logging/LoadTestMdcInjectionFilter.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/logging/LoadTestMdcInjectionFilt0000644000175000017500000000362512032276015032570 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.logging; import junit.framework.JUnit4TestAdapter; import junit.framework.Test; import junit.textui.TestRunner; import java.util.Date; /** * Test the MdcInjectionFilter load for Windows * * @author Apache MINA Project */ public class LoadTestMdcInjectionFilter { /** * The MdcInjectionFilterTest is unstable, it fails sporadically (and only on Windows ?) * This is a quick and dirty program to run the MdcInjectionFilterTest many times. * To be removed once we consider DIRMINA-784 to be fixed * */ public static void main(String[] args) { TestRunner runner = new TestRunner(); try { for (int i = 0; i < 50000; i++) { Test test = new JUnit4TestAdapter(MdcInjectionFilterTest.class); runner.doRun(test); System.out.println("i = " + i + " " + new Date()); } System.out.println("done"); } catch (Exception e) { e.printStackTrace(); } System.exit(0); } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/logging/MdcInjectionFilterTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/logging/MdcInjectionFilterTest.j0000644000175000017500000005115412032276015032547 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.logging; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import org.apache.log4j.AppenderSkeleton; import org.apache.log4j.Level; import org.apache.log4j.spi.LoggingEvent; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFactory; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoderAdapter; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import org.apache.mina.filter.codec.ProtocolEncoder; import org.apache.mina.filter.codec.ProtocolEncoderAdapter; import org.apache.mina.filter.codec.ProtocolEncoderOutput; import org.apache.mina.filter.executor.ExecutorFilter; import org.apache.mina.filter.statistic.ProfilerTimerFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import org.apache.mina.transport.socket.nio.NioSocketConnector; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Tests {@link MdcInjectionFilter} in various scenarios. * * @author Apache MINA Project */ public class MdcInjectionFilterTest { static Logger LOGGER = LoggerFactory.getLogger(MdcInjectionFilterTest.class); private static final int TIMEOUT = 5000; private final MyAppender appender = new MyAppender(); private int port; private NioSocketAcceptor acceptor; private Level previousLevelRootLogger; private ExecutorFilter executorFilter1; private ExecutorFilter executorFilter2; @Before public void setUp() throws Exception { // comment out next line if you want to see normal logging org.apache.log4j.Logger.getRootLogger().removeAllAppenders(); previousLevelRootLogger = org.apache.log4j.Logger.getRootLogger().getLevel(); org.apache.log4j.Logger.getRootLogger().setLevel(Level.DEBUG); org.apache.log4j.Logger.getRootLogger().addAppender(appender); acceptor = new NioSocketAcceptor(); } @After public void tearDown() throws Exception { acceptor.dispose(true); org.apache.log4j.Logger.getRootLogger().setLevel(previousLevelRootLogger); destroy(executorFilter1); destroy(executorFilter2); List after = getThreadNames(); // give acceptor some time to shut down Thread.sleep(50); after = getThreadNames(); int count = 0; // NOTE: this is *not* intended to be a permanent fix for this test-case. // There used to be no API to block until the ExecutorService of AbstractIoService is terminated. // The API exists now : dispose(true) so we should get rid of this code. while (contains(after, "Nio") && count++ < 10) { Thread.sleep(50); after = getThreadNames(); } while (contains(after, "pool") && count++ < 10) { Thread.sleep(50); after = getThreadNames(); } // The problem is that we clear the events of the appender here, but it's possible that a thread from // a previous test still generates events during the execution of the next test appender.clear(); } private void destroy(ExecutorFilter executorFilter) throws InterruptedException { if (executorFilter != null) { ExecutorService executor = (ExecutorService) executorFilter.getExecutor(); executor.shutdown(); while (!executor.isTerminated()) { //System.out.println("Waiting for termination of " + executorFilter); executor.awaitTermination(10, TimeUnit.MILLISECONDS); } } } @Test public void testSimpleChain() throws IOException, InterruptedException { DefaultIoFilterChainBuilder chain = new DefaultIoFilterChainBuilder(); chain.addFirst("mdc-injector", new MdcInjectionFilter()); chain.addLast("dummy", new DummyIoFilter()); chain.addLast("protocol", new ProtocolCodecFilter(new DummyProtocolCodecFactory())); test(chain); } @Test public void testExecutorFilterAtTheEnd() throws IOException, InterruptedException { executorFilter1 = new ExecutorFilter(); DefaultIoFilterChainBuilder chain = new DefaultIoFilterChainBuilder(); MdcInjectionFilter mdcInjectionFilter = new MdcInjectionFilter(); chain.addFirst("mdc-injector1", mdcInjectionFilter); chain.addLast("dummy", new DummyIoFilter()); chain.addLast("protocol", new ProtocolCodecFilter(new DummyProtocolCodecFactory())); chain.addLast("executor", executorFilter1); chain.addLast("mdc-injector2", mdcInjectionFilter); test(chain); } @Test public void testExecutorFilterAtBeginning() throws IOException, InterruptedException { executorFilter1 = new ExecutorFilter(); DefaultIoFilterChainBuilder chain = new DefaultIoFilterChainBuilder(); MdcInjectionFilter mdcInjectionFilter = new MdcInjectionFilter(); chain.addLast("executor", executorFilter1); chain.addLast("mdc-injector", mdcInjectionFilter); chain.addLast("dummy", new DummyIoFilter()); chain.addLast("protocol", new ProtocolCodecFilter(new DummyProtocolCodecFactory())); test(chain); } @Test public void testExecutorFilterBeforeProtocol() throws IOException, InterruptedException { executorFilter1 = new ExecutorFilter(); DefaultIoFilterChainBuilder chain = new DefaultIoFilterChainBuilder(); MdcInjectionFilter mdcInjectionFilter = new MdcInjectionFilter(); chain.addLast("executor", executorFilter1); chain.addLast("mdc-injector", mdcInjectionFilter); chain.addLast("dummy", new DummyIoFilter()); chain.addLast("protocol", new ProtocolCodecFilter(new DummyProtocolCodecFactory())); test(chain); } @Test public void testMultipleFilters() throws IOException, InterruptedException { executorFilter1 = new ExecutorFilter(); DefaultIoFilterChainBuilder chain = new DefaultIoFilterChainBuilder(); MdcInjectionFilter mdcInjectionFilter = new MdcInjectionFilter(); chain.addLast("executor", executorFilter1); chain.addLast("mdc-injector", mdcInjectionFilter); chain.addLast("profiler", new ProfilerTimerFilter()); chain.addLast("dummy", new DummyIoFilter()); chain.addLast("logger", new LoggingFilter()); chain.addLast("protocol", new ProtocolCodecFilter(new DummyProtocolCodecFactory())); test(chain); } @Test public void testTwoExecutorFilters() throws IOException, InterruptedException { DefaultIoFilterChainBuilder chain = new DefaultIoFilterChainBuilder(); MdcInjectionFilter mdcInjectionFilter = new MdcInjectionFilter(); executorFilter1 = new ExecutorFilter(); executorFilter2 = new ExecutorFilter(); chain.addLast("executorFilter1", executorFilter1); chain.addLast("mdc-injector1", mdcInjectionFilter); chain.addLast("protocol", new ProtocolCodecFilter(new DummyProtocolCodecFactory())); chain.addLast("dummy", new DummyIoFilter()); chain.addLast("executorFilter2", executorFilter2); // add the MdcInjectionFilter instance after every ExecutorFilter // it's important to use the same MdcInjectionFilter instance chain.addLast("mdc-injector2", mdcInjectionFilter); test(chain); } @Test public void testOnlyRemoteAddress() throws IOException, InterruptedException { DefaultIoFilterChainBuilder chain = new DefaultIoFilterChainBuilder(); chain.addFirst("mdc-injector", new MdcInjectionFilter(MdcInjectionFilter.MdcKey.remoteAddress)); chain.addLast("dummy", new DummyIoFilter()); chain.addLast("protocol", new ProtocolCodecFilter(new DummyProtocolCodecFactory())); SimpleIoHandler simpleIoHandler = new SimpleIoHandler(); acceptor.setHandler(simpleIoHandler); acceptor.bind(new InetSocketAddress(0)); port = acceptor.getLocalAddress().getPort(); acceptor.setFilterChainBuilder(chain); // create some clients NioSocketConnector connector = new NioSocketConnector(); connector.setHandler(new IoHandlerAdapter()); connectAndWrite(connector, 0); connectAndWrite(connector, 1); // wait until Iohandler has received all events simpleIoHandler.messageSentLatch.await(); simpleIoHandler.sessionIdleLatch.await(); simpleIoHandler.sessionClosedLatch.await(); connector.dispose(true); // make a copy to prevent ConcurrentModificationException List events = new ArrayList(appender.events); // verify that all logging events have correct MDC for (LoggingEvent event : events) { if (event.getLoggerName().startsWith("org.apache.mina.core.service.AbstractIoService")) { continue; } for (MdcInjectionFilter.MdcKey mdcKey : MdcInjectionFilter.MdcKey.values()) { String key = mdcKey.name(); Object value = event.getMDC(key); if (mdcKey == MdcInjectionFilter.MdcKey.remoteAddress) { assertNotNull("MDC[remoteAddress] not set for [" + event.getMessage() + "]", value); } else { assertNull("MDC[" + key + "] set for [" + event.getMessage() + "]", value); } } } } private void test(DefaultIoFilterChainBuilder chain) throws IOException, InterruptedException { // configure the server SimpleIoHandler simpleIoHandler = new SimpleIoHandler(); acceptor.setHandler(simpleIoHandler); acceptor.bind(new InetSocketAddress(0)); port = acceptor.getLocalAddress().getPort(); acceptor.setFilterChainBuilder(chain); // create some clients NioSocketConnector connector = new NioSocketConnector(); connector.setHandler(new IoHandlerAdapter()); SocketAddress remoteAddressClients[] = new SocketAddress[2]; remoteAddressClients[0] = connectAndWrite(connector, 0); remoteAddressClients[1] = connectAndWrite(connector, 1); // wait until Iohandler has received all events simpleIoHandler.messageSentLatch.await(); simpleIoHandler.sessionIdleLatch.await(); simpleIoHandler.sessionClosedLatch.await(); connector.dispose(true); // make a copy to prevent ConcurrentModificationException List events = new ArrayList(appender.events); Set loggersToCheck = new HashSet(); loggersToCheck.add(MdcInjectionFilterTest.class.getName()); loggersToCheck.add(ProtocolCodecFilter.class.getName()); loggersToCheck.add(LoggingFilter.class.getName()); // verify that all logging events have correct MDC for (LoggingEvent event : events) { if (loggersToCheck.contains(event.getLoggerName())) { Object remoteAddress = event.getMDC("remoteAddress"); assertNotNull("MDC[remoteAddress] not set for [" + event.getMessage() + "]", remoteAddress); assertNotNull("MDC[remotePort] not set for [" + event.getMessage() + "]", event.getMDC("remotePort")); assertEquals("every event should have MDC[handlerClass]", SimpleIoHandler.class.getName(), event.getMDC("handlerClass")); } } // assert we have received all expected logging events for each client for (int i = 0; i < remoteAddressClients.length; i++) { SocketAddress remoteAddressClient = remoteAddressClients[i]; assertEventExists(events, "sessionCreated", remoteAddressClient, null); assertEventExists(events, "sessionOpened", remoteAddressClient, null); assertEventExists(events, "decode", remoteAddressClient, null); assertEventExists(events, "messageReceived-1", remoteAddressClient, null); assertEventExists(events, "messageReceived-2", remoteAddressClient, "user-" + i); assertEventExists(events, "encode", remoteAddressClient, null); assertEventExists(events, "exceptionCaught", remoteAddressClient, "user-" + i); assertEventExists(events, "messageSent-1", remoteAddressClient, "user-" + i); assertEventExists(events, "messageSent-2", remoteAddressClient, null); assertEventExists(events, "sessionIdle", remoteAddressClient, "user-" + i); assertEventExists(events, "sessionClosed", remoteAddressClient, "user-" + i); assertEventExists(events, "sessionClosed", remoteAddressClient, "user-" + i); assertEventExists(events, "DummyIoFilter.sessionOpened", remoteAddressClient, "user-" + i); } } private SocketAddress connectAndWrite(NioSocketConnector connector, int clientNr) { ConnectFuture connectFuture = connector.connect(new InetSocketAddress("localhost", port)); connectFuture.awaitUninterruptibly(TIMEOUT); IoBuffer message = IoBuffer.allocate(4).putInt(clientNr).flip(); IoSession session = connectFuture.getSession(); session.write(message).awaitUninterruptibly(TIMEOUT); return session.getLocalAddress(); } private void assertEventExists(List events, String message, SocketAddress address, String user) { InetSocketAddress remoteAddress = (InetSocketAddress) address; for (LoggingEvent event : events) { if (event.getMessage().equals(message) && event.getMDC("remoteAddress").equals(remoteAddress.toString()) && event.getMDC("remoteIp").equals(remoteAddress.getAddress().getHostAddress()) && event.getMDC("remotePort").equals(remoteAddress.getPort() + "")) { if (user == null && event.getMDC("user") == null) { return; } if (user != null && user.equals(event.getMDC("user"))) { return; } return; } } fail("No LoggingEvent found from [" + remoteAddress + "] with message [" + message + "]"); } private static class SimpleIoHandler extends IoHandlerAdapter { CountDownLatch sessionIdleLatch = new CountDownLatch(2); CountDownLatch sessionClosedLatch = new CountDownLatch(2); CountDownLatch messageSentLatch = new CountDownLatch(2); /** * Default constructor */ public SimpleIoHandler() { super(); } @Override public void sessionCreated(IoSession session) throws Exception { LOGGER.info("sessionCreated"); session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 1); } @Override public void sessionOpened(IoSession session) throws Exception { LOGGER.info("sessionOpened"); } @Override public void sessionClosed(IoSession session) throws Exception { LOGGER.info("sessionClosed"); sessionClosedLatch.countDown(); } @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { LOGGER.info("sessionIdle"); sessionIdleLatch.countDown(); session.close(true); } @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { LOGGER.info("exceptionCaught", cause); } @Override public void messageReceived(IoSession session, Object message) throws Exception { LOGGER.info("messageReceived-1"); // adding a custom property to the context String user = "user-" + message; MdcInjectionFilter.setProperty(session, "user", user); LOGGER.info("messageReceived-2"); session.getService().broadcast(message); throw new RuntimeException("just a test, forcing exceptionCaught"); } @Override public void messageSent(IoSession session, Object message) throws Exception { LOGGER.info("messageSent-1"); MdcInjectionFilter.removeProperty(session, "user"); LOGGER.info("messageSent-2"); messageSentLatch.countDown(); } } private static class DummyProtocolCodecFactory implements ProtocolCodecFactory { /** * Default constructor */ public DummyProtocolCodecFactory() { super(); } public ProtocolEncoder getEncoder(IoSession session) throws Exception { return new ProtocolEncoderAdapter() { public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { LOGGER.info("encode"); IoBuffer buffer = IoBuffer.allocate(4).putInt(123).flip(); out.write(buffer); } }; } public ProtocolDecoder getDecoder(IoSession session) throws Exception { return new ProtocolDecoderAdapter() { public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { if (in.remaining() >= 4) { int value = in.getInt(); LOGGER.info("decode"); out.write(value); } } }; } } private static class MyAppender extends AppenderSkeleton { List events = Collections.synchronizedList(new ArrayList()); /** * Default constructor */ public MyAppender() { super(); } public void clear() { events.clear(); } @Override protected void append(final LoggingEvent loggingEvent) { loggingEvent.getMDCCopy(); events.add(loggingEvent); } public boolean requiresLayout() { return false; } public void close() { // Do nothing } } static class DummyIoFilter extends IoFilterAdapter { @Override public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception { LOGGER.info("DummyIoFilter.sessionOpened"); nextFilter.sessionOpened(session); } } private List getThreadNames() { List list = new ArrayList(); int active = Thread.activeCount(); Thread[] threads = new Thread[active]; Thread.enumerate(threads); for (Thread thread : threads) { try { String name = thread.getName(); list.add(name); } catch (NullPointerException ignore) { } } return list; } private boolean contains(List list, String search) { for (String s : list) { if (s.contains(search)) { return true; } } return false; } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/keepalive/0000755000175000017500000000000012162575507026345 5ustar ebourgebourg././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/keepalive/KeepAliveFilterTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/keepalive/KeepAliveFilterTest.ja0000644000175000017500000001533112032276015032523 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.keepalive; import static org.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler.EXCEPTION; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import java.net.InetSocketAddress; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import org.apache.mina.transport.socket.nio.NioSocketConnector; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * Tests {@link KeepAliveFilter} used by the connector with different * interested {@link IdleStatus}es. * * @author Apache MINA Project */ public class KeepAliveFilterTest { // Constants ----------------------------------------------------- static final IoBuffer PING = IoBuffer.wrap(new byte[] { 1 }); static final IoBuffer PONG = IoBuffer.wrap(new byte[] { 2 }); private static final int INTERVAL = 2; private static final int TIMEOUT = 1; private int port; private NioSocketAcceptor acceptor; @Before public void setUp() throws Exception { acceptor = new NioSocketAcceptor(); KeepAliveMessageFactory factory = new ServerFactory(); KeepAliveFilter filter = new KeepAliveFilter(factory, IdleStatus.BOTH_IDLE); acceptor.getFilterChain().addLast("keep-alive", filter); acceptor.setHandler(new IoHandlerAdapter()); acceptor.setDefaultLocalAddress(new InetSocketAddress(0)); acceptor.bind(); port = acceptor.getLocalAddress().getPort(); } @After public void tearDown() throws Exception { acceptor.unbind(); acceptor.dispose(); } @Test public void testKeepAliveFilterForReaderIdle() throws Exception { keepAliveFilterForIdleStatus(IdleStatus.READER_IDLE); } @Test public void testKeepAliveFilterForBothIdle() throws Exception { keepAliveFilterForIdleStatus(IdleStatus.BOTH_IDLE); } @Test public void testKeepAliveFilterForWriterIdle() throws Exception { keepAliveFilterForIdleStatus(IdleStatus.WRITER_IDLE); } // Package protected --------------------------------------------- // Protected ----------------------------------------------------- // Private ------------------------------------------------------- private void keepAliveFilterForIdleStatus(IdleStatus status) throws Exception { NioSocketConnector connector = new NioSocketConnector(); KeepAliveFilter filter = new KeepAliveFilter(new ClientFactory(), status, EXCEPTION, INTERVAL, TIMEOUT); filter.setForwardEvent(true); connector.getFilterChain().addLast("keep-alive", filter); final AtomicBoolean gotException = new AtomicBoolean(false); connector.setHandler(new IoHandlerAdapter() { @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { //cause.printStackTrace(); gotException.set(true); } @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { // Do nothing } }); ConnectFuture future = connector.connect(new InetSocketAddress("127.0.0.1", port)).awaitUninterruptibly(); IoSession session = future.getSession(); assertNotNull(session); Thread.sleep((INTERVAL + TIMEOUT + 1) * 1000); assertFalse("got an exception on the client", gotException.get()); session.close(true); connector.dispose(); } static boolean checkRequest(IoBuffer message) { IoBuffer buff = message; boolean check = buff.get() == 1; buff.rewind(); return check; } static boolean checkResponse(IoBuffer message) { IoBuffer buff = message; boolean check = buff.get() == 2; buff.rewind(); return check; } // Inner classes ------------------------------------------------- private final class ServerFactory implements KeepAliveMessageFactory { /** * Default constructor */ public ServerFactory() { super(); } public Object getRequest(IoSession session) { return null; } public Object getResponse(IoSession session, Object request) { return PONG.duplicate(); } public boolean isRequest(IoSession session, Object message) { if (message instanceof IoBuffer) { return checkRequest((IoBuffer) message); } return false; } public boolean isResponse(IoSession session, Object message) { if (message instanceof IoBuffer) { return checkResponse((IoBuffer) message); } return false; } } private final class ClientFactory implements KeepAliveMessageFactory { /** * Default constructor */ public ClientFactory() { super(); } public Object getRequest(IoSession session) { return PING.duplicate(); } public Object getResponse(IoSession session, Object request) { return null; } public boolean isRequest(IoSession session, Object message) { if (message instanceof IoBuffer) { return checkRequest((IoBuffer) message); } return false; } public boolean isResponse(IoSession session, Object message) { if (message instanceof IoBuffer) { return checkResponse((IoBuffer) message); } return false; } } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/ssl/0000755000175000017500000000000012162575507025201 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/ssl/KeyStoreFactoryTest.java0000644000175000017500000000456312032276014031774 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.ssl; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.security.KeyStore; import org.junit.Test; /** * Tests {@link KeyStoreFactory}. * * @author Apache MINA Project */ public class KeyStoreFactoryTest { @Test public void testCreateInstanceFromResource() throws Exception { // Test using default for now. KeyStoreFactory factory = new KeyStoreFactory(); factory.setDataUrl(getClass().getResource("keystore.cert")); factory.setPassword("boguspw"); KeyStore ks = factory.newInstance(); ks.getCertificate("bogus"); ks.getKey("bogus", "boguspw".toCharArray()); } @Test public void testCreateInstanceFromFile() throws Exception { // Copy the keystore from the class path to a temporary file. File file = File.createTempFile("keystoretest ", null); file.deleteOnExit(); InputStream in = getClass().getResourceAsStream("keystore.cert"); OutputStream out = new FileOutputStream(file); int b; while ((b = in.read()) != -1) { out.write(b); } in.close(); out.close(); // Test using default for now. KeyStoreFactory factory = new KeyStoreFactory(); factory.setDataFile(file); factory.setPassword("boguspw"); KeyStore ks = factory.newInstance(); ks.getCertificate("bogus"); ks.getKey("bogus", "boguspw".toCharArray()); } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/ssl/SslTest.java0000644000175000017500000001442212032276014027433 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */package org.apache.mina.filter.ssl; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.Security; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import org.apache.mina.util.AvailablePortFinder; import org.junit.Test; /** * Test a SSL session where the connection is established and closed twice. It should be * processed correctly (Test for DIRMINA-650) * * @author Apache MINA Project */ public class SslTest { /** A static port used for his test, chosen to avoid collisions */ private static final int port = AvailablePortFinder.getNextAvailable(5555); private static Exception clientError = null; private static InetAddress address; private static SSLSocketFactory factory; /** A JVM independant KEY_MANAGER_FACTORY algorithm */ private static final String KEY_MANAGER_FACTORY_ALGORITHM; static { String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm"); if (algorithm == null) { algorithm = KeyManagerFactory.getDefaultAlgorithm(); } KEY_MANAGER_FACTORY_ALGORITHM = algorithm; } private static class TestHandler extends IoHandlerAdapter { public void messageReceived(IoSession session, Object message) throws Exception { String line = (String) message; if (line.startsWith("hello")) { System.out.println("Server got: 'hello', waiting for 'send'"); Thread.sleep(1500); } else if (line.startsWith("send")) { System.out.println("Server got: 'send', sending 'data'"); session.write("data"); } } } /** * Starts a Server with the SSL Filter and a simple text line * protocol codec filter */ private static void startServer() throws Exception { NioSocketAcceptor acceptor = new NioSocketAcceptor(); acceptor.setReuseAddress(true); DefaultIoFilterChainBuilder filters = acceptor.getFilterChain(); // Inject the SSL filter SslFilter sslFilter = new SslFilter(createSSLContext()); filters.addLast("sslFilter", sslFilter); // Inject the TestLine codec filter filters.addLast("text", new ProtocolCodecFilter(new TextLineCodecFactory())); acceptor.setHandler(new TestHandler()); acceptor.bind(new InetSocketAddress(port)); } /** * Starts a client which will connect twice using SSL */ private static void startClient() throws Exception { address = InetAddress.getByName("localhost"); SSLContext context = createSSLContext(); factory = context.getSocketFactory(); connectAndSend(); // This one will throw a SocketTimeoutException if DIRMINA-650 is not fixed connectAndSend(); } private static void connectAndSend() throws Exception { Socket parent = new Socket(address, port); Socket socket = factory.createSocket(parent, address.getCanonicalHostName(), port, false); System.out.println("Client sending: hello"); socket.getOutputStream().write("hello \n".getBytes()); socket.getOutputStream().flush(); socket.setSoTimeout(10000); System.out.println("Client sending: send"); socket.getOutputStream().write("send\n".getBytes()); socket.getOutputStream().flush(); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); String line = in.readLine(); System.out.println("Client got: " + line); socket.close(); } private static SSLContext createSSLContext() throws IOException, GeneralSecurityException { char[] passphrase = "password".toCharArray(); SSLContext ctx = SSLContext.getInstance("TLS"); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM); TrustManagerFactory tmf = TrustManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM); KeyStore ks = KeyStore.getInstance("JKS"); KeyStore ts = KeyStore.getInstance("JKS"); ks.load(SslTest.class.getResourceAsStream("keystore.sslTest"), passphrase); ts.load(SslTest.class.getResourceAsStream("truststore.sslTest"), passphrase); kmf.init(ks, passphrase); tmf.init(ts); ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); return ctx; } @Test public void testSSL() throws Exception { startServer(); Thread t = new Thread() { public void run() { try { startClient(); } catch (Exception e) { clientError = e; } } }; t.start(); t.join(); if (clientError != null) throw clientError; } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/firewall/0000755000175000017500000000000012162575507026205 5ustar ebourgebourg././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/firewall/ConnectionThrottleFilterTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/firewall/ConnectionThrottleFilte0000644000175000017500000000450512032276014032730 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.firewall; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.net.InetSocketAddress; import org.apache.mina.core.session.DummySession; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * TODO Add documentation * * @author Apache MINA Project */ public class ConnectionThrottleFilterTest { private ConnectionThrottleFilter filter; private DummySession sessionOne; private DummySession sessionTwo; @Before public void setUp() throws Exception { filter = new ConnectionThrottleFilter(); sessionOne = new DummySession(); sessionOne.setRemoteAddress(new InetSocketAddress(1234)); sessionTwo = new DummySession(); sessionTwo.setRemoteAddress(new InetSocketAddress(1235)); } @After public void tearDown() throws Exception { filter = null; } @Test public void testGoodConnection() { filter.setAllowedInterval(100); filter.isConnectionOk(sessionOne); try { Thread.sleep(1000); } catch (InterruptedException e) { //e.printStackTrace(); } boolean result = filter.isConnectionOk(sessionOne); assertTrue(result); } @Test public void testBadConnection() { filter.setAllowedInterval(1000); filter.isConnectionOk(sessionTwo); assertFalse(filter.isConnectionOk(sessionTwo)); } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/firewall/SubnetIPv6Test.java0000644000175000017500000000326512032276014031646 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.firewall; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; import org.junit.Test; /** * TODO Add documentation * * @author Apache MINA Project */ public class SubnetIPv6Test { // Test Data private static final String TEST_V6ADDRESS = "1080:0:0:0:8:800:200C:417A"; @Test public void testIPv6() throws UnknownHostException { InetAddress a = InetAddress.getByName(TEST_V6ADDRESS); assertTrue(a instanceof Inet6Address); try { new Subnet(a, 24); fail("IPv6 not supported"); } catch (IllegalArgumentException e) { // signifies a successful test execution assertTrue(true); } } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/firewall/SubnetIPv4Test.java0000644000175000017500000000724212032276014031643 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.firewall; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.net.InetAddress; import java.net.UnknownHostException; import org.junit.Test; /** * TODO Add documentation * * @author Apache MINA Project */ public class SubnetIPv4Test { @Test public void test24() throws UnknownHostException { InetAddress a = InetAddress.getByName("127.2.3.0"); InetAddress b = InetAddress.getByName("127.2.3.4"); InetAddress c = InetAddress.getByName("127.2.3.255"); InetAddress d = InetAddress.getByName("127.2.4.4"); Subnet mask = new Subnet(a, 24); assertTrue(mask.inSubnet(a)); assertTrue(mask.inSubnet(b)); assertTrue(mask.inSubnet(c)); assertFalse(mask.inSubnet(d)); } @Test public void test16() throws UnknownHostException { InetAddress a = InetAddress.getByName("127.2.0.0"); InetAddress b = InetAddress.getByName("127.2.3.4"); InetAddress c = InetAddress.getByName("127.2.129.255"); InetAddress d = InetAddress.getByName("127.3.4.4"); Subnet mask = new Subnet(a, 16); assertTrue(mask.inSubnet(a)); assertTrue(mask.inSubnet(b)); assertTrue(mask.inSubnet(c)); assertFalse(mask.inSubnet(d)); } @Test public void testSingleIp() throws UnknownHostException { InetAddress a = InetAddress.getByName("127.2.3.4"); InetAddress b = InetAddress.getByName("127.2.3.3"); InetAddress c = InetAddress.getByName("127.2.3.255"); InetAddress d = InetAddress.getByName("127.2.3.0"); Subnet mask = new Subnet(a, 32); assertTrue(mask.inSubnet(a)); assertFalse(mask.inSubnet(b)); assertFalse(mask.inSubnet(c)); assertFalse(mask.inSubnet(d)); } @Test public void testToString() throws UnknownHostException { InetAddress a = InetAddress.getByName("127.2.3.0"); Subnet mask = new Subnet(a, 24); assertEquals("127.2.3.0/24", mask.toString()); } @Test public void testToStringLiteral() throws UnknownHostException { InetAddress a = InetAddress.getByName("localhost"); Subnet mask = new Subnet(a, 32); assertEquals("127.0.0.1/32", mask.toString()); } @Test public void testEquals() throws UnknownHostException { Subnet a = new Subnet(InetAddress.getByName("127.2.3.4"), 32); Subnet b = new Subnet(InetAddress.getByName("127.2.3.4"), 32); Subnet c = new Subnet(InetAddress.getByName("127.2.3.5"), 32); Subnet d = new Subnet(InetAddress.getByName("127.2.3.5"), 24); assertTrue(a.equals(b)); assertFalse(a.equals(c)); assertFalse(a.equals(d)); assertFalse(a.equals(null)); } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/buffer/0000755000175000017500000000000012162575507025651 5ustar ebourgebourg././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/buffer/BufferedWriteFilterTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/buffer/BufferedWriteFilterTest.j0000644000175000017500000000675712032276015032572 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.buffer; import static org.junit.Assert.assertEquals; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.session.DummySession; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.filter.logging.LoggingFilter; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Tests {@link BufferedWriteFilter}. * * @author Apache MINA Project * @since MINA 2.0.0-M2 */ public class BufferedWriteFilterTest { static final Logger LOGGER = LoggerFactory.getLogger(BufferedWriteFilterTest.class); @Test public void testNonExpandableBuffer() throws Exception { IoBuffer dest = IoBuffer.allocate(1); assertEquals(false, dest.isAutoExpand()); } @Test public void testBasicBuffering() { DummySession sess = new DummySession(); sess.getFilterChain().addFirst("peer", new IoFilterAdapter() { private int counter; @Override public void filterClose(NextFilter nextFilter, IoSession session) throws Exception { LOGGER.debug("Filter closed !"); assertEquals(3, counter); } @Override public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { LOGGER.debug("New buffered message written !"); counter++; try { IoBuffer buf = (IoBuffer) writeRequest.getMessage(); if (counter == 3) { assertEquals(1, buf.limit()); assertEquals(0, buf.get()); } else { assertEquals(10, buf.limit()); } } catch (Exception ex) { throw new AssertionError("Wrong message type"); } } }); sess.getFilterChain().addFirst("logger", new LoggingFilter()); BufferedWriteFilter bFilter = new BufferedWriteFilter(10); sess.getFilterChain().addLast("buffer", bFilter); IoBuffer data = IoBuffer.allocate(1); for (byte i = 0; i < 20; i++) { data.put((byte) (0x30 + i)); data.flip(); sess.write(data); data.clear(); } // Add one more byte to overflow the final buffer data.put((byte) 0); data.flip(); sess.write(data); // Flush the final byte bFilter.flush(sess); sess.close(true); } }mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/stream/0000755000175000017500000000000012162575507025673 5ustar ebourgebourg././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/stream/FileRegionWriteFilterTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/stream/FileRegionWriteFilterTest0000644000175000017500000000347412032276015032656 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.stream; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import org.apache.mina.core.file.DefaultFileRegion; import org.apache.mina.core.file.FileRegion; /** * Tests {@link StreamWriteFilter}. * * @author Apache MINA Project */ public class FileRegionWriteFilterTest extends AbstractStreamWriteFilterTest { @Override protected FileRegionWriteFilter createFilter() { return new FileRegionWriteFilter(); } @Override protected FileRegion createMessage(byte[] data) throws IOException { File file = File.createTempFile("mina", "unittest"); file.deleteOnExit(); FileChannel channel = new RandomAccessFile(file, "rw").getChannel(); ByteBuffer buffer = ByteBuffer.wrap(data); channel.write(buffer); return new DefaultFileRegion(channel); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/stream/StreamWriteFilterTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/stream/StreamWriteFilterTest.jav0000644000175000017500000000257612032276015032647 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.stream; import java.io.ByteArrayInputStream; import java.io.InputStream; /** * Tests {@link StreamWriteFilter}. * * @author Apache MINA Project */ public class StreamWriteFilterTest extends AbstractStreamWriteFilterTest { @Override protected StreamWriteFilter createFilter() { return new StreamWriteFilter(); } @Override protected InputStream createMessage(byte[] data) throws Exception { return new ByteArrayInputStream(data); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/stream/AbstractStreamWriteFilterTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/stream/AbstractStreamWriteFilter0000644000175000017500000004374112032276015032713 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.stream; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.security.MessageDigest; import java.util.LinkedList; import java.util.Queue; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.DummySession; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.DefaultWriteRequest; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import org.apache.mina.transport.socket.nio.NioSocketConnector; import org.apache.mina.util.AvailablePortFinder; import org.easymock.IArgumentMatcher; import org.easymock.classextension.EasyMock; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * TODO Add documentation * * @author Apache MINA Project */ public abstract class AbstractStreamWriteFilterTest> { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractStreamWriteFilterTest.class); protected final IoSession session = new DummySession(); abstract protected U createFilter(); abstract protected M createMessage(byte[] data) throws Exception; @Test public void testWriteEmptyFile() throws Exception { AbstractStreamWriteFilter filter = createFilter(); M message = createMessage(new byte[0]); WriteRequest writeRequest = new DefaultWriteRequest(message, new DummyWriteFuture()); NextFilter nextFilter = EasyMock.createMock(NextFilter.class); /* * Record expectations */ nextFilter.messageSent(session, writeRequest); /* * Replay. */ EasyMock.replay(nextFilter); filter.filterWrite(nextFilter, session, writeRequest); /* * Verify. */ EasyMock.verify(nextFilter); assertTrue(writeRequest.getFuture().isWritten()); } /** * Tests that the filter just passes objects which aren't FileRegion's * through to the next filter. * * @throws Exception when something goes wrong */ @Test public void testWriteNonFileRegionMessage() throws Exception { AbstractStreamWriteFilter filter = createFilter(); Object message = new Object(); WriteRequest writeRequest = new DefaultWriteRequest(message, new DummyWriteFuture()); NextFilter nextFilter = EasyMock.createMock(NextFilter.class); /* * Record expectations */ nextFilter.filterWrite(session, writeRequest); nextFilter.messageSent(session, writeRequest); /* * Replay. */ EasyMock.replay(nextFilter); filter.filterWrite(nextFilter, session, writeRequest); filter.messageSent(nextFilter, session, writeRequest); /* * Verify. */ EasyMock.verify(nextFilter); } /** * Tests when the contents of the file fits into one write buffer. * * @throws Exception when something goes wrong */ @Test public void testWriteSingleBufferFile() throws Exception { byte[] data = new byte[] { 1, 2, 3, 4 }; AbstractStreamWriteFilter filter = createFilter(); M message = createMessage(data); WriteRequest writeRequest = new DefaultWriteRequest(message, new DummyWriteFuture()); NextFilter nextFilter = EasyMock.createMock(NextFilter.class); /* * Record expectations */ nextFilter.filterWrite(EasyMock.eq(session), eqWriteRequest(new DefaultWriteRequest(IoBuffer.wrap(data)))); nextFilter.messageSent(session, writeRequest); /* * Replay. */ EasyMock.replay(nextFilter); filter.filterWrite(nextFilter, session, writeRequest); filter.messageSent(nextFilter, session, writeRequest); /* * Verify. */ EasyMock.verify(nextFilter); assertTrue(writeRequest.getFuture().isWritten()); } /** * Tests when the contents of the file doesn't fit into one write buffer. * * @throws Exception when something goes wrong */ @Test public void testWriteSeveralBuffersStream() throws Exception { AbstractStreamWriteFilter filter = createFilter(); filter.setWriteBufferSize(4); byte[] data = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; byte[] chunk1 = new byte[] { 1, 2, 3, 4 }; byte[] chunk2 = new byte[] { 5, 6, 7, 8 }; byte[] chunk3 = new byte[] { 9, 10 }; M message = createMessage(data); WriteRequest writeRequest = new DefaultWriteRequest(message, new DummyWriteFuture()); WriteRequest chunk1Request = new DefaultWriteRequest(IoBuffer.wrap(chunk1)); WriteRequest chunk2Request = new DefaultWriteRequest(IoBuffer.wrap(chunk2)); WriteRequest chunk3Request = new DefaultWriteRequest(IoBuffer.wrap(chunk3)); NextFilter nextFilter = EasyMock.createMock(NextFilter.class); /* * Record expectations */ nextFilter.filterWrite(EasyMock.eq(session), eqWriteRequest(chunk1Request)); nextFilter.filterWrite(EasyMock.eq(session), eqWriteRequest(chunk2Request)); nextFilter.filterWrite(EasyMock.eq(session), eqWriteRequest(chunk3Request)); nextFilter.messageSent(EasyMock.eq(session), eqWriteRequest(writeRequest)); /* * Replay. */ EasyMock.replay(nextFilter); filter.filterWrite(nextFilter, session, writeRequest); filter.messageSent(nextFilter, session, chunk1Request); filter.messageSent(nextFilter, session, chunk2Request); filter.messageSent(nextFilter, session, chunk3Request); /* * Verify. */ EasyMock.verify(nextFilter); assertTrue(writeRequest.getFuture().isWritten()); } @Test public void testWriteWhileWriteInProgress() throws Exception { AbstractStreamWriteFilter filter = createFilter(); M message = createMessage(new byte[5]); Queue queue = new LinkedList(); /* * Make up the situation. */ session.setAttribute(filter.CURRENT_STREAM, message); session.setAttribute(filter.WRITE_REQUEST_QUEUE, queue); NextFilter nextFilter = EasyMock.createMock(NextFilter.class); /* * Replay. (We recorded *nothing* because nothing should occur.) */ EasyMock.replay(nextFilter); WriteRequest wr = new DefaultWriteRequest(new Object(), new DummyWriteFuture()); filter.filterWrite(nextFilter, session, wr); assertEquals(1, queue.size()); assertSame(wr, queue.poll()); /* * Verify. */ EasyMock.verify(nextFilter); session.removeAttribute(filter.CURRENT_STREAM); session.removeAttribute(filter.WRITE_REQUEST_QUEUE); } @Test public void testWritesWriteRequestQueueWhenFinished() throws Exception { AbstractStreamWriteFilter filter = createFilter(); M message = createMessage(new byte[0]); WriteRequest wrs[] = new WriteRequest[] { new DefaultWriteRequest(new Object(), new DummyWriteFuture()), new DefaultWriteRequest(new Object(), new DummyWriteFuture()), new DefaultWriteRequest(new Object(), new DummyWriteFuture()) }; Queue queue = new LinkedList(); queue.add(wrs[0]); queue.add(wrs[1]); queue.add(wrs[2]); /* * Make up the situation. */ session.setAttribute(filter.CURRENT_STREAM, message); session.setAttribute(filter.CURRENT_WRITE_REQUEST, new DefaultWriteRequest(message)); session.setAttribute(filter.WRITE_REQUEST_QUEUE, queue); /* * Record expectations */ NextFilter nextFilter = EasyMock.createMock(NextFilter.class); nextFilter.filterWrite(session, wrs[0]); nextFilter.filterWrite(session, wrs[1]); nextFilter.filterWrite(session, wrs[2]); nextFilter.messageSent(EasyMock.eq(session), eqWriteRequest(new DefaultWriteRequest(message))); /* * Replay. */ EasyMock.replay(nextFilter); filter.messageSent(nextFilter, session, new DefaultWriteRequest(new Object())); assertEquals(0, queue.size()); /* * Verify. */ EasyMock.verify(nextFilter); } /** * Tests that {@link StreamWriteFilter#setWriteBufferSize(int)} checks the * specified size. */ @Test public void testSetWriteBufferSize() { AbstractStreamWriteFilter filter = createFilter(); try { filter.setWriteBufferSize(0); fail("0 writeBuferSize specified. IllegalArgumentException expected."); } catch (IllegalArgumentException iae) { // Pass, exception was thrown // Signifies a successful test execution assertTrue(true); } try { filter.setWriteBufferSize(-100); fail("Negative writeBuferSize specified. IllegalArgumentException expected."); } catch (IllegalArgumentException iae) { // Pass, exception was thrown // Signifies a successful test execution assertTrue(true); } filter.setWriteBufferSize(1); assertEquals(1, filter.getWriteBufferSize()); filter.setWriteBufferSize(1024); assertEquals(1024, filter.getWriteBufferSize()); } @Test public void testWriteUsingSocketTransport() throws Exception { NioSocketAcceptor acceptor = new NioSocketAcceptor(); acceptor.setReuseAddress(true); SocketAddress address = new InetSocketAddress("localhost", AvailablePortFinder.getNextAvailable()); NioSocketConnector connector = new NioSocketConnector(); // Generate 4MB of random data byte[] data = new byte[4 * 1024 * 1024]; new Random().nextBytes(data); byte[] expectedMd5 = MessageDigest.getInstance("MD5").digest(data); M message = createMessage(data); SenderHandler sender = new SenderHandler(message); ReceiverHandler receiver = new ReceiverHandler(data.length); acceptor.setHandler(sender); connector.setHandler(receiver); acceptor.bind(address); connector.connect(address); sender.latch.await(); receiver.latch.await(); acceptor.dispose(); assertEquals(data.length, receiver.bytesRead); byte[] actualMd5 = receiver.digest.digest(); assertEquals(expectedMd5.length, actualMd5.length); for (int i = 0; i < expectedMd5.length; i++) { assertEquals(expectedMd5[i], actualMd5[i]); } } private class SenderHandler extends IoHandlerAdapter { final CountDownLatch latch = new CountDownLatch(1); private M message; StreamWriteFilter streamWriteFilter = new StreamWriteFilter(); SenderHandler(M message) { this.message = message; } @Override public void sessionCreated(IoSession session) throws Exception { super.sessionCreated(session); session.getFilterChain().addLast("codec", streamWriteFilter); } @Override public void sessionOpened(IoSession session) throws Exception { session.write(message); } @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { LOGGER.error("SenderHandler: exceptionCaught", cause); latch.countDown(); } @Override public void sessionClosed(IoSession session) throws Exception { LOGGER.info("SenderHandler: sessionClosed"); latch.countDown(); } @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { LOGGER.info("SenderHandler: sessionIdle"); latch.countDown(); } @Override public void messageSent(IoSession session, Object message) throws Exception { LOGGER.info("SenderHandler: messageSent"); if (message == this.message) { LOGGER.info("message == this.message"); latch.countDown(); } } } private static class ReceiverHandler extends IoHandlerAdapter { final CountDownLatch latch = new CountDownLatch(1); long bytesRead = 0; long size = 0; MessageDigest digest; ReceiverHandler(long size) throws Exception { this.size = size; digest = MessageDigest.getInstance("MD5"); } @Override public void sessionCreated(IoSession session) throws Exception { super.sessionCreated(session); session.getConfig().setIdleTime(IdleStatus.READER_IDLE, 5); } @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { LOGGER.info("ReceiverHandler: sessionIdle"); session.close(true); } @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { LOGGER.error("ReceiverHandler: exceptionCaught", cause); latch.countDown(); } @Override public void sessionClosed(IoSession session) throws Exception { LOGGER.info("ReceiverHandler: sessionClosed"); latch.countDown(); } @Override public void messageReceived(IoSession session, Object message) throws Exception { LOGGER.info("messageReceived"); IoBuffer buf = (IoBuffer) message; while (buf.hasRemaining()) { digest.update(buf.get()); bytesRead++; } LOGGER.info("messageReceived: bytesRead = {}", bytesRead); if (bytesRead >= size) { session.close(true); } } } public static WriteRequest eqWriteRequest(WriteRequest expected) { EasyMock.reportMatcher(new WriteRequestMatcher(expected)); return null; } private static class WriteRequestMatcher implements IArgumentMatcher { private final WriteRequest expected; public WriteRequestMatcher(WriteRequest expected) { this.expected = expected; } public boolean matches(Object actual) { if (actual instanceof WriteRequest) { WriteRequest w2 = (WriteRequest) actual; return expected.getMessage().equals(w2.getMessage()) && expected.getFuture().isWritten() == w2.getFuture().isWritten(); } return false; } public void appendTo(StringBuffer buffer) { buffer.append("Expected a WriteRequest with the message '").append(expected.getMessage()).append("'"); } } private static class DummyWriteFuture implements WriteFuture { private boolean written; /** * Default constructor */ public DummyWriteFuture() { super(); } public boolean isWritten() { return written; } public void setWritten() { this.written = true; } public IoSession getSession() { return null; } public Object getLock() { return this; } public void join() { // Do nothing } public boolean join(long timeoutInMillis) { return true; } public boolean isDone() { return true; } public WriteFuture addListener(IoFutureListener listener) { return this; } public WriteFuture removeListener(IoFutureListener listener) { return this; } public WriteFuture await() throws InterruptedException { return this; } public boolean await(long timeout, TimeUnit unit) throws InterruptedException { return true; } public boolean await(long timeoutMillis) throws InterruptedException { return true; } public WriteFuture awaitUninterruptibly() { return this; } public boolean awaitUninterruptibly(long timeout, TimeUnit unit) { return true; } public boolean awaitUninterruptibly(long timeoutMillis) { return true; } public Throwable getException() { return null; } public void setException(Throwable cause) { throw new IllegalStateException(); } } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/codec/0000755000175000017500000000000012162575507025455 5ustar ebourgebourg././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/codec/DemuxingProtocolDecoderBugTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/codec/DemuxingProtocolDecoderBug0000644000175000017500000001044212032276015032613 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import org.apache.mina.filter.codec.demux.MessageDecoderResult; import org.apache.mina.filter.codec.demux.MessageDecoderAdapter; import org.apache.mina.filter.codec.demux.DemuxingProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.DummySession; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.service.DefaultTransportMetadata; import org.apache.mina.core.file.FileRegion; import org.apache.mina.transport.socket.SocketSessionConfig; import org.easymock.EasyMock; import org.junit.Test; import java.net.InetSocketAddress; import java.nio.charset.Charset; /** * Simple Unit Test showing that the DemuxingProtocolDecoder has * inconsistent behavior if used with a non fragmented transport. * * @author Apache MINA Project */ public class DemuxingProtocolDecoderBugTest { private static void doTest(IoSession session) throws Exception { ProtocolDecoderOutput mock = EasyMock.createMock(ProtocolDecoderOutput.class); mock.write(Character.valueOf('A')); mock.write(Character.valueOf('B')); mock.write(Integer.valueOf(1)); mock.write(Integer.valueOf(2)); mock.write(Character.valueOf('C')); EasyMock.replay(mock); IoBuffer buffer = IoBuffer.allocate(1000); buffer.putString("AB12C", Charset.defaultCharset().newEncoder()); buffer.flip(); DemuxingProtocolDecoder decoder = new DemuxingProtocolDecoder(); decoder.addMessageDecoder(CharacterMessageDecoder.class); decoder.addMessageDecoder(IntegerMessageDecoder.class); decoder.decode(session, buffer, mock); EasyMock.verify(mock); } public static class CharacterMessageDecoder extends MessageDecoderAdapter { public MessageDecoderResult decodable(IoSession session, IoBuffer in) { return Character.isDigit((char) in.get()) ? MessageDecoderResult.NOT_OK : MessageDecoderResult.OK; } public MessageDecoderResult decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { out.write(Character.valueOf((char) in.get())); return MessageDecoderResult.OK; } } public static class IntegerMessageDecoder extends MessageDecoderAdapter { public MessageDecoderResult decodable(IoSession session, IoBuffer in) { return Character.isDigit((char) in.get()) ? MessageDecoderResult.OK : MessageDecoderResult.NOT_OK; } public MessageDecoderResult decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { out.write(Integer.parseInt("" + (char) in.get())); return MessageDecoderResult.OK; } } private static class SessionStub extends DummySession { public SessionStub(boolean fragmented) { setTransportMetadata(new DefaultTransportMetadata("nio", "socket", false, fragmented, InetSocketAddress.class, SocketSessionConfig.class, IoBuffer.class, FileRegion.class)); } } /** * Test a decoding with fragmentation */ @Test public void testFragmentedTransport() throws Exception { doTest(new SessionStub(true)); } /** * Test a decoding without fragmentation */ @Test public void testNonFragmentedTransport() throws Exception { doTest(new SessionStub(false)); } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/codec/textline/0000755000175000017500000000000012162575507027311 5ustar ebourgebourg././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTe0000644000175000017500000003311512032276015032536 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.textline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.filter.codec.ProtocolCodecSession; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import org.apache.mina.filter.codec.RecoverableProtocolDecoderException; import org.junit.Test; /** * Tests {@link TextLineDecoder}. * * @author Apache MINA Project */ public class TextLineDecoderTest { @Test public void testNormalDecode() throws Exception { TextLineDecoder decoder = new TextLineDecoder(Charset.forName("UTF-8"), LineDelimiter.WINDOWS); CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder(); ProtocolCodecSession session = new ProtocolCodecSession(); ProtocolDecoderOutput out = session.getDecoderOutput(); IoBuffer in = IoBuffer.allocate(16); // Test one decode and one output in.putString("ABC\r\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(1, session.getDecoderOutputQueue().size()); assertEquals("ABC", session.getDecoderOutputQueue().poll()); // Test two decode and one output in.clear(); in.putString("DEF", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(0, session.getDecoderOutputQueue().size()); in.clear(); in.putString("GHI\r\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(1, session.getDecoderOutputQueue().size()); assertEquals("DEFGHI", session.getDecoderOutputQueue().poll()); // Test one decode and two output in.clear(); in.putString("JKL\r\nMNO\r\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(2, session.getDecoderOutputQueue().size()); assertEquals("JKL", session.getDecoderOutputQueue().poll()); assertEquals("MNO", session.getDecoderOutputQueue().poll()); // Test aborted delimiter (DIRMINA-506) in.clear(); in.putString("ABC\r\r\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(1, session.getDecoderOutputQueue().size()); assertEquals("ABC\r", session.getDecoderOutputQueue().poll()); // Test splitted long delimiter decoder = new TextLineDecoder(Charset.forName("UTF-8"), new LineDelimiter("\n\n\n")); in.clear(); in.putString("PQR\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(0, session.getDecoderOutputQueue().size()); in.clear(); in.putString("\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(0, session.getDecoderOutputQueue().size()); in.clear(); in.putString("\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(1, session.getDecoderOutputQueue().size()); assertEquals("PQR", session.getDecoderOutputQueue().poll()); // Test splitted long delimiter which produces two output decoder = new TextLineDecoder(Charset.forName("UTF-8"), new LineDelimiter("\n\n\n")); in.clear(); in.putString("PQR\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(0, session.getDecoderOutputQueue().size()); in.clear(); in.putString("\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(0, session.getDecoderOutputQueue().size()); in.clear(); in.putString("\nSTU\n\n\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(2, session.getDecoderOutputQueue().size()); assertEquals("PQR", session.getDecoderOutputQueue().poll()); assertEquals("STU", session.getDecoderOutputQueue().poll()); // Test splitted long delimiter mixed with partial non-delimiter. decoder = new TextLineDecoder(Charset.forName("UTF-8"), new LineDelimiter("\n\n\n")); in.clear(); in.putString("PQR\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(0, session.getDecoderOutputQueue().size()); in.clear(); in.putString("X\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(0, session.getDecoderOutputQueue().size()); in.clear(); in.putString("\n\nSTU\n\n\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(2, session.getDecoderOutputQueue().size()); assertEquals("PQR\nX", session.getDecoderOutputQueue().poll()); assertEquals("STU", session.getDecoderOutputQueue().poll()); } public void testAutoDecode() throws Exception { TextLineDecoder decoder = new TextLineDecoder(Charset.forName("UTF-8"), LineDelimiter.AUTO); CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder(); ProtocolCodecSession session = new ProtocolCodecSession(); ProtocolDecoderOutput out = session.getDecoderOutput(); IoBuffer in = IoBuffer.allocate(16); // Test one decode and one output in.putString("ABC\r\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(1, session.getDecoderOutputQueue().size()); assertEquals("ABC", session.getDecoderOutputQueue().poll()); // Test two decode and one output in.clear(); in.putString("DEF", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(0, session.getDecoderOutputQueue().size()); in.clear(); in.putString("GHI\r\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(1, session.getDecoderOutputQueue().size()); assertEquals("DEFGHI", session.getDecoderOutputQueue().poll()); // Test one decode and two output in.clear(); in.putString("JKL\r\nMNO\r\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(2, session.getDecoderOutputQueue().size()); assertEquals("JKL", session.getDecoderOutputQueue().poll()); assertEquals("MNO", session.getDecoderOutputQueue().poll()); // Test multiple '\n's in.clear(); in.putString("\n\n\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(3, session.getDecoderOutputQueue().size()); assertEquals("", session.getDecoderOutputQueue().poll()); assertEquals("", session.getDecoderOutputQueue().poll()); assertEquals("", session.getDecoderOutputQueue().poll()); // Test splitted long delimiter (\r\r\n) in.clear(); in.putString("PQR\r", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(0, session.getDecoderOutputQueue().size()); in.clear(); in.putString("\r", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(0, session.getDecoderOutputQueue().size()); in.clear(); in.putString("\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(1, session.getDecoderOutputQueue().size()); assertEquals("PQR", session.getDecoderOutputQueue().poll()); // Test splitted long delimiter (\r\r\n) which produces two output in.clear(); in.putString("PQR\r", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(0, session.getDecoderOutputQueue().size()); in.clear(); in.putString("\r", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(0, session.getDecoderOutputQueue().size()); in.clear(); in.putString("\nSTU\r\r\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(2, session.getDecoderOutputQueue().size()); assertEquals("PQR", session.getDecoderOutputQueue().poll()); assertEquals("STU", session.getDecoderOutputQueue().poll()); // Test splitted long delimiter mixed with partial non-delimiter. in.clear(); in.putString("PQR\r", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(0, session.getDecoderOutputQueue().size()); in.clear(); in.putString("X\r", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(0, session.getDecoderOutputQueue().size()); in.clear(); in.putString("\r\nSTU\r\r\n", encoder); in.flip(); decoder.decode(session, in, out); assertEquals(2, session.getDecoderOutputQueue().size()); assertEquals("PQR\rX", session.getDecoderOutputQueue().poll()); assertEquals("STU", session.getDecoderOutputQueue().poll()); in.clear(); String s = new String(new byte[] { 0, 77, 105, 110, 97 }); in.putString(s, encoder); in.flip(); decoder.decode(session, in, out); assertEquals(1, session.getDecoderOutputQueue().size()); assertEquals(s, session.getDecoderOutputQueue().poll()); } public void testOverflow() throws Exception { TextLineDecoder decoder = new TextLineDecoder(Charset.forName("UTF-8"), LineDelimiter.AUTO); decoder.setMaxLineLength(3); CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder(); ProtocolCodecSession session = new ProtocolCodecSession(); ProtocolDecoderOutput out = session.getDecoderOutput(); IoBuffer in = IoBuffer.allocate(16); // Make sure the overflow exception is not thrown until // the delimiter is encountered. in.putString("A", encoder).flip().mark(); decoder.decode(session, in.reset().mark(), out); assertEquals(0, session.getDecoderOutputQueue().size()); decoder.decode(session, in.reset().mark(), out); assertEquals(0, session.getDecoderOutputQueue().size()); decoder.decode(session, in.reset().mark(), out); assertEquals(0, session.getDecoderOutputQueue().size()); decoder.decode(session, in.reset().mark(), out); assertEquals(0, session.getDecoderOutputQueue().size()); in.clear().putString("A\r\nB\r\n", encoder).flip(); try { decoder.decode(session, in, out); fail(); } catch (RecoverableProtocolDecoderException e) { // signifies a successful test execution assertTrue(true); } decoder.decode(session, in, out); assertEquals(1, session.getDecoderOutputQueue().size()); assertEquals("B", session.getDecoderOutputQueue().poll()); // Make sure OOM is not thrown. System.gc(); long oldFreeMemory = Runtime.getRuntime().freeMemory(); in = IoBuffer.allocate(1048576 * 16).sweep((byte) ' ').mark(); for (int i = 0; i < 10; i++) { decoder.decode(session, in.reset().mark(), out); assertEquals(0, session.getDecoderOutputQueue().size()); // Memory consumption should be minimal. assertTrue(Runtime.getRuntime().freeMemory() - oldFreeMemory < 1048576); } in.clear().putString("C\r\nD\r\n", encoder).flip(); try { decoder.decode(session, in, out); fail(); } catch (RecoverableProtocolDecoderException e) { // signifies a successful test execution assertTrue(true); } decoder.decode(session, in, out); assertEquals(1, session.getDecoderOutputQueue().size()); assertEquals("D", session.getDecoderOutputQueue().poll()); // Memory consumption should be minimal. assertTrue(Runtime.getRuntime().freeMemory() - oldFreeMemory < 1048576); } public void testSMTPDataBounds() throws Exception { TextLineDecoder decoder = new TextLineDecoder(Charset.forName("ISO-8859-1"), new LineDelimiter("\r\n.\r\n")); CharsetEncoder encoder = Charset.forName("ISO-8859-1").newEncoder(); ProtocolCodecSession session = new ProtocolCodecSession(); IoBuffer in = IoBuffer.allocate(16).setAutoExpand(true); in.putString("\r\n", encoder).flip().mark(); decoder.decode(session, in.reset().mark(), session.getDecoderOutput()); assertEquals(0, session.getDecoderOutputQueue().size()); in.putString("Body\r\n.\r\n", encoder).flip().mark(); decoder.decode(session, in.reset().mark(), session.getDecoderOutput()); assertEquals(1, session.getDecoderOutputQueue().size()); assertEquals("\r\n\r\nBody", session.getDecoderOutputQueue().poll()); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/codec/textline/TextLineEncoderTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/codec/textline/TextLineEncoderTe0000644000175000017500000000372712032276015032556 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.textline; import static org.junit.Assert.assertEquals; import java.nio.charset.Charset; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.filter.codec.ProtocolCodecSession; import org.apache.mina.filter.codec.ProtocolEncoderOutput; import org.junit.Test; /** * Tests {@link TextLineEncoder}. * * @author Apache MINA Project */ public class TextLineEncoderTest { @Test public void testEncode() throws Exception { TextLineEncoder encoder = new TextLineEncoder(Charset.forName("UTF-8"), LineDelimiter.WINDOWS); ProtocolCodecSession session = new ProtocolCodecSession(); ProtocolEncoderOutput out = session.getEncoderOutput(); encoder.encode(session, "ABC", out); assertEquals(1, session.getEncoderOutputQueue().size()); IoBuffer buf = (IoBuffer) session.getEncoderOutputQueue().poll(); assertEquals(5, buf.remaining()); assertEquals('A', buf.get()); assertEquals('B', buf.get()); assertEquals('C', buf.get()); assertEquals('\r', buf.get()); assertEquals('\n', buf.get()); } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/codec/serialization/0000755000175000017500000000000012162575507030332 5ustar ebourgebourg././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/codec/serialization/ObjectSerializationTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/codec/serialization/ObjectSerial0000644000175000017500000000617712032276015032622 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.serialization; import static org.junit.Assert.assertEquals; import java.io.ByteArrayOutputStream; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.filter.codec.ProtocolCodecSession; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import org.apache.mina.filter.codec.ProtocolEncoder; import org.apache.mina.filter.codec.ProtocolEncoderOutput; import org.junit.Test; /** * Tests object serialization codec and streams. * * @author Apache MINA Project */ public class ObjectSerializationTest { @Test public void testEncoder() throws Exception { final String expected = "1234"; ProtocolCodecSession session = new ProtocolCodecSession(); ProtocolEncoderOutput out = session.getEncoderOutput(); ProtocolEncoder encoder = new ObjectSerializationEncoder(); encoder.encode(session, expected, out); assertEquals(1, session.getEncoderOutputQueue().size()); IoBuffer buf = (IoBuffer) session.getEncoderOutputQueue().poll(); testDecoderAndInputStream(expected, buf); } @Test public void testOutputStream() throws Exception { final String expected = "1234"; ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectSerializationOutputStream osos = new ObjectSerializationOutputStream(baos); osos.writeObject(expected); osos.flush(); testDecoderAndInputStream(expected, IoBuffer.wrap(baos.toByteArray())); } private void testDecoderAndInputStream(String expected, IoBuffer in) throws Exception { // Test InputStream ObjectSerializationInputStream osis = new ObjectSerializationInputStream(in.duplicate().asInputStream()); Object actual = osis.readObject(); assertEquals(expected, actual); // Test ProtocolDecoder ProtocolDecoder decoder = new ObjectSerializationDecoder(); ProtocolCodecSession session = new ProtocolCodecSession(); ProtocolDecoderOutput decoderOut = session.getDecoderOutput(); decoder.decode(session, in.duplicate(), decoderOut); assertEquals(1, session.getDecoderOutputQueue().size()); assertEquals(expected, session.getDecoderOutputQueue().poll()); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/codec/CumulativeProtocolDecoderTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/codec/CumulativeProtocolDecoderT0000644000175000017500000001520712032276015032643 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.net.SocketAddress; import java.util.ArrayList; import java.util.List; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.service.DefaultTransportMetadata; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionConfig; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * Tests {@link CumulativeProtocolDecoder}. * * @author Apache MINA Project */ public class CumulativeProtocolDecoderTest { private final ProtocolCodecSession session = new ProtocolCodecSession(); private IoBuffer buf; private IntegerDecoder decoder; @Before public void setUp() throws Exception { buf = IoBuffer.allocate(16); decoder = new IntegerDecoder(); session.setTransportMetadata(new DefaultTransportMetadata("mina", "dummy", false, true, SocketAddress.class, IoSessionConfig.class, IoBuffer.class)); } @After public void tearDown() throws Exception { decoder.dispose(session); } @Test public void testCumulation() throws Exception { buf.put((byte) 0); buf.flip(); decoder.decode(session, buf, session.getDecoderOutput()); assertEquals(0, session.getDecoderOutputQueue().size()); assertEquals(buf.limit(), buf.position()); buf.clear(); buf.put((byte) 0); buf.put((byte) 0); buf.put((byte) 1); buf.flip(); decoder.decode(session, buf, session.getDecoderOutput()); assertEquals(1, session.getDecoderOutputQueue().size()); assertEquals(new Integer(1), session.getDecoderOutputQueue().poll()); assertEquals(buf.limit(), buf.position()); } @Test public void testRepeatitiveDecode() throws Exception { for (int i = 0; i < 4; i++) { buf.putInt(i); } buf.flip(); decoder.decode(session, buf, session.getDecoderOutput()); assertEquals(4, session.getDecoderOutputQueue().size()); assertEquals(buf.limit(), buf.position()); List expected = new ArrayList(); for (int i = 0; i < 4; i++) { assertTrue(session.getDecoderOutputQueue().contains(i)); } } @Test public void testWrongImplementationDetection() throws Exception { try { new WrongDecoder().decode(session, buf, session.getDecoderOutput()); fail(); } catch (IllegalStateException e) { // OK } } @Test public void testBufferDerivation() throws Exception { decoder = new DuplicatingIntegerDecoder(); buf.putInt(1); // Put some extra byte to make the decoder create an internal buffer. buf.put((byte) 0); buf.flip(); decoder.decode(session, buf, session.getDecoderOutput()); assertEquals(1, session.getDecoderOutputQueue().size()); assertEquals(1, session.getDecoderOutputQueue().poll()); assertEquals(buf.limit(), buf.position()); // Keep appending to the internal buffer. // DuplicatingIntegerDecoder will keep duplicating the internal // buffer to disable auto-expansion, and CumulativeProtocolDecoder // should detect that user derived its internal buffer. // Consequently, CumulativeProtocolDecoder will perform // reallocation to avoid putting incoming data into // the internal buffer with auto-expansion disabled. for (int i = 2; i < 10; i++) { buf.clear(); buf.putInt(i); // Put some extra byte to make the decoder keep the internal buffer. buf.put((byte) 0); buf.flip(); buf.position(1); decoder.decode(session, buf, session.getDecoderOutput()); assertEquals(1, session.getDecoderOutputQueue().size()); assertEquals(i, session.getDecoderOutputQueue().poll()); assertEquals(buf.limit(), buf.position()); } } private static class IntegerDecoder extends CumulativeProtocolDecoder { /** * Default constructor */ public IntegerDecoder() { super(); } @Override protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { assertTrue(in.hasRemaining()); if (in.remaining() < 4) { return false; } out.write(new Integer(in.getInt())); return true; } public void dispose() throws Exception { // Do nothing } } private static class WrongDecoder extends CumulativeProtocolDecoder { /** * Default constructor */ public WrongDecoder() { super(); } @Override protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { return true; } public void dispose() throws Exception { // Do nothing } } private static class DuplicatingIntegerDecoder extends IntegerDecoder { /** * Default constructor */ public DuplicatingIntegerDecoder() { super(); } @Override protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { in.duplicate(); // Will disable auto-expansion. assertFalse(in.isAutoExpand()); return super.doDecode(session, in, out); } public void dispose() throws Exception { // Do nothing } } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/util/0000755000175000017500000000000012162575507025355 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/util/WrappingFilterTest.java0000644000175000017500000001254712032276015032012 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.util; import static org.junit.Assert.assertEquals; import java.util.ArrayList; import java.util.List; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterEvent; import org.apache.mina.core.session.DummySession; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoEventType; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.DefaultWriteRequest; import org.apache.mina.core.write.WriteRequest; import org.easymock.EasyMock; import org.junit.Before; import org.junit.Test; /** * Tests {@link CommonEventFilter}. * * @author Apache MINA Project */ public class WrappingFilterTest { private IoSession session; private IoFilter.NextFilter nextFilter; @Before public void setUp() throws Exception { /* * Create the mocks. */ session = new DummySession(); nextFilter = EasyMock.createMock(IoFilter.NextFilter.class); //nextFilter = (IoFilter.NextFilter) mockNextFilter.getClass(); } @Test public void testFilter() throws Exception { MyWrappingFilter wrappingFilter = new MyWrappingFilter(); /* record expectations */ Object message1 = "message one"; Object message2 = "message two"; WriteRequest writeRequest1 = new DefaultWriteRequest("test1"); WriteRequest writeRequest2 = new DefaultWriteRequest("test2"); Throwable cause = new Throwable("testing"); nextFilter.sessionCreated(session); nextFilter.sessionOpened(session); nextFilter.sessionIdle(session, IdleStatus.READER_IDLE); nextFilter.messageReceived(session, message1); nextFilter.messageSent(session, writeRequest1); nextFilter.messageSent(session, writeRequest2); nextFilter.messageReceived(session, message2); nextFilter.filterWrite(session, writeRequest1); nextFilter.filterClose(session); nextFilter.exceptionCaught(session, cause); nextFilter.sessionClosed(session); /* replay */ EasyMock.replay(nextFilter); wrappingFilter.sessionCreated(nextFilter, session); wrappingFilter.sessionOpened(nextFilter, session); wrappingFilter.sessionIdle(nextFilter, session, IdleStatus.READER_IDLE); wrappingFilter.messageReceived(nextFilter, session, message1); wrappingFilter.messageSent(nextFilter, session, writeRequest1); wrappingFilter.messageSent(nextFilter, session, writeRequest2); wrappingFilter.messageReceived(nextFilter, session, message2); wrappingFilter.filterWrite(nextFilter, session, writeRequest1); wrappingFilter.filterClose(nextFilter, session); wrappingFilter.exceptionCaught(nextFilter, session, cause); wrappingFilter.sessionClosed(nextFilter, session); /* verify */ EasyMock.verify(nextFilter); /* check event lists */ assertEquals(11, wrappingFilter.eventsBefore.size()); assertEquals(IoEventType.SESSION_CREATED, wrappingFilter.eventsBefore.get(0)); assertEquals(IoEventType.SESSION_OPENED, wrappingFilter.eventsBefore.get(1)); assertEquals(IoEventType.SESSION_IDLE, wrappingFilter.eventsBefore.get(2)); assertEquals(IoEventType.MESSAGE_RECEIVED, wrappingFilter.eventsBefore.get(3)); assertEquals(IoEventType.MESSAGE_SENT, wrappingFilter.eventsBefore.get(4)); assertEquals(IoEventType.MESSAGE_SENT, wrappingFilter.eventsBefore.get(5)); assertEquals(IoEventType.MESSAGE_RECEIVED, wrappingFilter.eventsBefore.get(6)); assertEquals(IoEventType.WRITE, wrappingFilter.eventsBefore.get(7)); assertEquals(IoEventType.CLOSE, wrappingFilter.eventsBefore.get(8)); assertEquals(IoEventType.EXCEPTION_CAUGHT, wrappingFilter.eventsBefore.get(9)); assertEquals(IoEventType.SESSION_CLOSED, wrappingFilter.eventsBefore.get(10)); assertEquals(wrappingFilter.eventsBefore, wrappingFilter.eventsAfter); } private static class MyWrappingFilter extends CommonEventFilter { List eventsBefore = new ArrayList(); List eventsAfter = new ArrayList(); /** * Default constructor */ public MyWrappingFilter() { super(); } @Override protected void filter(IoFilterEvent event) { eventsBefore.add(event.getType()); event.fire(); eventsAfter.add(event.getType()); } } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/reqres/0000755000175000017500000000000012162575507025701 5ustar ebourgebourg././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/reqres/RequestResponseFilterTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/filter/reqres/RequestResponseFilterTest0000644000175000017500000003070512032276014032771 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.reqres; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.NoSuchElementException; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.session.DummySession; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.DefaultWriteRequest; import org.apache.mina.core.write.WriteRequest; import org.easymock.AbstractMatcher; import org.easymock.MockControl; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * Tests {@link RequestResponseFilter}. * * @author Apache MINA Project */ public class RequestResponseFilterTest { private ScheduledExecutorService scheduler; private RequestResponseFilter filter; private IoSession session; private IoFilterChain chain; private NextFilter nextFilter; private MockControl nextFilterControl; private final WriteRequestMatcher matcher = new WriteRequestMatcher(); @Before public void setUp() throws Exception { scheduler = Executors.newScheduledThreadPool(1); filter = new RequestResponseFilter(new MessageInspector(), scheduler); // Set up mock objects. session = new DummySession(); chain = session.getFilterChain(); nextFilterControl = MockControl.createControl(NextFilter.class); nextFilter = (NextFilter) nextFilterControl.getMock(); // Initialize the filter. filter.onPreAdd(chain, "reqres", nextFilter); filter.onPostAdd(chain, "reqres", nextFilter); assertFalse(session.getAttributeKeys().isEmpty()); } @After public void tearDown() throws Exception { // Destroy the filter. filter.onPreRemove(chain, "reqres", nextFilter); filter.onPostRemove(chain, "reqres", nextFilter); filter.destroy(); filter = null; scheduler.shutdown(); } @Test public void testWholeResponse() throws Exception { Request req = new Request(1, new Object(), Long.MAX_VALUE); Response res = new Response(req, new Message(1, ResponseType.WHOLE), ResponseType.WHOLE); WriteRequest rwr = new DefaultWriteRequest(req); // Record nextFilter.filterWrite(session, new DefaultWriteRequest(req.getMessage())); nextFilterControl.setMatcher(matcher); nextFilter.messageSent(session, rwr); nextFilter.messageReceived(session, res); // Replay nextFilterControl.replay(); filter.filterWrite(nextFilter, session, rwr); filter.messageSent(nextFilter, session, matcher.getLastWriteRequest()); filter.messageReceived(nextFilter, session, res.getMessage()); filter.messageReceived(nextFilter, session, res.getMessage()); // Ignored // Verify nextFilterControl.verify(); assertEquals(res, req.awaitResponse()); assertNoSuchElementException(req); } private void assertNoSuchElementException(Request req) throws InterruptedException { // Make sure if an exception is thrown if a user waits one more time. try { req.awaitResponse(); fail(); } catch (NoSuchElementException e) { // Signifies a successful test execution assertTrue(true); } } @Test public void testPartialResponse() throws Exception { Request req = new Request(1, new Object(), Long.MAX_VALUE); Response res1 = new Response(req, new Message(1, ResponseType.PARTIAL), ResponseType.PARTIAL); Response res2 = new Response(req, new Message(1, ResponseType.PARTIAL_LAST), ResponseType.PARTIAL_LAST); WriteRequest rwr = new DefaultWriteRequest(req); // Record nextFilter.filterWrite(session, new DefaultWriteRequest(req.getMessage())); nextFilterControl.setMatcher(matcher); nextFilter.messageSent(session, rwr); nextFilter.messageReceived(session, res1); nextFilter.messageReceived(session, res2); // Replay nextFilterControl.replay(); filter.filterWrite(nextFilter, session, rwr); filter.messageSent(nextFilter, session, matcher.getLastWriteRequest()); filter.messageReceived(nextFilter, session, res1.getMessage()); filter.messageReceived(nextFilter, session, res2.getMessage()); filter.messageReceived(nextFilter, session, res1.getMessage()); // Ignored filter.messageReceived(nextFilter, session, res2.getMessage()); // Ignored // Verify nextFilterControl.verify(); assertEquals(res1, req.awaitResponse()); assertEquals(res2, req.awaitResponse()); assertNoSuchElementException(req); } @Test public void testWholeResponseTimeout() throws Exception { Request req = new Request(1, new Object(), 10); // 10ms timeout Response res = new Response(req, new Message(1, ResponseType.WHOLE), ResponseType.WHOLE); WriteRequest rwr = new DefaultWriteRequest(req); // Record nextFilter.filterWrite(session, new DefaultWriteRequest(req.getMessage())); nextFilterControl.setMatcher(matcher); nextFilter.messageSent(session, rwr); nextFilter.exceptionCaught(session, new RequestTimeoutException(req)); nextFilterControl.setMatcher(new ExceptionMatcher()); // Replay nextFilterControl.replay(); filter.filterWrite(nextFilter, session, rwr); filter.messageSent(nextFilter, session, matcher.getLastWriteRequest()); Thread.sleep(300); // Wait until the request times out. filter.messageReceived(nextFilter, session, res.getMessage()); // Ignored // Verify nextFilterControl.verify(); assertRequestTimeoutException(req); assertNoSuchElementException(req); } private void assertRequestTimeoutException(Request req) throws InterruptedException { try { req.awaitResponse(); fail(); } catch (RequestTimeoutException e) { // Signifies a successful test execution assertTrue(true); } } @Test public void testPartialResponseTimeout() throws Exception { Request req = new Request(1, new Object(), 10); // 10ms timeout Response res1 = new Response(req, new Message(1, ResponseType.PARTIAL), ResponseType.PARTIAL); Response res2 = new Response(req, new Message(1, ResponseType.PARTIAL_LAST), ResponseType.PARTIAL_LAST); WriteRequest rwr = new DefaultWriteRequest(req); // Record nextFilter.filterWrite(session, new DefaultWriteRequest(req.getMessage())); nextFilterControl.setMatcher(matcher); nextFilter.messageSent(session, rwr); nextFilter.messageReceived(session, res1); nextFilter.exceptionCaught(session, new RequestTimeoutException(req)); nextFilterControl.setMatcher(new ExceptionMatcher()); // Replay nextFilterControl.replay(); filter.filterWrite(nextFilter, session, rwr); filter.messageSent(nextFilter, session, matcher.getLastWriteRequest()); filter.messageReceived(nextFilter, session, res1.getMessage()); Thread.sleep(300); // Wait until the request times out. filter.messageReceived(nextFilter, session, res2.getMessage()); // Ignored filter.messageReceived(nextFilter, session, res1.getMessage()); // Ignored // Verify nextFilterControl.verify(); assertEquals(res1, req.awaitResponse()); assertRequestTimeoutException(req); assertNoSuchElementException(req); } @Test public void testTimeoutByDisconnection() throws Exception { // We run a test case that doesn't raise a timeout to make sure // the timeout is not raised again by disconnection. testWholeResponse(); nextFilterControl.reset(); Request req1 = new Request(1, new Object(), Long.MAX_VALUE); Request req2 = new Request(2, new Object(), Long.MAX_VALUE); WriteRequest rwr1 = new DefaultWriteRequest(req1); WriteRequest rwr2 = new DefaultWriteRequest(req2); // Record nextFilter.filterWrite(session, new DefaultWriteRequest(req1.getMessage())); nextFilterControl.setMatcher(matcher); nextFilter.messageSent(session, rwr1); nextFilter.filterWrite(session, new DefaultWriteRequest(req2.getMessage())); nextFilter.messageSent(session, rwr2); nextFilter.exceptionCaught(session, new RequestTimeoutException(req1)); nextFilterControl.setMatcher(new ExceptionMatcher()); nextFilter.exceptionCaught(session, new RequestTimeoutException(req2)); nextFilter.sessionClosed(session); // Replay nextFilterControl.replay(); filter.filterWrite(nextFilter, session, rwr1); filter.messageSent(nextFilter, session, matcher.getLastWriteRequest()); filter.filterWrite(nextFilter, session, rwr2); filter.messageSent(nextFilter, session, matcher.getLastWriteRequest()); filter.sessionClosed(nextFilter, session); // Verify nextFilterControl.verify(); assertRequestTimeoutException(req1); assertRequestTimeoutException(req2); } static class Message { private final int id; private final ResponseType type; Message(int id, ResponseType type) { this.id = id; this.type = type; } public int getId() { return id; } public ResponseType getType() { return type; } } private static class MessageInspector implements ResponseInspector { /** * Default constructor */ public MessageInspector() { super(); } public Object getRequestId(Object message) { if (!(message instanceof Message)) { return null; } return ((Message) message).getId(); } public ResponseType getResponseType(Object message) { if (!(message instanceof Message)) { return null; } return ((Message) message).getType(); } } private static class WriteRequestMatcher extends AbstractMatcher { private WriteRequest lastWriteRequest; /** * Default constructor */ public WriteRequestMatcher() { super(); } public WriteRequest getLastWriteRequest() { return lastWriteRequest; } @Override protected boolean argumentMatches(Object expected, Object actual) { if (actual instanceof WriteRequest && expected instanceof WriteRequest) { boolean answer = ((WriteRequest) expected).getMessage().equals(((WriteRequest) actual).getMessage()); lastWriteRequest = (WriteRequest) actual; return answer; } return super.argumentMatches(expected, actual); } } static class ExceptionMatcher extends AbstractMatcher { @Override protected boolean argumentMatches(Object expected, Object actual) { if (actual instanceof RequestTimeoutException && expected instanceof RequestTimeoutException) { return ((RequestTimeoutException) expected).getRequest().equals( ((RequestTimeoutException) actual).getRequest()); } return super.argumentMatches(expected, actual); } } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/0000755000175000017500000000000012162575507025147 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/AbstractFileRegionTest.java0000644000175000017500000001310712032276016032350 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.util.concurrent.CountDownLatch; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import org.apache.mina.util.AvailablePortFinder; import org.junit.Test; /** * TODO Add documentation * * @author Apache MINA Project */ public abstract class AbstractFileRegionTest { private static final int FILE_SIZE = 1 * 1024 * 1024; // 1MB file protected abstract IoAcceptor createAcceptor(); protected abstract IoConnector createConnector(); @Test public void testSendLargeFile() throws Throwable { File file = createLargeFile(); assertEquals("Test file not as big as specified", FILE_SIZE, file.length()); final CountDownLatch latch = new CountDownLatch(1); final boolean[] success = { false }; final Throwable[] exception = { null }; int port = AvailablePortFinder.getNextAvailable(1025); IoAcceptor acceptor = createAcceptor(); IoConnector connector = createConnector(); try { acceptor.setHandler(new IoHandlerAdapter() { private int index = 0; @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { exception[0] = cause; session.close(true); } @Override public void messageReceived(IoSession session, Object message) throws Exception { IoBuffer buffer = (IoBuffer) message; while (buffer.hasRemaining()) { int x = buffer.getInt(); if (x != index) { throw new Exception(String.format("Integer at %d was %d but should have been %d", index, x, index)); } index++; } if (index > FILE_SIZE / 4) { throw new Exception("Read too much data"); } if (index == FILE_SIZE / 4) { success[0] = true; session.close(true); } } }); ((NioSocketAcceptor) acceptor).setReuseAddress(true); acceptor.bind(new InetSocketAddress(port)); connector.setHandler(new IoHandlerAdapter() { @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { exception[0] = cause; session.close(true); } @Override public void sessionClosed(IoSession session) throws Exception { latch.countDown(); } }); ConnectFuture future = connector.connect(new InetSocketAddress("localhost", port)); future.awaitUninterruptibly(); IoSession session = future.getSession(); session.write(file); latch.await(); if (exception[0] != null) { throw exception[0]; } assertTrue("Did not complete file transfer successfully", success[0]); assertEquals("Written messages should be 1 (we wrote one file)", 1, session.getWrittenMessages()); assertEquals("Written bytes should match file size", FILE_SIZE, session.getWrittenBytes()); } finally { try { connector.dispose(); } finally { acceptor.dispose(); } } } private File createLargeFile() throws IOException { File largeFile = File.createTempFile("mina-test", "largefile"); largeFile.deleteOnExit(); FileChannel channel = new FileOutputStream(largeFile).getChannel(); ByteBuffer buffer = createBuffer(); channel.write(buffer); channel.close(); return largeFile; } private ByteBuffer createBuffer() { ByteBuffer buffer = ByteBuffer.allocate(FILE_SIZE); for (int i = 0; i < FILE_SIZE / 4; i++) { buffer.putInt(i); } buffer.flip(); return buffer; } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/AbstractConnectorTest.java0000644000175000017500000001572412032276016032266 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.net.InetSocketAddress; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionInitializer; import org.apache.mina.util.AvailablePortFinder; import org.junit.Test; /** * Tests a generic {@link IoConnector}. * * @author Apache MINA Project */ public abstract class AbstractConnectorTest { protected abstract IoAcceptor createAcceptor(); protected abstract IoConnector createConnector(); @Test public void testConnectFutureSuccessTiming() throws Exception { int port = AvailablePortFinder.getNextAvailable(1025); IoAcceptor acceptor = createAcceptor(); acceptor.setHandler(new IoHandlerAdapter()); acceptor.bind(new InetSocketAddress(port)); try { final StringBuffer buf = new StringBuffer(); IoConnector connector = createConnector(); connector.setHandler(new IoHandlerAdapter() { @Override public void sessionCreated(IoSession session) { buf.append("1"); } @Override public void sessionOpened(IoSession session) { buf.append("2"); } @Override public void exceptionCaught(IoSession session, Throwable cause) { buf.append("X"); } }); ConnectFuture future = connector.connect(new InetSocketAddress("localhost", port)); future.awaitUninterruptibly(); buf.append("3"); future.getSession().close(true); // sessionCreated() will fire before the connect future completes // but sessionOpened() may not assertTrue(Pattern.matches("12?32?", buf.toString())); } finally { acceptor.dispose(); } } @Test public void testConnectFutureFailureTiming() throws Exception { int port = AvailablePortFinder.getNextAvailable(1025); final StringBuffer buf = new StringBuffer(); IoConnector connector = createConnector(); connector.setHandler(new IoHandlerAdapter() { @Override public void sessionCreated(IoSession session) { buf.append("X"); } @Override public void sessionOpened(IoSession session) { buf.append("Y"); } @Override public void exceptionCaught(IoSession session, Throwable cause) { buf.append("Z"); } }); try { ConnectFuture future = connector.connect(new InetSocketAddress("localhost", port)); future.awaitUninterruptibly(); buf.append("1"); try { future.getSession().close(true); fail(); } catch (RuntimeIoException e) { // Signifies a successful test execution assertTrue(true); } assertEquals("1", buf.toString()); } finally { connector.dispose(); } } /** * Test to make sure the SessionCallback gets invoked before IoHandler.sessionCreated. */ @Test public void testSessionCallbackInvocation() throws Exception { final int callbackInvoked = 0; final int sessionCreatedInvoked = 1; final int sessionCreatedInvokedBeforeCallback = 2; final boolean[] assertions = { false, false, false }; final CountDownLatch latch = new CountDownLatch(2); final ConnectFuture[] callbackFuture = new ConnectFuture[1]; int port = AvailablePortFinder.getNextAvailable(1025); IoAcceptor acceptor = createAcceptor(); IoConnector connector = createConnector(); try { acceptor.setHandler(new IoHandlerAdapter()); InetSocketAddress address = new InetSocketAddress(port); acceptor.bind(address); connector.setHandler(new IoHandlerAdapter() { @Override public void sessionCreated(IoSession session) throws Exception { assertions[sessionCreatedInvoked] = true; assertions[sessionCreatedInvokedBeforeCallback] = !assertions[callbackInvoked]; latch.countDown(); } }); ConnectFuture future = connector.connect(new InetSocketAddress("127.0.0.1", port), new IoSessionInitializer() { public void initializeSession(IoSession session, ConnectFuture future) { assertions[callbackInvoked] = true; callbackFuture[0] = future; latch.countDown(); } }); assertTrue("Timed out waiting for callback and IoHandler.sessionCreated to be invoked", latch.await(5, TimeUnit.SECONDS)); assertTrue("Callback was not invoked", assertions[callbackInvoked]); assertTrue("IoHandler.sessionCreated was not invoked", assertions[sessionCreatedInvoked]); assertFalse("IoHandler.sessionCreated was invoked before session callback", assertions[sessionCreatedInvokedBeforeCallback]); assertSame("Callback future should have been same future as returned by connect", future, callbackFuture[0]); } finally { try { connector.dispose(); } finally { acceptor.dispose(); } } } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/AbstractTrafficControlTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/AbstractTrafficControlTest.ja0000644000175000017500000002035012032276016032713 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport; import java.net.SocketAddress; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.core.session.IoSession; import org.junit.After; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** * Abstract base class for testing suspending and resuming reads and * writes. * * @author Apache MINA Project */ public abstract class AbstractTrafficControlTest { protected int port; protected IoAcceptor acceptor; protected TransportMetadata transportType; public AbstractTrafficControlTest(IoAcceptor acceptor) { this.acceptor = acceptor; } @Before public void setUp() throws Exception { acceptor.setHandler(new ServerIoHandler()); acceptor.bind(createServerSocketAddress(0)); port = getPort(acceptor.getLocalAddress()); } @After public void tearDown() throws Exception { acceptor.unbind(); acceptor.dispose(); } protected abstract ConnectFuture connect(int port, IoHandler handler) throws Exception; protected abstract SocketAddress createServerSocketAddress(int port); protected abstract int getPort(SocketAddress address); @Test public void testSuspendResumeReadWrite() throws Exception { ConnectFuture future = connect(port, new ClientIoHandler()); future.awaitUninterruptibly(); IoSession session = future.getSession(); // We wait for the sessionCreated() event is fired because we // cannot guarantee that it is invoked already. while (session.getAttribute("lock") == null) { Thread.yield(); } Object lock = session.getAttribute("lock"); synchronized (lock) { write(session, "1"); assertEquals('1', read(session)); assertEquals("1", getReceived(session)); assertEquals("1", getSent(session)); session.suspendRead(); Thread.sleep(100); write(session, "2"); assertFalse(canRead(session)); assertEquals("1", getReceived(session)); assertEquals("12", getSent(session)); session.suspendWrite(); Thread.sleep(100); write(session, "3"); assertFalse(canRead(session)); assertEquals("1", getReceived(session)); assertEquals("12", getSent(session)); session.resumeRead(); Thread.sleep(100); write(session, "4"); assertEquals('2', read(session)); assertEquals("12", getReceived(session)); assertEquals("12", getSent(session)); session.resumeWrite(); Thread.sleep(100); assertEquals('3', read(session)); assertEquals('4', read(session)); write(session, "5"); assertEquals('5', read(session)); assertEquals("12345", getReceived(session)); assertEquals("12345", getSent(session)); session.suspendWrite(); Thread.sleep(100); write(session, "6"); assertFalse(canRead(session)); assertEquals("12345", getReceived(session)); assertEquals("12345", getSent(session)); session.suspendRead(); session.resumeWrite(); Thread.sleep(100); write(session, "7"); assertFalse(canRead(session)); assertEquals("12345", getReceived(session)); assertEquals("1234567", getSent(session)); session.resumeRead(); Thread.sleep(100); assertEquals('6', read(session)); assertEquals('7', read(session)); assertEquals("1234567", getReceived(session)); assertEquals("1234567", getSent(session)); } session.close(true).awaitUninterruptibly(); } private void write(IoSession session, String s) throws Exception { session.write(IoBuffer.wrap(s.getBytes("ASCII"))); } private int read(IoSession session) throws Exception { int pos = ((Integer) session.getAttribute("pos")).intValue(); for (int i = 0; i < 10 && pos == getReceived(session).length(); i++) { Object lock = session.getAttribute("lock"); lock.wait(200); } session.setAttribute("pos", new Integer(pos + 1)); String received = getReceived(session); assertTrue(received.length() > pos); return getReceived(session).charAt(pos); } private boolean canRead(IoSession session) throws Exception { int pos = ((Integer) session.getAttribute("pos")).intValue(); Object lock = session.getAttribute("lock"); lock.wait(250); String received = getReceived(session); return pos < received.length(); } private String getReceived(IoSession session) throws Exception { return session.getAttribute("received").toString(); } private String getSent(IoSession session) throws Exception { return session.getAttribute("sent").toString(); } private static class ClientIoHandler extends IoHandlerAdapter { /** * Default constructor */ public ClientIoHandler() { super(); } @Override public void sessionCreated(IoSession session) throws Exception { super.sessionCreated(session); session.setAttribute("pos", new Integer(0)); session.setAttribute("received", new StringBuffer()); session.setAttribute("sent", new StringBuffer()); session.setAttribute("lock", new Object()); } @Override public void messageReceived(IoSession session, Object message) throws Exception { IoBuffer buffer = (IoBuffer) message; byte[] data = new byte[buffer.remaining()]; buffer.get(data); Object lock = session.getAttribute("lock"); synchronized (lock) { StringBuffer sb = (StringBuffer) session.getAttribute("received"); sb.append(new String(data, "ASCII")); lock.notifyAll(); } } @Override public void messageSent(IoSession session, Object message) throws Exception { IoBuffer buffer = (IoBuffer) message; buffer.rewind(); byte[] data = new byte[buffer.remaining()]; buffer.get(data); StringBuffer sb = (StringBuffer) session.getAttribute("sent"); sb.append(new String(data, "ASCII")); } } private static class ServerIoHandler extends IoHandlerAdapter { /** * Default constructor */ public ServerIoHandler() { super(); } @Override public void messageReceived(IoSession session, Object message) throws Exception { // Just echo the received bytes. IoBuffer rb = (IoBuffer) message; IoBuffer wb = IoBuffer.allocate(rb.remaining()); wb.put(rb); wb.flip(); session.write(wb); } } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/0000755000175000017500000000000012032276016026424 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/0000755000175000017500000000000012162575507027224 5ustar ebourgebourg././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/SocketBindTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/SocketBindTest.jav0000644000175000017500000000321512032276016032601 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import java.net.InetSocketAddress; import java.net.SocketAddress; import org.apache.mina.core.service.IoConnector; import org.apache.mina.transport.AbstractBindTest; /** * Tests {@link NioSocketAcceptor} resource leakage. * * @author Apache MINA Project */ public class SocketBindTest extends AbstractBindTest { public SocketBindTest() { super(new NioSocketAcceptor()); } @Override protected SocketAddress createSocketAddress(int port) { return new InetSocketAddress("localhost", port); } @Override protected int getPort(SocketAddress address) { return ((InetSocketAddress) address).getPort(); } @Override protected IoConnector newConnector() { return new NioSocketConnector(); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/DatagramConfigTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/DatagramConfigTest0000644000175000017500000001004612032276016032643 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.net.InetSocketAddress; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.util.AvailablePortFinder; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * Tests if {@link NioDatagramAcceptor} session is configured properly. * * @author Apache MINA Project */ public class DatagramConfigTest { private IoAcceptor acceptor; private IoConnector connector; String result; public DatagramConfigTest() { // Do nothing } @Before public void setUp() throws Exception { result = ""; acceptor = new NioDatagramAcceptor(); connector = new NioDatagramConnector(); } @After public void tearDown() throws Exception { acceptor.dispose(); connector.dispose(); } @Test public void testAcceptorFilterChain() throws Exception { int port = AvailablePortFinder.getNextAvailable(1024 + 1000); IoFilter mockFilter = new MockFilter(); IoHandler mockHandler = new MockHandler(); acceptor.getFilterChain().addLast("mock", mockFilter); acceptor.setHandler(mockHandler); acceptor.bind(new InetSocketAddress(port)); try { connector.setHandler(new IoHandlerAdapter()); ConnectFuture future = connector.connect(new InetSocketAddress("127.0.0.1", port)); future.awaitUninterruptibly(); WriteFuture writeFuture = future.getSession().write(IoBuffer.allocate(16).putInt(0).flip()); writeFuture.awaitUninterruptibly(); assertTrue(writeFuture.isWritten()); future.getSession().close(true); for (int i = 0; i < 30; i++) { if (result.length() == 2) { break; } Thread.sleep(100); } assertEquals("FH", result); } finally { acceptor.unbind(); } } private class MockFilter extends IoFilterAdapter { /** * Default constructor */ public MockFilter() { super(); } @Override public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception { result += "F"; nextFilter.messageReceived(session, message); } } private class MockHandler extends IoHandlerAdapter { /** * Default constructor */ public MockHandler() { super(); } @Override public void messageReceived(IoSession session, Object message) throws Exception { result += "H"; } } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/DatagramPortUnreachableTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/DatagramPortUnreac0000644000175000017500000000615012032276016032661 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import static org.junit.Assert.assertEquals; import java.net.InetSocketAddress; import java.net.PortUnreachableException; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.transport.socket.DatagramSessionConfig; import org.apache.mina.util.AvailablePortFinder; import org.junit.Test; /** * Tests {@link DatagramSessionConfig#setCloseOnPortUnreachable(boolean)}. * * @author Apache MINA Project */ public class DatagramPortUnreachableTest { Object mutex = new Object(); private void runTest(boolean closeOnPortUnreachable) throws Exception { IoConnector connector = new NioDatagramConnector(); connector.setHandler(new IoHandlerAdapter() { @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { if (cause instanceof PortUnreachableException) { synchronized (mutex) { mutex.notify(); } } } }); ConnectFuture future = connector.connect(new InetSocketAddress("localhost", AvailablePortFinder .getNextAvailable(20000))); future.awaitUninterruptibly(); IoSession session = future.getSession(); DatagramSessionConfig cfg = ((DatagramSessionConfig) session.getConfig()); cfg.setUseReadOperation(true); cfg.setCloseOnPortUnreachable(closeOnPortUnreachable); synchronized (mutex) { session.write(IoBuffer.allocate(1)).awaitUninterruptibly().isWritten(); session.read(); mutex.wait(); } Thread.sleep(500); assertEquals(closeOnPortUnreachable, session.isClosing()); connector.dispose(); } @Test public void testPortUnreachableClosesSession() throws Exception { // session should be closing runTest(true); } @Test public void testNormal() throws Exception { // test that session is not closed on port unreachable exception runTest(false); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/NioFileRegionTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/NioFileRegionTest.0000644000175000017500000000273412032276016032551 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoConnector; import org.apache.mina.transport.AbstractFileRegionTest; /** * TODO Add documentation * * @author Apache MINA Project */ public class NioFileRegionTest extends AbstractFileRegionTest { @Override protected IoAcceptor createAcceptor() { NioSocketAcceptor acceptor = new NioSocketAcceptor(); acceptor.setReuseAddress(true); return acceptor; } @Override protected IoConnector createConnector() { return new NioSocketConnector(); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/DatagramRecyclerTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/DatagramRecyclerTe0000644000175000017500000001742112032276016032643 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; import java.net.InetSocketAddress; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.ExpiringSessionRecycler; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.util.AvailablePortFinder; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * Tests if datagram sessions are recycled properly. * * @author Apache MINA Project */ public class DatagramRecyclerTest { private NioDatagramAcceptor acceptor; private NioDatagramConnector connector; public DatagramRecyclerTest() { // Do nothing } @Before public void setUp() throws Exception { acceptor = new NioDatagramAcceptor(); connector = new NioDatagramConnector(); } @After public void tearDown() throws Exception { acceptor.dispose(); connector.dispose(); } @Test public void testDatagramRecycler() throws Exception { int port = AvailablePortFinder.getNextAvailable(1024); ExpiringSessionRecycler recycler = new ExpiringSessionRecycler(1, 1); MockHandler acceptorHandler = new MockHandler(); MockHandler connectorHandler = new MockHandler(); acceptor.setHandler(acceptorHandler); acceptor.setSessionRecycler(recycler); acceptor.bind(new InetSocketAddress(port)); try { connector.setHandler(connectorHandler); ConnectFuture future = connector.connect(new InetSocketAddress("localhost", port)); future.awaitUninterruptibly(); // Write whatever to trigger the acceptor. future.getSession().write(IoBuffer.allocate(1)).awaitUninterruptibly(); // Close the client-side connection. // This doesn't mean that the acceptor-side connection is also closed. // The life cycle of the acceptor-side connection is managed by the recycler. future.getSession().close(true); future.getSession().getCloseFuture().awaitUninterruptibly(); assertTrue(future.getSession().getCloseFuture().isClosed()); // Wait until the acceptor-side connection is closed. while (acceptorHandler.session == null) { Thread.yield(); } acceptorHandler.session.getCloseFuture().awaitUninterruptibly(3000); // Is it closed? assertTrue(acceptorHandler.session.getCloseFuture().isClosed()); Thread.sleep(1000); assertEquals("CROPSECL", connectorHandler.result.toString()); assertEquals("CROPRECL", acceptorHandler.result.toString()); } finally { acceptor.unbind(); } } @Test public void testCloseRequest() throws Exception { int port = AvailablePortFinder.getNextAvailable(1024); ExpiringSessionRecycler recycler = new ExpiringSessionRecycler(10, 1); MockHandler acceptorHandler = new MockHandler(); MockHandler connectorHandler = new MockHandler(); acceptor.getSessionConfig().setIdleTime(IdleStatus.READER_IDLE, 1); acceptor.setHandler(acceptorHandler); acceptor.setSessionRecycler(recycler); acceptor.bind(new InetSocketAddress(port)); try { connector.setHandler(connectorHandler); ConnectFuture future = connector.connect(new InetSocketAddress("localhost", port)); future.awaitUninterruptibly(); // Write whatever to trigger the acceptor. future.getSession().write(IoBuffer.allocate(1)).awaitUninterruptibly(); // Make sure the connection is closed before recycler closes it. while (acceptorHandler.session == null) { Thread.yield(); } acceptorHandler.session.close(true); assertTrue(acceptorHandler.session.getCloseFuture().awaitUninterruptibly(3000)); IoSession oldSession = acceptorHandler.session; // Wait until all events are processed and clear the state. long startTime = System.currentTimeMillis(); while (acceptorHandler.result.length() < 8) { Thread.yield(); if (System.currentTimeMillis() - startTime > 5000) { throw new Exception(); } } acceptorHandler.result.setLength(0); acceptorHandler.session = null; // Write whatever to trigger the acceptor again. WriteFuture wf = future.getSession().write(IoBuffer.allocate(1)).awaitUninterruptibly(); assertTrue(wf.isWritten()); // Make sure the connection is closed before recycler closes it. while (acceptorHandler.session == null) { Thread.yield(); } acceptorHandler.session.close(true); assertTrue(acceptorHandler.session.getCloseFuture().awaitUninterruptibly(3000)); future.getSession().close(true).awaitUninterruptibly(); assertNotSame(oldSession, acceptorHandler.session); } finally { acceptor.unbind(); } } private class MockHandler extends IoHandlerAdapter { public volatile IoSession session; public final StringBuffer result = new StringBuffer(); /** * Default constructor */ public MockHandler() { super(); } @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { this.session = session; result.append("CA"); } @Override public void messageReceived(IoSession session, Object message) throws Exception { this.session = session; result.append("RE"); } @Override public void messageSent(IoSession session, Object message) throws Exception { this.session = session; result.append("SE"); } @Override public void sessionClosed(IoSession session) throws Exception { this.session = session; result.append("CL"); } @Override public void sessionCreated(IoSession session) throws Exception { this.session = session; result.append("CR"); } @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { this.session = session; result.append("ID"); } @Override public void sessionOpened(IoSession session) throws Exception { this.session = session; result.append("OP"); } } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/DatagramTrafficControlTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/DatagramTrafficCon0000644000175000017500000000374512032276016032624 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import java.net.InetSocketAddress; import java.net.SocketAddress; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandler; import org.apache.mina.transport.AbstractTrafficControlTest; /** * Tests suspending and resuming reads and writes for the datagram * transport type. * * @author Apache MINA Project */ public class DatagramTrafficControlTest extends AbstractTrafficControlTest { public DatagramTrafficControlTest() { super(new NioDatagramAcceptor()); } @Override protected ConnectFuture connect(int port, IoHandler handler) throws Exception { IoConnector connector = new NioDatagramConnector(); connector.setHandler(handler); return connector.connect(new InetSocketAddress("localhost", port)); } @Override protected SocketAddress createServerSocketAddress(int port) { return new InetSocketAddress(port); } @Override protected int getPort(SocketAddress address) { return ((InetSocketAddress) address).getPort(); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/PollingIoProcessorTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/PollingIoProcessor0000644000175000017500000001404112032276016032730 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import static org.junit.Assert.assertNotNull; import java.io.IOException; import java.net.InetSocketAddress; import java.net.NoRouteToHostException; import java.util.Iterator; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.file.FileRegion; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.polling.AbstractPollingIoProcessor; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.SessionState; import org.apache.mina.util.AvailablePortFinder; import org.junit.Ignore; import org.junit.Test; /** * Tests non regression on issue DIRMINA-632. * * @author Apache MINA Project */ public class PollingIoProcessorTest { @Ignore @Test public void testExceptionOnWrite() throws Exception { final Executor ex = Executors.newFixedThreadPool(1); IoConnector connector = new NioSocketConnector(new AbstractPollingIoProcessor(ex) { private NioProcessor proc = new NioProcessor(ex); @Override protected Iterator allSessions() { return proc.allSessions(); } @Override protected void destroy(NioSession session) throws Exception { proc.destroy(session); } @Override protected void doDispose() throws Exception { proc.doDispose(); } @Override protected void init(NioSession session) throws Exception { proc.init(session); } @Override protected boolean isInterestedInRead(NioSession session) { return proc.isInterestedInRead(session); } @Override protected boolean isInterestedInWrite(NioSession session) { return proc.isInterestedInWrite(session); } @Override protected boolean isReadable(NioSession session) { return proc.isReadable(session); } @Override protected boolean isSelectorEmpty() { return proc.isSelectorEmpty(); } @Override protected boolean isWritable(NioSession session) { return proc.isWritable(session); } @Override protected int read(NioSession session, IoBuffer buf) throws Exception { return proc.read(session, buf); } @Override protected int select(long timeout) throws Exception { return proc.select(timeout); } @Override protected int select() throws Exception { return proc.select(); } @Override protected Iterator selectedSessions() { return proc.selectedSessions(); } @Override protected void setInterestedInRead(NioSession session, boolean interested) throws Exception { proc.setInterestedInRead(session, interested); } @Override protected void setInterestedInWrite(NioSession session, boolean interested) throws Exception { proc.setInterestedInWrite(session, interested); } @Override protected SessionState getState(NioSession session) { return proc.getState(session); } @Override protected int transferFile(NioSession session, FileRegion region, int length) throws Exception { return proc.transferFile(session, region, length); } @Override protected void wakeup() { proc.wakeup(); } @Override protected int write(NioSession session, IoBuffer buf, int length) throws Exception { throw new NoRouteToHostException("No Route To Host Test"); } @Override protected boolean isBrokenConnection() throws IOException { return proc.isBrokenConnection(); } @Override protected void registerNewSelector() throws IOException { proc.registerNewSelector(); } }); connector.setHandler(new IoHandlerAdapter()); IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.setHandler(new IoHandlerAdapter()); InetSocketAddress addr = new InetSocketAddress("localhost", AvailablePortFinder.getNextAvailable(20000)); acceptor.bind(addr); ConnectFuture future = connector.connect(addr); future.awaitUninterruptibly(); IoSession session = future.getSession(); WriteFuture wf = session.write(IoBuffer.allocate(1)).awaitUninterruptibly(); assertNotNull(wf.getException()); connector.dispose(); acceptor.dispose(); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/DatagramConnectorTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/DatagramConnectorT0000644000175000017500000000314012032276016032651 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoConnector; import org.apache.mina.transport.AbstractConnectorTest; /** * Tests {@link NioDatagramConnector}. * * @author Apache MINA Project */ public class DatagramConnectorTest extends AbstractConnectorTest { @Override protected IoAcceptor createAcceptor() { return new NioDatagramAcceptor(); } @Override protected IoConnector createConnector() { return new NioDatagramConnector(); } @Override public void testConnectFutureFailureTiming() throws Exception { // Skip the test; Datagram connection can be made even if there's no // server at the endpoint. } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/DatagramBindTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/DatagramBindTest.j0000644000175000017500000000322712032276016032545 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import java.net.InetSocketAddress; import java.net.SocketAddress; import org.apache.mina.core.service.IoConnector; import org.apache.mina.transport.AbstractBindTest; /** * Tests {@link NioDatagramAcceptor} resource leakage. * * @author Apache MINA Project */ public class DatagramBindTest extends AbstractBindTest { public DatagramBindTest() { super(new NioDatagramAcceptor()); } @Override protected SocketAddress createSocketAddress(int port) { return new InetSocketAddress("localhost", port); } @Override protected int getPort(SocketAddress address) { return ((InetSocketAddress) address).getPort(); } @Override protected IoConnector newConnector() { return new NioDatagramConnector(); } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/SocketTrafficControlTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/SocketTrafficContr0000644000175000017500000000373312032276016032677 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import java.net.InetSocketAddress; import java.net.SocketAddress; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandler; import org.apache.mina.transport.AbstractTrafficControlTest; /** * Tests suspending and resuming reads and writes for the socket transport * type. * * @author Apache MINA Project */ public class SocketTrafficControlTest extends AbstractTrafficControlTest { public SocketTrafficControlTest() { super(new NioSocketAcceptor()); } @Override protected ConnectFuture connect(int port, IoHandler handler) throws Exception { IoConnector connector = new NioSocketConnector(); connector.setHandler(handler); return connector.connect(new InetSocketAddress("localhost", port)); } @Override protected SocketAddress createServerSocketAddress(int port) { return new InetSocketAddress(port); } @Override protected int getPort(SocketAddress address) { return ((InetSocketAddress) address).getPort(); } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/DatagramSessionIdleTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/DatagramSessionIdl0000644000175000017500000001100412032276016032645 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.net.InetSocketAddress; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.util.AvailablePortFinder; import org.junit.Test; /** * Test for DIRMINA-732 * * @author Apache MINA Project */ public class DatagramSessionIdleTest { private boolean readerIdleReceived; private boolean writerIdleReceived; private boolean bothIdleReceived; private Object mutex = new Object(); private class TestHandler extends IoHandlerAdapter { @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { if (status == IdleStatus.BOTH_IDLE) { bothIdleReceived = true; } else if (status == IdleStatus.READER_IDLE) { readerIdleReceived = true; } else if (status == IdleStatus.WRITER_IDLE) { writerIdleReceived = true; } synchronized (mutex) { mutex.notifyAll(); } super.sessionIdle(session, status); } } @Test public void testSessionIdle() throws Exception { final int READER_IDLE_TIME = 3;//seconds final int WRITER_IDLE_TIME = READER_IDLE_TIME + 2;//seconds final int BOTH_IDLE_TIME = WRITER_IDLE_TIME + 2;//seconds NioDatagramAcceptor acceptor = new NioDatagramAcceptor(); acceptor.getSessionConfig().setBothIdleTime(BOTH_IDLE_TIME); acceptor.getSessionConfig().setReaderIdleTime(READER_IDLE_TIME); acceptor.getSessionConfig().setWriterIdleTime(WRITER_IDLE_TIME); InetSocketAddress bindAddress = new InetSocketAddress(AvailablePortFinder.getNextAvailable()); acceptor.setHandler(new TestHandler()); acceptor.bind(bindAddress); IoSession session = acceptor.newSession( new InetSocketAddress("127.0.0.1", AvailablePortFinder.getNextAvailable()), bindAddress); //check properties to be copied from acceptor to session assertEquals(BOTH_IDLE_TIME, session.getConfig().getBothIdleTime()); assertEquals(READER_IDLE_TIME, session.getConfig().getReaderIdleTime()); assertEquals(WRITER_IDLE_TIME, session.getConfig().getWriterIdleTime()); //verify that IDLE events really received by handler long startTime = System.currentTimeMillis(); synchronized (mutex) { while (!readerIdleReceived && (System.currentTimeMillis() - startTime) < (READER_IDLE_TIME + 1) * 1000) try { mutex.wait(READER_IDLE_TIME * 1000); } catch (Exception e) { e.printStackTrace(); } } assertTrue(readerIdleReceived); synchronized (mutex) { while (!writerIdleReceived && (System.currentTimeMillis() - startTime) < (WRITER_IDLE_TIME + 1) * 1000) try { mutex.wait((WRITER_IDLE_TIME - READER_IDLE_TIME) * 1000); } catch (Exception e) { e.printStackTrace(); } } assertTrue(writerIdleReceived); synchronized (mutex) { while (!bothIdleReceived && (System.currentTimeMillis() - startTime) < (BOTH_IDLE_TIME + 1) * 1000) try { mutex.wait((BOTH_IDLE_TIME - WRITER_IDLE_TIME) * 1000); } catch (Exception e) { e.printStackTrace(); } } assertTrue(bothIdleReceived); } }././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/SocketConnectorTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/socket/nio/SocketConnectorTes0000644000175000017500000000274612032276016032724 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoConnector; import org.apache.mina.transport.AbstractConnectorTest; /** * Tests {@link NioSocketConnector}. * * @author Apache MINA Project */ public class SocketConnectorTest extends AbstractConnectorTest { @Override protected IoAcceptor createAcceptor() { NioSocketAcceptor acceptor = new NioSocketAcceptor(); acceptor.setReuseAddress(true); return acceptor; } @Override protected IoConnector createConnector() { return new NioSocketConnector(); } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/AbstractBindTest.java0000644000175000017500000002341512032276016031204 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; import java.net.SocketAddress; import java.util.Collection; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.transport.socket.DatagramAcceptor; import org.apache.mina.transport.socket.DatagramSessionConfig; import org.apache.mina.transport.socket.SocketAcceptor; import org.apache.mina.transport.socket.SocketSessionConfig; import org.junit.After; import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Tests {@link IoAcceptor} resource leakage by repeating bind and unbind. * * @author Apache MINA Project */ public abstract class AbstractBindTest { protected final IoAcceptor acceptor; protected int port; public AbstractBindTest(IoAcceptor acceptor) { this.acceptor = acceptor; } protected abstract SocketAddress createSocketAddress(int port); protected abstract int getPort(SocketAddress address); protected abstract IoConnector newConnector(); protected void bind(boolean reuseAddress) throws IOException { acceptor.setHandler(new EchoProtocolHandler()); setReuseAddress(reuseAddress); // Find an available test port and bind to it. boolean socketBound = false; // Let's start from port #1 to detect possible resource leak // because test will fail in port 1-1023 if user run this test // as a normal user. for (port = 1; port <= 65535; port++) { socketBound = false; try { acceptor.setDefaultLocalAddress(createSocketAddress(port)); acceptor.bind(); socketBound = true; break; } catch (IOException e) { //System.out.println(e.getMessage()); } } // If there is no port available, test fails. if (!socketBound) { throw new IOException("Cannot bind any test port."); } //System.out.println( "Using port " + port + " for testing." ); } private void setReuseAddress(boolean reuseAddress) { if (acceptor instanceof DatagramAcceptor) { ((DatagramSessionConfig) acceptor.getSessionConfig()).setReuseAddress(reuseAddress); } else if (acceptor instanceof SocketAcceptor) { ((SocketAcceptor) acceptor).setReuseAddress(reuseAddress); } } @After public void tearDown() { try { acceptor.dispose(); } catch (Exception e) { // ignore } acceptor.setDefaultLocalAddress(null); } @Test public void testAnonymousBind() throws Exception { acceptor.setHandler(new IoHandlerAdapter()); acceptor.setDefaultLocalAddress(null); acceptor.bind(); assertNotNull(acceptor.getLocalAddress()); acceptor.unbind(acceptor.getLocalAddress()); assertNull(acceptor.getLocalAddress()); acceptor.setDefaultLocalAddress(createSocketAddress(0)); acceptor.bind(); assertNotNull(acceptor.getLocalAddress()); assertTrue(getPort(acceptor.getLocalAddress()) != 0); acceptor.unbind(acceptor.getLocalAddress()); } @Test public void testDuplicateBind() throws IOException { bind(false); try { acceptor.bind(); fail("Exception is not thrown"); } catch (Exception e) { // Signifies a successfull test case execution assertTrue(true); } } @Test public void testDuplicateUnbind() throws IOException { bind(false); // this should succeed acceptor.unbind(); // this shouldn't fail acceptor.unbind(); } @Test public void testManyTimes() throws IOException { bind(true); for (int i = 0; i < 1024; i++) { acceptor.unbind(); acceptor.bind(); } } @Test public void testUnbindDisconnectsClients() throws Exception { bind(true); IoConnector connector = newConnector(); IoSession[] sessions = new IoSession[5]; connector.setHandler(new IoHandlerAdapter()); for (int i = 0; i < sessions.length; i++) { ConnectFuture future = connector.connect(createSocketAddress(port)); future.awaitUninterruptibly(); sessions[i] = future.getSession(); assertTrue(sessions[i].isConnected()); assertTrue(sessions[i].write(IoBuffer.allocate(1)).awaitUninterruptibly().isWritten()); } // Wait for the server side sessions to be created. Thread.sleep(500); Collection managedSessions = acceptor.getManagedSessions().values(); assertEquals(5, managedSessions.size()); acceptor.unbind(); // Wait for the client side sessions to close. Thread.sleep(500); assertEquals(0, managedSessions.size()); for (IoSession element : managedSessions) { assertFalse(element.isConnected()); } } @Test public void testUnbindResume() throws Exception { bind(true); IoConnector connector = newConnector(); IoSession session = null; connector.setHandler(new IoHandlerAdapter()); ConnectFuture future = connector.connect(createSocketAddress(port)); future.awaitUninterruptibly(); session = future.getSession(); assertTrue(session.isConnected()); assertTrue(session.write(IoBuffer.allocate(1)).awaitUninterruptibly().isWritten()); // Wait for the server side session to be created. Thread.sleep(500); Collection managedSession = acceptor.getManagedSessions().values(); assertEquals(1, managedSession.size()); acceptor.unbind(); // Wait for the client side sessions to close. Thread.sleep(500); assertEquals(0, managedSession.size()); for (IoSession element : managedSession) { assertFalse(element.isConnected()); } // Rebind bind(true); // Check again the connection future = connector.connect(createSocketAddress(port)); future.awaitUninterruptibly(); session = future.getSession(); assertTrue(session.isConnected()); assertTrue(session.write(IoBuffer.allocate(1)).awaitUninterruptibly().isWritten()); // Wait for the server side session to be created. Thread.sleep(500); managedSession = acceptor.getManagedSessions().values(); assertEquals(1, managedSession.size()); } @Test @Ignore public void testRegressively() throws IOException { setReuseAddress(true); SocketAddress addr = createSocketAddress(port); EchoProtocolHandler handler = new EchoProtocolHandler(); acceptor.setDefaultLocalAddress(addr); acceptor.setHandler(handler); for (int i = 0; i < 1048576; i++) { acceptor.bind(); acceptor.unbind(); } bind(false); } private static class EchoProtocolHandler extends IoHandlerAdapter { private static final Logger LOG = LoggerFactory.getLogger(EchoProtocolHandler.class); /** * Default constructor */ public EchoProtocolHandler() { super(); } @Override public void sessionCreated(IoSession session) { if (session.getConfig() instanceof SocketSessionConfig) { ((SocketSessionConfig) session.getConfig()).setReceiveBufferSize(2048); } session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10); } @Override public void sessionIdle(IoSession session, IdleStatus status) { LOG.info("*** IDLE #" + session.getIdleCount(IdleStatus.BOTH_IDLE) + " ***"); } @Override public void exceptionCaught(IoSession session, Throwable cause) { //cause.printStackTrace(); session.close(true); } @Override public void messageReceived(IoSession session, Object message) throws Exception { if (!(message instanceof IoBuffer)) { return; } IoBuffer rb = (IoBuffer) message; // Write the received data back to remote peer IoBuffer wb = IoBuffer.allocate(rb.remaining()); wb.put(rb); wb.flip(); session.write(wb); } } }mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/vmpipe/0000755000175000017500000000000012162575507026447 5ustar ebourgebourg././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/vmpipe/VmPipeTrafficControlTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/vmpipe/VmPipeTrafficControlTe0000644000175000017500000000362612032276016032717 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.vmpipe; import java.net.SocketAddress; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandler; import org.apache.mina.transport.AbstractTrafficControlTest; /** * Tests suspending and resuming reads and writes for the VM pipe transport * type. * * @author Apache MINA Project */ public class VmPipeTrafficControlTest extends AbstractTrafficControlTest { public VmPipeTrafficControlTest() { super(new VmPipeAcceptor()); } @Override protected ConnectFuture connect(int port, IoHandler handler) throws Exception { IoConnector connector = new VmPipeConnector(); connector.setHandler(handler); return connector.connect(new VmPipeAddress(port)); } @Override protected SocketAddress createServerSocketAddress(int port) { return new VmPipeAddress(port); } @Override protected int getPort(SocketAddress address) { return ((VmPipeAddress) address).getPort(); } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/vmpipe/VmPipeBindTest.java0000644000175000017500000000310712032276016032135 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.vmpipe; import java.net.SocketAddress; import org.apache.mina.core.service.IoConnector; import org.apache.mina.transport.AbstractBindTest; /** * Tests {@link VmPipeAcceptor} bind and unbind. * * @author Apache MINA Project */ public class VmPipeBindTest extends AbstractBindTest { public VmPipeBindTest() { super(new VmPipeAcceptor()); } @Override protected SocketAddress createSocketAddress(int port) { return new VmPipeAddress(port); } @Override protected int getPort(SocketAddress address) { return ((VmPipeAddress) address).getPort(); } @Override protected IoConnector newConnector() { return new VmPipeConnector(); } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/vmpipe/VmPipeSessionCrossCommunicationTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/vmpipe/VmPipeSessionCrossComm0000644000175000017500000001337212032276016032757 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.mina.transport.vmpipe; import static org.junit.Assert.fail; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.junit.Test; /** * TODO Add documentation * * @author Apache MINA Project */ public class VmPipeSessionCrossCommunicationTest { @Test public void testOneSessionTalkingBackAndForthDoesNotDeadlock() throws Exception { final VmPipeAddress address = new VmPipeAddress(1); final IoConnector connector = new VmPipeConnector(); final AtomicReference c1 = new AtomicReference(); final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch messageCount = new CountDownLatch(2); IoAcceptor acceptor = new VmPipeAcceptor(); acceptor.setHandler(new IoHandlerAdapter() { @Override public void messageReceived(IoSession session, Object message) throws Exception { //System.out.println(Thread.currentThread().getName() + ": " + message); if ("start".equals(message)) { session.write("open new"); } else if ("re-use c1".equals(message)) { session.write("tell me something on c1 now"); } else if (((String) message).startsWith("please don't deadlock")) { messageCount.countDown(); } else { fail("unexpected message received " + message); } } }); acceptor.bind(address); connector.setHandler(new IoHandlerAdapter() { @Override public void messageReceived(IoSession session, Object message) throws Exception { //System.out.println(Thread.currentThread().getName() + ": " + message); if ("open new".equals(message)) { //System.out.println("opening c2 from " + Thread.currentThread().getName()); IoConnector c2 = new VmPipeConnector(); c2.setHandler(new IoHandlerAdapter() { @Override public void sessionOpened(IoSession session) throws Exception { session.write("re-use c1"); } @Override public void messageReceived(IoSession session, Object message) throws Exception { //System.out.println(Thread.currentThread().getName() + ": " + message); if ("tell me something on c1 now".equals(message)) { latch.countDown(); c1.get().write("please don't deadlock via c1"); } else { fail("unexpected message received " + message); } } }); ConnectFuture c2Future = c2.connect(address); c2Future.await(); latch.await(); c2Future.getSession().write("please don't deadlock via c2"); } else { fail("unexpeced message received " + message); } } }); ConnectFuture future = connector.connect(address); future.await(); c1.set(future.getSession()); c1.get().write("start"); ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); while (!messageCount.await(100, TimeUnit.MILLISECONDS)) { long[] threads = threadMXBean.findMonitorDeadlockedThreads(); if (null != threads) { StringBuffer sb = new StringBuffer(256); ThreadInfo[] infos = threadMXBean.getThreadInfo(threads, Integer.MAX_VALUE); for (ThreadInfo info : infos) { sb.append(info.getThreadName()).append(" blocked on ").append(info.getLockName()) .append(" owned by ").append(info.getLockOwnerName()).append("\n"); } for (ThreadInfo info : infos) { sb.append("\nStack for ").append(info.getThreadName()).append("\n"); for (StackTraceElement element : info.getStackTrace()) { sb.append("\t").append(element).append("\n"); } } fail("deadlocked! \n" + sb); } } acceptor.setCloseOnDeactivation(false); acceptor.dispose(); } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/vmpipe/VmPipeEventOrderTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/transport/vmpipe/VmPipeEventOrderTest.j0000644000175000017500000001547612032276016032662 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.vmpipe; import static org.junit.Assert.assertEquals; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.executor.ExecutorFilter; import org.junit.Test; /** * Makes sure the order of events are correct. * * @author Apache MINA Project */ public class VmPipeEventOrderTest { @Test public void testServerToClient() throws Exception { IoAcceptor acceptor = new VmPipeAcceptor(); IoConnector connector = new VmPipeConnector(); acceptor.setHandler(new IoHandlerAdapter() { @Override public void sessionOpened(IoSession session) throws Exception { session.write("B"); } @Override public void messageSent(IoSession session, Object message) throws Exception { session.close(true); } }); acceptor.bind(new VmPipeAddress(1)); final StringBuffer actual = new StringBuffer(); connector.setHandler(new IoHandlerAdapter() { @Override public void messageReceived(IoSession session, Object message) throws Exception { actual.append(message); } @Override public void sessionClosed(IoSession session) throws Exception { actual.append("C"); } @Override public void sessionOpened(IoSession session) throws Exception { actual.append("A"); } }); ConnectFuture future = connector.connect(new VmPipeAddress(1)); future.awaitUninterruptibly(); future.getSession().getCloseFuture().awaitUninterruptibly(); acceptor.dispose(); // sessionClosed() might not be invoked yet // even if the connection is closed. while (actual.indexOf("C") < 0) { Thread.yield(); } assertEquals("ABC", actual.toString()); } @Test public void testClientToServer() throws Exception { IoAcceptor acceptor = new VmPipeAcceptor(); IoConnector connector = new VmPipeConnector(); final StringBuffer actual = new StringBuffer(); acceptor.setHandler(new IoHandlerAdapter() { @Override public void messageReceived(IoSession session, Object message) throws Exception { actual.append(message); } @Override public void sessionClosed(IoSession session) throws Exception { actual.append("C"); } @Override public void sessionOpened(IoSession session) throws Exception { actual.append("A"); } }); acceptor.bind(new VmPipeAddress(1)); connector.setHandler(new IoHandlerAdapter() { @Override public void sessionOpened(IoSession session) throws Exception { session.write("B"); } @Override public void messageSent(IoSession session, Object message) throws Exception { session.close(true); } }); ConnectFuture future = connector.connect(new VmPipeAddress(1)); future.awaitUninterruptibly(); future.getSession().getCloseFuture().awaitUninterruptibly(); acceptor.dispose(); connector.dispose(); // sessionClosed() might not be invoked yet // even if the connection is closed. while (actual.indexOf("C") < 0) { Thread.yield(); } assertEquals("ABC", actual.toString()); } @Test public void testSessionCreated() throws Exception { final Semaphore semaphore = new Semaphore(0); final StringBuffer stringBuffer = new StringBuffer(); VmPipeAcceptor vmPipeAcceptor = new VmPipeAcceptor(); final VmPipeAddress vmPipeAddress = new VmPipeAddress(12345); vmPipeAcceptor.setHandler(new IoHandlerAdapter() { @Override public void sessionCreated(IoSession session) throws Exception { // pretend we are doing some time-consuming work. For // performance reasons, you would never want to do time // consuming work in sessionCreated. // However, this increases the likelihood of the timing bug. Thread.sleep(1000); stringBuffer.append("A"); } @Override public void sessionOpened(IoSession session) throws Exception { stringBuffer.append("B"); } @Override public void messageReceived(IoSession session, Object message) throws Exception { stringBuffer.append("C"); } @Override public void sessionClosed(IoSession session) throws Exception { stringBuffer.append("D"); semaphore.release(); } }); vmPipeAcceptor.bind(vmPipeAddress); final VmPipeConnector vmPipeConnector = new VmPipeConnector(); vmPipeConnector.getFilterChain().addLast("executor", new ExecutorFilter()); vmPipeConnector.setHandler(new IoHandlerAdapter()); ConnectFuture connectFuture = vmPipeConnector.connect(vmPipeAddress); connectFuture.awaitUninterruptibly(); connectFuture.getSession().write(IoBuffer.wrap(new byte[1])).awaitUninterruptibly(); connectFuture.getSession().close(false).awaitUninterruptibly(); semaphore.tryAcquire(1, TimeUnit.SECONDS); vmPipeAcceptor.unbind(vmPipeAddress); assertEquals(1, connectFuture.getSession().getWrittenBytes()); assertEquals("ABCD", stringBuffer.toString()); } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/handler/0000755000175000017500000000000012032276016024515 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/handler/chain/0000755000175000017500000000000012162575507025612 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/handler/chain/ChainedIoHandlerTest.java0000644000175000017500000000406712032276016032432 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.handler.chain; import org.apache.mina.core.session.DummySession; import org.apache.mina.core.session.IoSession; import org.junit.Test; import static org.junit.Assert.assertEquals; /** * A test case for {@link ChainedIoHandler}. * * @author Apache MINA Project */ public class ChainedIoHandlerTest { @Test public void testChainedCommand() throws Exception { IoHandlerChain chain = new IoHandlerChain(); StringBuilder buf = new StringBuilder(); chain.addLast("A", new TestCommand(buf, 'A')); chain.addLast("B", new TestCommand(buf, 'B')); chain.addLast("C", new TestCommand(buf, 'C')); new ChainedIoHandler(chain).messageReceived(new DummySession(), null); assertEquals("ABC", buf.toString()); } private class TestCommand implements IoHandlerCommand { private final StringBuilder buf; private final char ch; public TestCommand(StringBuilder buf, char ch) { this.buf = buf; this.ch = ch; } public void execute(NextCommand next, IoSession session, Object message) throws Exception { buf.append(ch); next.execute(session, message); } } } mina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/handler/demux/0000755000175000017500000000000012162575507025652 5ustar ebourgebourg././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/handler/demux/DemuxingIoHandlerTest.javamina2-2.0.7.orig/src/mina-core/src/test/java/org/apache/mina/handler/demux/DemuxingIoHandlerTest.jav0000644000175000017500000001567212032276016032562 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.handler.demux; import org.apache.mina.core.session.IoSession; import org.easymock.EasyMock; import org.junit.Before; import org.junit.Test; /** * Tests {@link org.apache.mina.handler.demux.DemuxingIoHandler}. * * @author Apache MINA Project */ @SuppressWarnings("unchecked") public class DemuxingIoHandlerTest { MessageHandler handler1; MessageHandler handler2; MessageHandler handler3; IoSession session; Object[] msg; @Before public void setUp() throws Exception { /* * Create the messages. */ msg = new Object[9]; msg[0] = new C1(); msg[1] = new C2(); msg[2] = new C3(); msg[3] = new C1(); msg[4] = new C2(); msg[5] = new C3(); msg[6] = new C1(); msg[7] = new C2(); msg[8] = new C3(); /* * Create mocks. */ handler1 = EasyMock.createMock(MessageHandler.class); handler2 = EasyMock.createMock(MessageHandler.class); handler3 = EasyMock.createMock(MessageHandler.class); session = EasyMock.createMock(IoSession.class); } @Test public void testFindHandlerByClass() throws Exception { /* * Record expectations. */ handler1.handleMessage(session, msg[0]); handler1.handleMessage(session, msg[1]); handler1.handleMessage(session, msg[2]); handler1.handleMessage(session, msg[3]); handler2.handleMessage(session, msg[4]); handler2.handleMessage(session, msg[5]); handler1.handleMessage(session, msg[6]); handler2.handleMessage(session, msg[7]); handler3.handleMessage(session, msg[8]); /* * Replay. */ EasyMock.replay(handler1); EasyMock.replay(handler2); EasyMock.replay(handler3); DemuxingIoHandler ioHandler = new DemuxingIoHandler(); /* * First round. All messages should be handled by handler1 */ ioHandler.addReceivedMessageHandler(C1.class, handler1); ioHandler.messageReceived(session, msg[0]); ioHandler.messageReceived(session, msg[1]); ioHandler.messageReceived(session, msg[2]); /* * Second round. C1 messages should be handled by handler1. C2 and C3 * messages should be handled by handler2. */ ioHandler.addReceivedMessageHandler(C2.class, handler2); ioHandler.messageReceived(session, msg[3]); ioHandler.messageReceived(session, msg[4]); ioHandler.messageReceived(session, msg[5]); /* * Third round. C1 messages should be handled by handler1, C2 by * handler2 and C3 by handler3. */ ioHandler.addReceivedMessageHandler(C3.class, handler3); ioHandler.messageReceived(session, msg[6]); ioHandler.messageReceived(session, msg[7]); ioHandler.messageReceived(session, msg[8]); /* * Verify. */ EasyMock.verify(handler1); EasyMock.verify(handler2); EasyMock.verify(handler3); } @Test public void testFindHandlerByInterface() throws Exception { /* * Record expectations. */ handler1.handleMessage(session, msg[0]); handler1.handleMessage(session, msg[1]); handler1.handleMessage(session, msg[2]); handler1.handleMessage(session, msg[3]); handler2.handleMessage(session, msg[4]); handler1.handleMessage(session, msg[5]); handler3.handleMessage(session, msg[6]); handler2.handleMessage(session, msg[7]); handler3.handleMessage(session, msg[8]); /* * Replay. */ EasyMock.replay(handler1); EasyMock.replay(handler2); EasyMock.replay(handler3); DemuxingIoHandler ioHandler = new DemuxingIoHandler(); /* * First round. All messages should be handled by handler1 */ ioHandler.addReceivedMessageHandler(I4.class, handler1); ioHandler.messageReceived(session, msg[0]); ioHandler.messageReceived(session, msg[1]); ioHandler.messageReceived(session, msg[2]); /* * Second round. C1 and C3 messages should be handled by handler1. C2 * messages should be handled by handler2. */ ioHandler.addReceivedMessageHandler(I6.class, handler2); ioHandler.messageReceived(session, msg[3]); ioHandler.messageReceived(session, msg[4]); ioHandler.messageReceived(session, msg[5]); /* * Third round. C1 and C3 messages should be handled by handler3. C2 * messages should be handled by handler2. */ ioHandler.addReceivedMessageHandler(I3.class, handler3); ioHandler.messageReceived(session, msg[6]); ioHandler.messageReceived(session, msg[7]); ioHandler.messageReceived(session, msg[8]); /* * Verify. */ EasyMock.verify(handler1); EasyMock.verify(handler2); EasyMock.verify(handler3); } /* * Define some interfaces and classes used when testing the findHandler * method. This is what the hierarchy looks like: * * C3 - I7 - I9 * | | /\ * | I8 I3 I4 * | * C2 - I5 - I6 * | * C1 - I1 - I2 - I4 * | * I3 */ public interface I1 { // Do nothing } public interface I2 extends I3 { // Do nothing } public interface I3 { // Do nothing } public interface I4 { // Do nothing } public static class C1 implements I1, I2, I4 { // Do nothing } public interface I5 { // Do nothing } public interface I6 { // Do nothing } public static class C2 extends C1 implements I5, I6 { // Do nothing } public interface I7 extends I8 { // Do nothing } public interface I8 { // Do nothing } public interface I9 extends I3, I4 { // Do nothing } public static class C3 extends C2 implements I7, I9 { // Do nothing } } mina2-2.0.7.orig/src/mina-core/src/test/resources/0000755000175000017500000000000012162575507021250 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/resources/log4j.properties0000644000175000017500000000276412032276017024404 0ustar ebourgebourg############################################################################# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ############################################################################# # Please don't modify the log level until we reach to acceptable test coverage. # It's very useful when I test examples manually. log4j.rootCategory=INFO, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c] - %m%n # you could use this pattern to test the MDC with the Chat server #log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %t %p %X{name} [%X{user}] [%X{remoteIp}:%X{remotePort}] [%c] - %m%nmina2-2.0.7.orig/src/mina-core/src/test/resources/org/0000755000175000017500000000000012032276017022025 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/resources/org/apache/0000755000175000017500000000000012032276017023246 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/resources/org/apache/mina/0000755000175000017500000000000012032276017024172 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/resources/org/apache/mina/filter/0000755000175000017500000000000012032276017025457 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/resources/org/apache/mina/filter/ssl/0000755000175000017500000000000012162575507026272 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/test/resources/org/apache/mina/filter/ssl/keystore.sslTest0000644000175000017500000000253012032276017031510 0ustar ebourgebourgtaserverJ900 +*Ե/7;BRsi{PA eL_d8(*;$ 4[qi?eW%lm USJq%*Ӝ/6}2=@a01r vd-у?G̹OdMR [g[l)Qf_5]Jj .E|XBqA&o"-ܝ/ـr"}uWЎ|…Ƭ- :(u}>V~o&f~3.&p!&{vSœi}Jt'h;OJ Si9a0  *H /A^>v!3JE@0v)X|RCQ#rp%MOػXl9ΥN …pUe/N쳍9+}﹎Yu}݁9sSˬsc4&VJJRZmina2-2.0.7.orig/src/mina-core/src/test/resources/org/apache/mina/filter/ssl/truststore.sslTest0000644000175000017500000000121612032276017032101 0ustar ebourgebourgcaJmX.509S0O0IJz0  *H 0l10UUnknown10UUnknown10UUnknown10U Unknown10U Unknown10UUnknown0 081218163137Z 090318163137Z0l10UUnknown10UUnknown10UUnknown10U Unknown10U Unknown10UUnknown00  *H 03/|)흶ޕOn&p!&{vSœi}Jt'h;OJ Si9a0  *H /A^>v!3JE@0v)X|RCQ#rp%MOػXl9ΥN …pUe/N쳍9+}﹎Yu}݁9sS 6ҁJVB0mina2-2.0.7.orig/src/mina-core/src/test/resources/org/apache/mina/filter/ssl/keystore.cert0000644000175000017500000000165112032276017031007 0ustar ebourgebourgbogus}Ė00 +*|a-##A֧o".FRy ֔Їf`BKZMiPо˖(-SXH:"3|'%Ne\5 IK82EW sa!F[ˈy (Ahic9+|&D[)O7؏D!ݥ ߰1ÛaE8DNc˸ꇖ(؄N v}Ѐq1YbiYAJkjK9TNe\0ܘ-R'X.50900rB,pS0  *H 0n1 0 USE10U Stockholm10U Stockholm10U  Bogus Inc10 U XXX CA10U bogus.com0 050307151635Z 150305151635Z0n1 0 USE10U Stockholm10U Stockholm10U  Bogus Inc10 U XXX CA10U bogus.com0[0  *H J0G@Z & |+mJ;X|jv>JHmK'6LAx3i o0  *H AI@Ba?>2n(9OdmiJE 5 @y |[:k#Ŧ];e8mina2-2.0.7.orig/src/mina-core/src/main/0000755000175000017500000000000012032276034017170 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/0000755000175000017500000000000012032276017020112 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/0000755000175000017500000000000012032276017020701 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/0000755000175000017500000000000012032276017022122 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/0000755000175000017500000000000012032276033023044 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/0000755000175000017500000000000012162575507024241 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/0000755000175000017500000000000012162575507026041 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/ProxyRequest.java0000644000175000017500000000351512032276022031364 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers; import java.net.InetSocketAddress; /** * ProxyRequest.java - Abstract wrapper class for proxy requests. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public abstract class ProxyRequest { /** * The address of the request endpoint. */ private InetSocketAddress endpointAddress = null; /** * Implicit constructor. */ public ProxyRequest() { // Do nothing } /** * Basic constructor of a {@link ProxyRequest} that only sets the * address of the request endpoint. * * @param endpointAddress the address of the request endpoint. */ public ProxyRequest(final InetSocketAddress endpointAddress) { this.endpointAddress = endpointAddress; } /** * Returns the address of the request endpoint. * * @return the address of the request endpoint */ public InetSocketAddress getEndpointAddress() { return endpointAddress; } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/0000755000175000017500000000000012162575507027020 5ustar ebourgebourg././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/HttpSmartProxyHandler.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/HttpSmartProxyHandl0000644000175000017500000001741312032276021032671 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.http; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.proxy.ProxyAuthException; import org.apache.mina.proxy.session.ProxyIoSession; import org.apache.mina.proxy.utils.StringUtilities; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * HttpSmartProxyHandler.java - HTTP proxy handler that automatically handles forwarding a request * to the appropriate authentication mechanism logic handler. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class HttpSmartProxyHandler extends AbstractHttpLogicHandler { private final static Logger logger = LoggerFactory.getLogger(HttpSmartProxyHandler.class); /** * Has the HTTP proxy request been sent ? */ private boolean requestSent = false; /** * The automatically selected http authentication logic handler. */ private AbstractAuthLogicHandler authHandler; public HttpSmartProxyHandler(final ProxyIoSession proxyIoSession) { super(proxyIoSession); } /** * Performs the handshake processing. * * @param nextFilter the next filter */ public void doHandshake(final NextFilter nextFilter) throws ProxyAuthException { logger.debug(" doHandshake()"); if (authHandler != null) { authHandler.doHandshake(nextFilter); } else { if (requestSent) { // Safety check throw new ProxyAuthException("Authentication request already sent"); } logger.debug(" sending HTTP request"); // Compute request headers HttpProxyRequest req = (HttpProxyRequest) getProxyIoSession().getRequest(); Map> headers = req.getHeaders() != null ? req.getHeaders() : new HashMap>(); AbstractAuthLogicHandler.addKeepAliveHeaders(headers); req.setHeaders(headers); // Write request to the proxy writeRequest(nextFilter, req); requestSent = true; } } /** * Automatic selection of the authentication algorithm. If preferedOrder is set then * algorithms are selected from the list order otherwise the algorithm tries to select the most * secured algorithm available first. * * @param response the proxy response */ private void autoSelectAuthHandler(final HttpProxyResponse response) throws ProxyAuthException { // Get the Proxy-Authenticate header List values = response.getHeaders().get("Proxy-Authenticate"); ProxyIoSession proxyIoSession = getProxyIoSession(); if (values == null || values.size() == 0) { authHandler = HttpAuthenticationMethods.NO_AUTH.getNewHandler(proxyIoSession); } else if (getProxyIoSession().getPreferedOrder() == null) { // No preference order set for auth mechanisms int method = -1; // Test which auth mechanism to use. First found is the first used // that's why we test in a decreasing security quality order. for (String proxyAuthHeader : values) { proxyAuthHeader = proxyAuthHeader.toLowerCase(); if (proxyAuthHeader.contains("ntlm")) { method = HttpAuthenticationMethods.NTLM.getId(); break; } else if (proxyAuthHeader.contains("digest") && method != HttpAuthenticationMethods.NTLM.getId()) { method = HttpAuthenticationMethods.DIGEST.getId(); } else if (proxyAuthHeader.contains("basic") && method == -1) { method = HttpAuthenticationMethods.BASIC.getId(); } } if (method != -1) { try { authHandler = HttpAuthenticationMethods.getNewHandler(method, proxyIoSession); } catch (Exception ex) { logger.debug("Following exception occured:", ex); } } if (authHandler == null) { authHandler = HttpAuthenticationMethods.NO_AUTH.getNewHandler(proxyIoSession); } } else { for (HttpAuthenticationMethods method : proxyIoSession.getPreferedOrder()) { if (authHandler != null) { break; } if (method == HttpAuthenticationMethods.NO_AUTH) { authHandler = HttpAuthenticationMethods.NO_AUTH.getNewHandler(proxyIoSession); break; } for (String proxyAuthHeader : values) { proxyAuthHeader = proxyAuthHeader.toLowerCase(); try { // test which auth mechanism to use if (proxyAuthHeader.contains("basic") && method == HttpAuthenticationMethods.BASIC) { authHandler = HttpAuthenticationMethods.BASIC.getNewHandler(proxyIoSession); break; } else if (proxyAuthHeader.contains("digest") && method == HttpAuthenticationMethods.DIGEST) { authHandler = HttpAuthenticationMethods.DIGEST.getNewHandler(proxyIoSession); break; } else if (proxyAuthHeader.contains("ntlm") && method == HttpAuthenticationMethods.NTLM) { authHandler = HttpAuthenticationMethods.NTLM.getNewHandler(proxyIoSession); break; } } catch (Exception ex) { logger.debug("Following exception occured:", ex); } } } } if (authHandler == null) { throw new ProxyAuthException("Unknown authentication mechanism(s): " + values); } } /** * Handle a HTTP response from the proxy server. * * @param response The proxy response. */ @Override public void handleResponse(final HttpProxyResponse response) throws ProxyAuthException { if (!isHandshakeComplete() && ("close".equalsIgnoreCase(StringUtilities.getSingleValuedHeader(response.getHeaders(), "Proxy-Connection")) || "close".equalsIgnoreCase(StringUtilities.getSingleValuedHeader( response.getHeaders(), "Connection")))) { getProxyIoSession().setReconnectionNeeded(true); } if (response.getStatusCode() == 407) { if (authHandler == null) { autoSelectAuthHandler(response); } authHandler.handleResponse(response); } else { throw new ProxyAuthException("Error: unexpected response code " + response.getStatusLine() + " received from proxy."); } } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/ntlm/0000755000175000017500000000000012162575507027772 5ustar ebourgebourg././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/ntlm/NTLMResponses.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/ntlm/NTLMResponses.0000644000175000017500000003773412032276021032446 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.http.ntlm; import java.io.UnsupportedEncodingException; import java.security.Key; import java.security.MessageDigest; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; /** * NTLMResponses.java - Calculates the various Type 3 responses. Needs an MD4, MD5 and DES * crypto provider (Please note that default provider doesn't provide MD4). * * Copyright (c) 2003 Eric Glass * Permission to use, copy, modify, and distribute this document for any purpose and without * any fee is hereby granted, provided that the above copyright notice and this list of * conditions appear in all copies. * @see http://curl.haxx.se/rfc/ntlm.html * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class NTLMResponses { // LAN Manager magic constant used in LM Response calculation public static byte[] LM_HASH_MAGIC_CONSTANT = null; static { try { LM_HASH_MAGIC_CONSTANT = "KGS!@#$%".getBytes("US-ASCII"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } /** * Calculates the LM Response for the given challenge, using the specified * password. * * @param password The user's password. * @param challenge The Type 2 challenge from the server. * * @return The LM Response. */ public static byte[] getLMResponse(String password, byte[] challenge) throws Exception { byte[] lmHash = lmHash(password); return lmResponse(lmHash, challenge); } /** * Calculates the NTLM Response for the given challenge, using the * specified password. * * @param password The user's password. * @param challenge The Type 2 challenge from the server. * * @return The NTLM Response. */ public static byte[] getNTLMResponse(String password, byte[] challenge) throws Exception { byte[] ntlmHash = ntlmHash(password); return lmResponse(ntlmHash, challenge); } /** * Calculates the NTLMv2 Response for the given challenge, using the * specified authentication target, username, password, target information * block, and client nonce. * * @param target The authentication target (i.e., domain). * @param user The username. * @param password The user's password. * @param targetInformation The target information block from the Type 2 * message. * @param challenge The Type 2 challenge from the server. * @param clientNonce The random 8-byte client nonce. * * @return The NTLMv2 Response. */ public static byte[] getNTLMv2Response(String target, String user, String password, byte[] targetInformation, byte[] challenge, byte[] clientNonce) throws Exception { return getNTLMv2Response(target, user, password, targetInformation, challenge, clientNonce, System.currentTimeMillis()); } /** * Calculates the NTLMv2 Response for the given challenge, using the * specified authentication target, username, password, target information * block, and client nonce. * * @param target The authentication target (i.e., domain). * @param user The username. * @param password The user's password. * @param targetInformation The target information block from the Type 2 * message. * @param challenge The Type 2 challenge from the server. * @param clientNonce The random 8-byte client nonce. * @param time The time stamp. * * @return The NTLMv2 Response. */ public static byte[] getNTLMv2Response(String target, String user, String password, byte[] targetInformation, byte[] challenge, byte[] clientNonce, long time) throws Exception { byte[] ntlmv2Hash = ntlmv2Hash(target, user, password); byte[] blob = createBlob(targetInformation, clientNonce, time); return lmv2Response(ntlmv2Hash, blob, challenge); } /** * Calculates the LMv2 Response for the given challenge, using the * specified authentication target, username, password, and client * challenge. * * @param target The authentication target (i.e., domain). * @param user The username. * @param password The user's password. * @param challenge The Type 2 challenge from the server. * @param clientNonce The random 8-byte client nonce. * * @return The LMv2 Response. */ public static byte[] getLMv2Response(String target, String user, String password, byte[] challenge, byte[] clientNonce) throws Exception { byte[] ntlmv2Hash = ntlmv2Hash(target, user, password); return lmv2Response(ntlmv2Hash, clientNonce, challenge); } /** * Calculates the NTLM2 Session Response for the given challenge, using the * specified password and client nonce. * * @param password The user's password. * @param challenge The Type 2 challenge from the server. * @param clientNonce The random 8-byte client nonce. * * @return The NTLM2 Session Response. This is placed in the NTLM * response field of the Type 3 message; the LM response field contains * the client nonce, null-padded to 24 bytes. */ public static byte[] getNTLM2SessionResponse(String password, byte[] challenge, byte[] clientNonce) throws Exception { byte[] ntlmHash = ntlmHash(password); MessageDigest md5 = MessageDigest.getInstance("MD5"); md5.update(challenge); md5.update(clientNonce); byte[] sessionHash = new byte[8]; System.arraycopy(md5.digest(), 0, sessionHash, 0, 8); return lmResponse(ntlmHash, sessionHash); } /** * Creates the LM Hash of the user's password. * * @param password The password. * * @return The LM Hash of the given password, used in the calculation * of the LM Response. */ private static byte[] lmHash(String password) throws Exception { byte[] oemPassword = password.toUpperCase().getBytes("US-ASCII"); int length = Math.min(oemPassword.length, 14); byte[] keyBytes = new byte[14]; System.arraycopy(oemPassword, 0, keyBytes, 0, length); Key lowKey = createDESKey(keyBytes, 0); Key highKey = createDESKey(keyBytes, 7); Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); des.init(Cipher.ENCRYPT_MODE, lowKey); byte[] lowHash = des.doFinal(LM_HASH_MAGIC_CONSTANT); des.init(Cipher.ENCRYPT_MODE, highKey); byte[] highHash = des.doFinal(LM_HASH_MAGIC_CONSTANT); byte[] lmHash = new byte[16]; System.arraycopy(lowHash, 0, lmHash, 0, 8); System.arraycopy(highHash, 0, lmHash, 8, 8); return lmHash; } /** * Creates the NTLM Hash of the user's password. * * @param password The password. * * @return The NTLM Hash of the given password, used in the calculation * of the NTLM Response and the NTLMv2 and LMv2 Hashes. */ private static byte[] ntlmHash(String password) throws Exception { byte[] unicodePassword = password.getBytes("UnicodeLittleUnmarked"); MessageDigest md4 = MessageDigest.getInstance("MD4"); return md4.digest(unicodePassword); } /** * Creates the NTLMv2 Hash of the user's password. * * @param target The authentication target (i.e., domain). * @param user The username. * @param password The password. * * @return The NTLMv2 Hash, used in the calculation of the NTLMv2 * and LMv2 Responses. */ private static byte[] ntlmv2Hash(String target, String user, String password) throws Exception { byte[] ntlmHash = ntlmHash(password); String identity = user.toUpperCase() + target; return hmacMD5(identity.getBytes("UnicodeLittleUnmarked"), ntlmHash); } /** * Creates the LM Response from the given hash and Type 2 challenge. * * @param hash The LM or NTLM Hash. * @param challenge The server challenge from the Type 2 message. * * @return The response (either LM or NTLM, depending on the provided * hash). */ private static byte[] lmResponse(byte[] hash, byte[] challenge) throws Exception { byte[] keyBytes = new byte[21]; System.arraycopy(hash, 0, keyBytes, 0, 16); Key lowKey = createDESKey(keyBytes, 0); Key middleKey = createDESKey(keyBytes, 7); Key highKey = createDESKey(keyBytes, 14); Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); des.init(Cipher.ENCRYPT_MODE, lowKey); byte[] lowResponse = des.doFinal(challenge); des.init(Cipher.ENCRYPT_MODE, middleKey); byte[] middleResponse = des.doFinal(challenge); des.init(Cipher.ENCRYPT_MODE, highKey); byte[] highResponse = des.doFinal(challenge); byte[] lmResponse = new byte[24]; System.arraycopy(lowResponse, 0, lmResponse, 0, 8); System.arraycopy(middleResponse, 0, lmResponse, 8, 8); System.arraycopy(highResponse, 0, lmResponse, 16, 8); return lmResponse; } /** * Creates the LMv2 Response from the given hash, client data, and * Type 2 challenge. * * @param hash The NTLMv2 Hash. * @param clientData The client data (blob or client nonce). * @param challenge The server challenge from the Type 2 message. * * @return The response (either NTLMv2 or LMv2, depending on the * client data). */ private static byte[] lmv2Response(byte[] hash, byte[] clientData, byte[] challenge) throws Exception { byte[] data = new byte[challenge.length + clientData.length]; System.arraycopy(challenge, 0, data, 0, challenge.length); System.arraycopy(clientData, 0, data, challenge.length, clientData.length); byte[] mac = hmacMD5(data, hash); byte[] lmv2Response = new byte[mac.length + clientData.length]; System.arraycopy(mac, 0, lmv2Response, 0, mac.length); System.arraycopy(clientData, 0, lmv2Response, mac.length, clientData.length); return lmv2Response; } /** * Creates the NTLMv2 blob from the given target information block and * client nonce. * * @param targetInformation The target information block from the Type 2 * message. * @param clientNonce The random 8-byte client nonce. * @param time the time stamp. * * @return The blob, used in the calculation of the NTLMv2 Response. */ private static byte[] createBlob(byte[] targetInformation, byte[] clientNonce, long time) { byte[] blobSignature = new byte[] { (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00 }; byte[] reserved = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; byte[] unknown1 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; byte[] unknown2 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; time += 11644473600000l; // milliseconds from January 1, 1601 -> epoch. time *= 10000; // tenths of a microsecond. // convert to little-endian byte array. byte[] timestamp = new byte[8]; for (int i = 0; i < 8; i++) { timestamp[i] = (byte) time; time >>>= 8; } byte[] blob = new byte[blobSignature.length + reserved.length + timestamp.length + clientNonce.length + unknown1.length + targetInformation.length + unknown2.length]; int offset = 0; System.arraycopy(blobSignature, 0, blob, offset, blobSignature.length); offset += blobSignature.length; System.arraycopy(reserved, 0, blob, offset, reserved.length); offset += reserved.length; System.arraycopy(timestamp, 0, blob, offset, timestamp.length); offset += timestamp.length; System.arraycopy(clientNonce, 0, blob, offset, clientNonce.length); offset += clientNonce.length; System.arraycopy(unknown1, 0, blob, offset, unknown1.length); offset += unknown1.length; System.arraycopy(targetInformation, 0, blob, offset, targetInformation.length); offset += targetInformation.length; System.arraycopy(unknown2, 0, blob, offset, unknown2.length); return blob; } /** * Calculates the HMAC-MD5 hash of the given data using the specified * hashing key. * * @param data The data for which the hash will be calculated. * @param key The hashing key. * * @return The HMAC-MD5 hash of the given data. */ public static byte[] hmacMD5(byte[] data, byte[] key) throws Exception { byte[] ipad = new byte[64]; byte[] opad = new byte[64]; // Stores key in pads and XOR it with ipad and opad values for (int i = 0; i < 64; i++) { if (i < key.length) { ipad[i] = (byte) (key[i] ^ 0x36); opad[i] = (byte) (key[i] ^ 0x5c); } else { ipad[i] = 0x36; opad[i] = 0x5c; } } byte[] content = new byte[data.length + 64]; System.arraycopy(ipad, 0, content, 0, 64); System.arraycopy(data, 0, content, 64, data.length); MessageDigest md5 = MessageDigest.getInstance("MD5"); data = md5.digest(content); content = new byte[data.length + 64]; System.arraycopy(opad, 0, content, 0, 64); System.arraycopy(data, 0, content, 64, data.length); return md5.digest(content); } /** * Creates a DES encryption key from the given key material. * * @param bytes A byte array containing the DES key material. * @param offset The offset in the given byte array at which * the 7-byte key material starts. * * @return A DES encryption key created from the key material * starting at the specified offset in the given byte array. */ private static Key createDESKey(byte[] bytes, int offset) { byte[] keyBytes = new byte[7]; System.arraycopy(bytes, offset, keyBytes, 0, 7); byte[] material = new byte[8]; material[0] = keyBytes[0]; material[1] = (byte) (keyBytes[0] << 7 | (keyBytes[1] & 0xff) >>> 1); material[2] = (byte) (keyBytes[1] << 6 | (keyBytes[2] & 0xff) >>> 2); material[3] = (byte) (keyBytes[2] << 5 | (keyBytes[3] & 0xff) >>> 3); material[4] = (byte) (keyBytes[3] << 4 | (keyBytes[4] & 0xff) >>> 4); material[5] = (byte) (keyBytes[4] << 3 | (keyBytes[5] & 0xff) >>> 5); material[6] = (byte) (keyBytes[5] << 2 | (keyBytes[6] & 0xff) >>> 6); material[7] = (byte) (keyBytes[6] << 1); oddParity(material); return new SecretKeySpec(material, "DES"); } /** * Applies odd parity to the given byte array. * * @param bytes The data whose parity bits are to be adjusted for * odd parity. */ private static void oddParity(byte[] bytes) { for (int i = 0; i < bytes.length; i++) { byte b = bytes[i]; boolean needsParity = (((b >>> 7) ^ (b >>> 6) ^ (b >>> 5) ^ (b >>> 4) ^ (b >>> 3) ^ (b >>> 2) ^ (b >>> 1)) & 0x01) == 0; if (needsParity) { bytes[i] |= (byte) 0x01; } else { bytes[i] &= (byte) 0xfe; } } } }././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/ntlm/NTLMUtilities.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/ntlm/NTLMUtilities.0000644000175000017500000004447712032276021032442 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.http.ntlm; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.util.StringTokenizer; import org.apache.mina.proxy.utils.ByteUtilities; /** * NTLMUtilities.java - NTLM functions used for authentication and unit testing. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class NTLMUtilities implements NTLMConstants { /** * @see #writeSecurityBuffer(short, short, int, byte[], int) */ public final static byte[] writeSecurityBuffer(short length, int bufferOffset) { byte[] b = new byte[8]; writeSecurityBuffer(length, length, bufferOffset, b, 0); return b; } /** * Writes a security buffer to the given array b at offset * offset. A security buffer defines a pointer to an area * in the data that defines some data with a variable length. This allows * to have a semi-fixed length header thus making a little bit easier * the decoding process in the NTLM protocol. * * @param length the length of the security buffer * @param allocated the allocated space for the security buffer (should be * greater or equal to length * @param bufferOffset the offset from the main array where the currently * defined security buffer will be written * @param b the buffer in which we write the security buffer * @param offset the offset at which to write to the b buffer */ public final static void writeSecurityBuffer(short length, short allocated, int bufferOffset, byte[] b, int offset) { ByteUtilities.writeShort(length, b, offset); ByteUtilities.writeShort(allocated, b, offset + 2); ByteUtilities.writeInt(bufferOffset, b, offset + 4); } /** * Writes the Windows OS version passed in as three byte values * (majorVersion.minorVersion.buildNumber) to the given byte array * at offset. * * @param majorVersion the major version number * @param minorVersion the minor version number * @param buildNumber the build number * @param b the target byte array * @param offset the offset at which to write in the array */ public final static void writeOSVersion(byte majorVersion, byte minorVersion, short buildNumber, byte[] b, int offset) { b[offset] = majorVersion; b[offset + 1] = minorVersion; b[offset + 2] = (byte) buildNumber; b[offset + 3] = (byte) (buildNumber >> 8); b[offset + 4] = 0; b[offset + 5] = 0; b[offset + 6] = 0; b[offset + 7] = 0x0F; } /** * Tries to return a valid OS version on Windows systems. If it fails to * do so or if we're running on another OS then a fake Windows XP OS * version is returned because the protocol uses it. * * @return a NTLM OS version byte buffer */ public final static byte[] getOsVersion() { String os = System.getProperty("os.name"); if (os == null || !os.toUpperCase().contains("WINDOWS")) { return DEFAULT_OS_VERSION; } byte[] osVer = new byte[8]; // Let's enclose the code by a try...catch in order to // manage incorrect strings. In this case, we will generate // an exception and deal with the special cases. try { Process pr = Runtime.getRuntime().exec("cmd /C ver"); BufferedReader reader = new BufferedReader(new InputStreamReader(pr.getInputStream())); pr.waitFor(); String line; // We loop as we may have blank lines. do { line = reader.readLine(); } while ((line != null) && (line.length() != 0)); reader.close(); // If line is null, we must not go any farther if (line == null) { // Throw an exception to jump into the catch() part throw new Exception(); } // The command line should return a response like : // Microsoft Windows XP [version 5.1.2600] int pos = line.toLowerCase().indexOf("version"); if (pos == -1) { // Throw an exception to jump into the catch() part throw new Exception(); } pos += 8; line = line.substring(pos, line.indexOf(']')); StringTokenizer tk = new StringTokenizer(line, "."); if (tk.countTokens() != 3) { // Throw an exception to jump into the catch() part throw new Exception(); } writeOSVersion(Byte.parseByte(tk.nextToken()), Byte.parseByte(tk.nextToken()), Short.parseShort(tk.nextToken()), osVer, 0); } catch (Exception ex) { try { String version = System.getProperty("os.version"); writeOSVersion(Byte.parseByte(version.substring(0, 1)), Byte.parseByte(version.substring(2, 3)), (short) 0, osVer, 0); } catch (Exception ex2) { return DEFAULT_OS_VERSION; } } return osVer; } /** * see http://davenport.sourceforge.net/ntlm.html#theType1Message * * @param workStation the workstation name * @param domain the domain name * @param customFlags custom flags, if null then * NTLMConstants.DEFAULT_CONSTANTS is used * @param osVersion the os version of the client, if null then * NTLMConstants.DEFAULT_OS_VERSION is used * @return the type 1 message */ public final static byte[] createType1Message(String workStation, String domain, Integer customFlags, byte[] osVersion) { byte[] msg = null; if (osVersion != null && osVersion.length != 8) { throw new IllegalArgumentException("osVersion parameter should be a 8 byte wide array"); } if (workStation == null || domain == null) { throw new IllegalArgumentException("workStation and domain must be non null"); } int flags = customFlags != null ? customFlags | FLAG_NEGOTIATE_WORKSTATION_SUPPLIED | FLAG_NEGOTIATE_DOMAIN_SUPPLIED : DEFAULT_FLAGS; ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { baos.write(NTLM_SIGNATURE); baos.write(ByteUtilities.writeInt(MESSAGE_TYPE_1)); baos.write(ByteUtilities.writeInt(flags)); byte[] domainData = ByteUtilities.getOEMStringAsByteArray(domain); byte[] workStationData = ByteUtilities.getOEMStringAsByteArray(workStation); int pos = (osVersion != null) ? 40 : 32; baos.write(writeSecurityBuffer((short) domainData.length, pos + workStationData.length)); baos.write(writeSecurityBuffer((short) workStationData.length, pos)); if (osVersion != null) { baos.write(osVersion); } // Order is not mandatory since a pointer is given in the security buffers baos.write(workStationData); baos.write(domainData); msg = baos.toByteArray(); baos.close(); } catch (IOException e) { return null; } return msg; } /** * Writes a security buffer and returns the pointer of the position * where to write the next security buffer. * * @param baos the stream where the security buffer is written * @param len the length of the security buffer * @param pointer the position where the security buffer can be written * @return the position where the next security buffer will be written * @throws IOException if writing to the ByteArrayOutputStream fails */ public final static int writeSecurityBufferAndUpdatePointer(ByteArrayOutputStream baos, short len, int pointer) throws IOException { baos.write(writeSecurityBuffer(len, pointer)); return pointer + len; } /** * Extracts the NTLM challenge from the type 2 message as an 8 byte array. * * @param msg the type 2 message byte array * @return the challenge */ public final static byte[] extractChallengeFromType2Message(byte[] msg) { byte[] challenge = new byte[8]; System.arraycopy(msg, 24, challenge, 0, 8); return challenge; } /** * Extracts the NTLM flags from the type 2 message. * * @param msg the type 2 message byte array * @return the proxy flags as an int */ public final static int extractFlagsFromType2Message(byte[] msg) { byte[] flagsBytes = new byte[4]; System.arraycopy(msg, 20, flagsBytes, 0, 4); ByteUtilities.changeWordEndianess(flagsBytes, 0, 4); return ByteUtilities.makeIntFromByte4(flagsBytes); } /** * Reads the byte array described by the security buffer stored at the * securityBufferOffset offset. * * @param msg the message where to read the security buffer and it's value * @param securityBufferOffset the offset at which to read the security buffer * @return a new byte array holding the data pointed by the security buffer */ public final static byte[] readSecurityBufferTarget(byte[] msg, int securityBufferOffset) { byte[] securityBuffer = new byte[8]; System.arraycopy(msg, securityBufferOffset, securityBuffer, 0, 8); ByteUtilities.changeWordEndianess(securityBuffer, 0, 8); int length = ByteUtilities.makeIntFromByte2(securityBuffer); int offset = ByteUtilities.makeIntFromByte4(securityBuffer, 4); byte[] secBufValue = new byte[length]; System.arraycopy(msg, offset, secBufValue, 0, length); return secBufValue; } /** * Extracts the target name from the type 2 message. * * @param msg the type 2 message byte array * @param msgFlags the flags if null then flags are extracted from the * type 2 message * @return the target name * @throws UnsupportedEncodingException if unable to use the * needed UTF-16LE or ASCII charsets */ public final static String extractTargetNameFromType2Message(byte[] msg, Integer msgFlags) throws UnsupportedEncodingException { // Read the security buffer to determine where the target name // is stored and what it's length is byte[] targetName = readSecurityBufferTarget(msg, 12); // now we convert it to a string int flags = msgFlags == null ? extractFlagsFromType2Message(msg) : msgFlags; if (ByteUtilities.isFlagSet(flags, FLAG_NEGOTIATE_UNICODE)) { return new String(targetName, "UTF-16LE"); } return new String(targetName, "ASCII"); } /** * Extracts the target information block from the type 2 message. * * @param msg the type 2 message byte array * @param msgFlags the flags if null then flags are extracted from the * type 2 message * @return the target info */ public final static byte[] extractTargetInfoFromType2Message(byte[] msg, Integer msgFlags) { int flags = msgFlags == null ? extractFlagsFromType2Message(msg) : msgFlags; if (!ByteUtilities.isFlagSet(flags, FLAG_NEGOTIATE_TARGET_INFO)) return null; int pos = 40; //isFlagSet(flags, FLAG_NEGOTIATE_LOCAL_CALL) ? 40 : 32; return readSecurityBufferTarget(msg, pos); } /** * Prints to the {@link PrintWriter} the target information block extracted * from the type 2 message. * * @param msg the type 2 message * @param msgFlags the flags if null then flags are extracted from the * type 2 message * @param out the output target for the information * @throws UnsupportedEncodingException if unable to use the * needed UTF-16LE or ASCII charsets */ public final static void printTargetInformationBlockFromType2Message(byte[] msg, Integer msgFlags, PrintWriter out) throws UnsupportedEncodingException { int flags = msgFlags == null ? extractFlagsFromType2Message(msg) : msgFlags; byte[] infoBlock = extractTargetInfoFromType2Message(msg, flags); if (infoBlock == null) { out.println("No target information block found !"); } else { int pos = 0; while (infoBlock[pos] != 0) { out.print("---\nType " + infoBlock[pos] + ": "); switch (infoBlock[pos]) { case 1: out.println("Server name"); break; case 2: out.println("Domain name"); break; case 3: out.println("Fully qualified DNS hostname"); break; case 4: out.println("DNS domain name"); break; case 5: out.println("Parent DNS domain name"); break; } byte[] len = new byte[2]; System.arraycopy(infoBlock, pos + 2, len, 0, 2); ByteUtilities.changeByteEndianess(len, 0, 2); int length = ByteUtilities.makeIntFromByte2(len, 0); out.println("Length: " + length + " bytes"); out.print("Data: "); if (ByteUtilities.isFlagSet(flags, FLAG_NEGOTIATE_UNICODE)) { out.println(new String(infoBlock, pos + 4, length, "UTF-16LE")); } else { out.println(new String(infoBlock, pos + 4, length, "ASCII")); } pos += 4 + length; out.flush(); } } } /** * @see http://davenport.sourceforge.net/ntlm.html#theType3Message * * @param user the user name * @param password the user password * @param challenge the challenge response * @param target the target name * @param workstation the client workstation's name * @param serverFlags the flags set by the client * @param osVersion the os version of the client * @return the type 3 message */ public final static byte[] createType3Message(String user, String password, byte[] challenge, String target, String workstation, Integer serverFlags, byte[] osVersion) { byte[] msg = null; if (challenge == null || challenge.length != 8) { throw new IllegalArgumentException("challenge[] should be a 8 byte wide array"); } if (osVersion != null && osVersion.length != 8) { throw new IllegalArgumentException("osVersion should be a 8 byte wide array"); } //TOSEE breaks tests /*int flags = serverFlags != null ? serverFlags | FLAG_NEGOTIATE_WORKSTATION_SUPPLIED | FLAG_NEGOTIATE_DOMAIN_SUPPLIED : DEFAULT_FLAGS;*/ int flags = serverFlags != null ? serverFlags : DEFAULT_FLAGS; ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { baos.write(NTLM_SIGNATURE); baos.write(ByteUtilities.writeInt(MESSAGE_TYPE_3)); byte[] dataLMResponse = NTLMResponses.getLMResponse(password, challenge); byte[] dataNTLMResponse = NTLMResponses.getNTLMResponse(password, challenge); boolean useUnicode = ByteUtilities.isFlagSet(flags, FLAG_NEGOTIATE_UNICODE); byte[] targetName = ByteUtilities.encodeString(target, useUnicode); byte[] userName = ByteUtilities.encodeString(user, useUnicode); byte[] workstationName = ByteUtilities.encodeString(workstation, useUnicode); int pos = osVersion != null ? 72 : 64; int responsePos = pos + targetName.length + userName.length + workstationName.length; responsePos = writeSecurityBufferAndUpdatePointer(baos, (short) dataLMResponse.length, responsePos); writeSecurityBufferAndUpdatePointer(baos, (short) dataNTLMResponse.length, responsePos); pos = writeSecurityBufferAndUpdatePointer(baos, (short) targetName.length, pos); pos = writeSecurityBufferAndUpdatePointer(baos, (short) userName.length, pos); writeSecurityBufferAndUpdatePointer(baos, (short) workstationName.length, pos); /** LM/LMv2 Response security buffer 20 NTLM/NTLMv2 Response security buffer 28 Target Name security buffer 36 User Name security buffer 44 Workstation Name security buffer (52) Session Key (optional) security buffer (60) Flags (optional) long (64) OS Version Structure (Optional) 8 bytes **/ // Session Key Security Buffer ??! baos.write(new byte[] { 0, 0, 0, 0, (byte) 0x9a, 0, 0, 0 }); baos.write(ByteUtilities.writeInt(flags)); if (osVersion != null) { baos.write(osVersion); } // Order is not mandatory since a pointer is given in the security buffers baos.write(targetName); baos.write(userName); baos.write(workstationName); baos.write(dataLMResponse); baos.write(dataNTLMResponse); msg = baos.toByteArray(); baos.close(); } catch (Exception e) { e.printStackTrace(); return null; } return msg; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/ntlm/NTLMConstants.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/ntlm/NTLMConstants.0000644000175000017500000001761712032276021032437 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.http.ntlm; /** * NTLMConstants.java - All NTLM constants. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public interface NTLMConstants { // Signature "NTLMSSP"+{0} public final static byte[] NTLM_SIGNATURE = new byte[] { 0x4E, 0x54, 0x4C, 0x4D, 0x53, 0x53, 0x50, 0 }; // Version 5.1.2600 a Windows XP version (ex: Build 2600.xpsp_sp2_gdr.050301-1519 : Service Pack 2) public final static byte[] DEFAULT_OS_VERSION = new byte[] { 0x05, 0x01, 0x28, 0x0A, 0, 0, 0, 0x0F }; /** * Message types */ public final static int MESSAGE_TYPE_1 = 1; public final static int MESSAGE_TYPE_2 = 2; public final static int MESSAGE_TYPE_3 = 3; /** * Message flags */ // Indicates that Unicode strings are supported for use in security buffer data public final static int FLAG_NEGOTIATE_UNICODE = 0x00000001; // Indicates that OEM strings are supported for use in security buffer data public final static int FLAG_NEGOTIATE_OEM = 0x00000002; // Requests that the server's authentication realm be included in the Type 2 message public final static int FLAG_REQUEST_SERVER_AUTH_REALM = 0x00000004; // Specifies that authenticated communication between the client // and server should carry a digital signature (message integrity) public final static int FLAG_NEGOTIATE_SIGN = 0x00000010; // Specifies that authenticated communication between the client // and server should be encrypted (message confidentiality) public final static int FLAG_NEGOTIATE_SEAL = 0x00000020; // Indicates that datagram authentication is being used public final static int FLAG_NEGOTIATE_DATAGRAM_STYLE = 0x00000040; // Indicates that the Lan Manager Session Key should be used for signing and // sealing authenticated communications public final static int FLAG_NEGOTIATE_LAN_MANAGER_KEY = 0x00000080; // Indicates that NTLM authentication is being used public final static int FLAG_NEGOTIATE_NTLM = 0x00000200; // Sent by the client in the Type 3 message to indicate that an anonymous context // has been established. This also affects the response fields public final static int FLAG_NEGOTIATE_ANONYMOUS = 0x00000800; // Sent by the client in the Type 1 message to indicate that the name of the domain in which // the client workstation has membership is included in the message. This is used by the // server to determine whether the client is eligible for local authentication public final static int FLAG_NEGOTIATE_DOMAIN_SUPPLIED = 0x00001000; // Sent by the client in the Type 1 message to indicate that the client workstation's name // is included in the message. This is used by the server to determine whether the client // is eligible for local authentication public final static int FLAG_NEGOTIATE_WORKSTATION_SUPPLIED = 0x00002000; // Sent by the server to indicate that the server and client are on the same machine. // Implies that the client may use the established local credentials for authentication // instead of calculating a response to the challenge public final static int FLAG_NEGOTIATE_LOCAL_CALL = 0x00004000; // Indicates that authenticated communication between the client and server should // be signed with a "dummy" signature public final static int FLAG_NEGOTIATE_ALWAYS_SIGN = 0x00008000; // Sent by the server in the Type 2 message to indicate that the target authentication // realm is a domain public final static int FLAG_TARGET_TYPE_DOMAIN = 0x00010000; // Sent by the server in the Type 2 message to indicate that the target authentication // realm is a server public final static int FLAG_TARGET_TYPE_SERVER = 0x00020000; // Sent by the server in the Type 2 message to indicate that the target authentication // realm is a share. Presumably, this is for share-level authentication. Usage is unclear public final static int FLAG_TARGET_TYPE_SHARE = 0x00040000; // Indicates that the NTLM2 signing and sealing scheme should be used for protecting // authenticated communications. Note that this refers to a particular session security // scheme, and is not related to the use of NTLMv2 authentication. This flag can, however, // have an effect on the response calculations public final static int FLAG_NEGOTIATE_NTLM2 = 0x00080000; // Sent by the server in the Type 2 message to indicate that it is including a Target // Information block in the message. The Target Information block is used in the // calculation of the NTLMv2 response public final static int FLAG_NEGOTIATE_TARGET_INFO = 0x00800000; // Indicates that 128-bit encryption is supported public final static int FLAG_NEGOTIATE_128_BIT_ENCRYPTION = 0x20000000; // Indicates that the client will provide an encrypted master key in the "Session Key" // field of the Type 3 message public final static int FLAG_NEGOTIATE_KEY_EXCHANGE = 0x40000000; // Indicates that 56-bit encryption is supported public final static int FLAG_NEGOTIATE_56_BIT_ENCRYPTION = 0x80000000; // WARN : These flags usage has not been identified public final static int FLAG_UNIDENTIFIED_1 = 0x00000008; public final static int FLAG_UNIDENTIFIED_2 = 0x00000100; // Negotiate Netware ??! public final static int FLAG_UNIDENTIFIED_3 = 0x00000400; public final static int FLAG_UNIDENTIFIED_4 = 0x00100000; // Request Init Response ??! public final static int FLAG_UNIDENTIFIED_5 = 0x00200000; // Request Accept Response ??! public final static int FLAG_UNIDENTIFIED_6 = 0x00400000; // Request Non-NT Session Key ??! public final static int FLAG_UNIDENTIFIED_7 = 0x01000000; public final static int FLAG_UNIDENTIFIED_8 = 0x02000000; public final static int FLAG_UNIDENTIFIED_9 = 0x04000000; public final static int FLAG_UNIDENTIFIED_10 = 0x08000000; public final static int FLAG_UNIDENTIFIED_11 = 0x10000000; // Default minimal flag set public final static int DEFAULT_FLAGS = FLAG_NEGOTIATE_OEM | FLAG_NEGOTIATE_UNICODE | FLAG_NEGOTIATE_WORKSTATION_SUPPLIED | FLAG_NEGOTIATE_DOMAIN_SUPPLIED; /** * Target Information sub blocks types. It may be that there are other * as-yet-unidentified sub block types as well. */ // Sub block terminator public final static short TARGET_INFORMATION_SUBBLOCK_TERMINATOR_TYPE = 0x0000; // Server name public final static short TARGET_INFORMATION_SUBBLOCK_SERVER_TYPE = 0x0100; // Domain name public final static short TARGET_INFORMATION_SUBBLOCK_DOMAIN_TYPE = 0x0200; // Fully-qualified DNS host name (i.e., server.domain.com) public final static short TARGET_INFORMATION_SUBBLOCK_FQDNS_HOSTNAME_TYPE = 0x0300; // DNS domain name (i.e., domain.com) public final static short TARGET_INFORMATION_SUBBLOCK_DNS_DOMAIN_NAME_TYPE = 0x0400; // Apparently the "parent" DNS domain for servers in sub domains public final static short TARGET_INFORMATION_SUBBLOCK_PARENT_DNS_DOMAIN_NAME_TYPE = 0x0500; }././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/ntlm/HttpNTLMAuthLogicHandler.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/ntlm/HttpNTLMAuthLo0000644000175000017500000001424312032276021032431 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.http.ntlm; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.proxy.ProxyAuthException; import org.apache.mina.proxy.handlers.http.AbstractAuthLogicHandler; import org.apache.mina.proxy.handlers.http.HttpProxyConstants; import org.apache.mina.proxy.handlers.http.HttpProxyRequest; import org.apache.mina.proxy.handlers.http.HttpProxyResponse; import org.apache.mina.proxy.session.ProxyIoSession; import org.apache.mina.proxy.utils.StringUtilities; import org.apache.mina.util.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * HttpNTLMAuthLogicHandler.java - HTTP NTLM authentication mechanism logic handler. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class HttpNTLMAuthLogicHandler extends AbstractAuthLogicHandler { private final static Logger LOGGER = LoggerFactory.getLogger(HttpNTLMAuthLogicHandler.class); /** * The challenge provided by the server. */ private byte[] challengePacket = null; /** * {@inheritDoc} */ public HttpNTLMAuthLogicHandler(final ProxyIoSession proxyIoSession) throws ProxyAuthException { super(proxyIoSession); ((HttpProxyRequest) request).checkRequiredProperties(HttpProxyConstants.USER_PROPERTY, HttpProxyConstants.PWD_PROPERTY, HttpProxyConstants.DOMAIN_PROPERTY, HttpProxyConstants.WORKSTATION_PROPERTY); } /** * {@inheritDoc} */ @Override public void doHandshake(NextFilter nextFilter) throws ProxyAuthException { LOGGER.debug(" doHandshake()"); if (step > 0 && challengePacket == null) { throw new IllegalStateException("NTLM Challenge packet not received"); } HttpProxyRequest req = (HttpProxyRequest) request; Map> headers = req.getHeaders() != null ? req.getHeaders() : new HashMap>(); String domain = req.getProperties().get(HttpProxyConstants.DOMAIN_PROPERTY); String workstation = req.getProperties().get(HttpProxyConstants.WORKSTATION_PROPERTY); if (step > 0) { LOGGER.debug(" sending NTLM challenge response"); byte[] challenge = NTLMUtilities.extractChallengeFromType2Message(challengePacket); int serverFlags = NTLMUtilities.extractFlagsFromType2Message(challengePacket); String username = req.getProperties().get(HttpProxyConstants.USER_PROPERTY); String password = req.getProperties().get(HttpProxyConstants.PWD_PROPERTY); byte[] authenticationPacket = NTLMUtilities.createType3Message(username, password, challenge, domain, workstation, serverFlags, null); StringUtilities.addValueToHeader(headers, "Proxy-Authorization", "NTLM " + new String(Base64.encodeBase64(authenticationPacket)), true); } else { LOGGER.debug(" sending NTLM negotiation packet"); byte[] negotiationPacket = NTLMUtilities.createType1Message(workstation, domain, null, null); StringUtilities.addValueToHeader(headers, "Proxy-Authorization", "NTLM " + new String(Base64.encodeBase64(negotiationPacket)), true); } addKeepAliveHeaders(headers); req.setHeaders(headers); writeRequest(nextFilter, req); step++; } /** * Returns the value of the NTLM Proxy-Authenticate header. * * @param response the proxy response */ private String getNTLMHeader(final HttpProxyResponse response) { List values = response.getHeaders().get("Proxy-Authenticate"); for (String s : values) { if (s.startsWith("NTLM")) { return s; } } return null; } /** * {@inheritDoc} */ @Override public void handleResponse(final HttpProxyResponse response) throws ProxyAuthException { if (step == 0) { String challengeResponse = getNTLMHeader(response); step = 1; if (challengeResponse == null || challengeResponse.length() < 5) { // Nothing to handle at this step. // Just need to send a reply type 1 message in doHandshake(). return; } // else there was no step 0 so continue to step 1. } if (step == 1) { // Header should look like : // Proxy-Authenticate: NTLM still_some_more_stuff String challengeResponse = getNTLMHeader(response); if (challengeResponse == null || challengeResponse.length() < 5) { throw new ProxyAuthException("Unexpected error while reading server challenge !"); } try { challengePacket = Base64.decodeBase64(challengeResponse.substring(5).getBytes( proxyIoSession.getCharsetName())); } catch (IOException e) { throw new ProxyAuthException("Unable to decode the base64 encoded NTLM challenge", e); } step = 2; } else { throw new ProxyAuthException("Received unexpected response code (" + response.getStatusLine() + ")."); } } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/AbstractHttpLogicHandler.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/AbstractHttpLogicHa0000644000175000017500000003500412032276021032560 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.http; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionInitializer; import org.apache.mina.proxy.AbstractProxyLogicHandler; import org.apache.mina.proxy.ProxyAuthException; import org.apache.mina.proxy.session.ProxyIoSession; import org.apache.mina.proxy.utils.IoBufferDecoder; import org.apache.mina.proxy.utils.StringUtilities; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * AbstractHttpLogicHandler.java - Base class for HTTP proxy {@link AbstractProxyLogicHandler} implementations. * Provides HTTP request encoding/response decoding functionality. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public abstract class AbstractHttpLogicHandler extends AbstractProxyLogicHandler { private final static Logger LOGGER = LoggerFactory.getLogger(AbstractHttpLogicHandler.class); private final static String DECODER = AbstractHttpLogicHandler.class.getName() + ".Decoder"; private final static byte[] HTTP_DELIMITER = new byte[] { '\r', '\n', '\r', '\n' }; private final static byte[] CRLF_DELIMITER = new byte[] { '\r', '\n' }; // Parsing vars /** * Temporary buffer to accumulate the HTTP response from the proxy. */ private IoBuffer responseData = null; /** * The parsed http proxy response */ private HttpProxyResponse parsedResponse = null; /** * The content length of the proxy response. */ private int contentLength = -1; // HTTP/1.1 vars /** * A flag that indicates that this is a HTTP/1.1 response with chunked data.and that some chunks are missing. */ private boolean hasChunkedData; /** * A flag that indicates that some chunks of data are missing to complete the HTTP/1.1 response. */ private boolean waitingChunkedData; /** * A flag that indicates that chunked data has been read and that we're now reading the footers. */ private boolean waitingFooters; /** * Contains the position of the entity body start in the responseData {@link IoBuffer}. */ private int entityBodyStartPosition; /** * Contains the limit of the entity body start in the responseData {@link IoBuffer}. */ private int entityBodyLimitPosition; /** * Creates a new {@link AbstractHttpLogicHandler}. * * @param proxyIoSession the {@link ProxyIoSession} in use. * @param request the requested url to negotiate with the proxy. */ public AbstractHttpLogicHandler(final ProxyIoSession proxyIoSession) { super(proxyIoSession); } /** * Handles incoming data during the handshake process. Should consume only the * handshake data from the buffer, leaving any extra data in place. * * @param nextFilter the next filter * @param buf the buffer holding received data */ public synchronized void messageReceived(final NextFilter nextFilter, final IoBuffer buf) throws ProxyAuthException { LOGGER.debug(" messageReceived()"); IoBufferDecoder decoder = (IoBufferDecoder) getSession().getAttribute(DECODER); if (decoder == null) { decoder = new IoBufferDecoder(HTTP_DELIMITER); getSession().setAttribute(DECODER, decoder); } try { if (parsedResponse == null) { responseData = decoder.decodeFully(buf); if (responseData == null) { return; } // Handle the response String responseHeader = responseData.getString(getProxyIoSession().getCharset().newDecoder()); entityBodyStartPosition = responseData.position(); LOGGER.debug(" response header received:\n{}", responseHeader.replace("\r", "\\r").replace("\n", "\\n\n")); // Parse the response parsedResponse = decodeResponse(responseHeader); // Is handshake complete ? if (parsedResponse.getStatusCode() == 200 || (parsedResponse.getStatusCode() >= 300 && parsedResponse.getStatusCode() <= 307)) { buf.position(0); setHandshakeComplete(); return; } String contentLengthHeader = StringUtilities.getSingleValuedHeader(parsedResponse.getHeaders(), "Content-Length"); if (contentLengthHeader == null) { contentLength = 0; } else { contentLength = Integer.parseInt(contentLengthHeader.trim()); decoder.setContentLength(contentLength, true); } } if (!hasChunkedData) { if (contentLength > 0) { IoBuffer tmp = decoder.decodeFully(buf); if (tmp == null) { return; } responseData.setAutoExpand(true); responseData.put(tmp); contentLength = 0; } if ("chunked".equalsIgnoreCase(StringUtilities.getSingleValuedHeader(parsedResponse.getHeaders(), "Transfer-Encoding"))) { // Handle Transfer-Encoding: Chunked LOGGER.debug("Retrieving additional http response chunks"); hasChunkedData = true; waitingChunkedData = true; } } if (hasChunkedData) { // Read chunks while (waitingChunkedData) { if (contentLength == 0) { decoder.setDelimiter(CRLF_DELIMITER, false); IoBuffer tmp = decoder.decodeFully(buf); if (tmp == null) { return; } String chunkSize = tmp.getString(getProxyIoSession().getCharset().newDecoder()); int pos = chunkSize.indexOf(';'); if (pos >= 0) { chunkSize = chunkSize.substring(0, pos); } else { chunkSize = chunkSize.substring(0, chunkSize.length() - 2); } contentLength = Integer.decode("0x" + chunkSize); if (contentLength > 0) { contentLength += 2; // also read chunk's trailing CRLF decoder.setContentLength(contentLength, true); } } if (contentLength == 0) { waitingChunkedData = false; waitingFooters = true; entityBodyLimitPosition = responseData.position(); break; } IoBuffer tmp = decoder.decodeFully(buf); if (tmp == null) { return; } contentLength = 0; responseData.put(tmp); buf.position(buf.position()); } // Read footers while (waitingFooters) { decoder.setDelimiter(CRLF_DELIMITER, false); IoBuffer tmp = decoder.decodeFully(buf); if (tmp == null) { return; } if (tmp.remaining() == 2) { waitingFooters = false; break; } // add footer to headers String footer = tmp.getString(getProxyIoSession().getCharset().newDecoder()); String[] f = footer.split(":\\s?", 2); StringUtilities.addValueToHeader(parsedResponse.getHeaders(), f[0], f[1], false); responseData.put(tmp); responseData.put(CRLF_DELIMITER); } } responseData.flip(); LOGGER.debug(" end of response received:\n{}", responseData.getString(getProxyIoSession().getCharset().newDecoder())); // Retrieve entity body content responseData.position(entityBodyStartPosition); responseData.limit(entityBodyLimitPosition); parsedResponse.setBody(responseData.getString(getProxyIoSession().getCharset().newDecoder())); // Free the response buffer responseData.free(); responseData = null; handleResponse(parsedResponse); parsedResponse = null; hasChunkedData = false; contentLength = -1; decoder.setDelimiter(HTTP_DELIMITER, true); if (!isHandshakeComplete()) { doHandshake(nextFilter); } } catch (Exception ex) { if (ex instanceof ProxyAuthException) { throw ((ProxyAuthException) ex); } throw new ProxyAuthException("Handshake failed", ex); } } /** * Handles a HTTP response from the proxy server. * * @param response The response. */ public abstract void handleResponse(final HttpProxyResponse response) throws ProxyAuthException; /** * Calls{@link #writeRequest0(NextFilter, HttpProxyRequest)} to write the request. * If needed a reconnection to the proxy is done previously. * * @param nextFilter the next filter * @param request the http request */ public void writeRequest(final NextFilter nextFilter, final HttpProxyRequest request) { ProxyIoSession proxyIoSession = getProxyIoSession(); if (proxyIoSession.isReconnectionNeeded()) { reconnect(nextFilter, request); } else { writeRequest0(nextFilter, request); } } /** * Encodes a HTTP request and sends it to the proxy server. * * @param nextFilter the next filter * @param request the http request */ private void writeRequest0(final NextFilter nextFilter, final HttpProxyRequest request) { try { String data = request.toHttpString(); IoBuffer buf = IoBuffer.wrap(data.getBytes(getProxyIoSession().getCharsetName())); LOGGER.debug(" write:\n{}", data.replace("\r", "\\r").replace("\n", "\\n\n")); writeData(nextFilter, buf); } catch (UnsupportedEncodingException ex) { closeSession("Unable to send HTTP request: ", ex); } } /** * Method to reconnect to the proxy when it decides not to maintain the connection * during handshake. * * @param nextFilter the next filter * @param request the http request */ private void reconnect(final NextFilter nextFilter, final HttpProxyRequest request) { LOGGER.debug("Reconnecting to proxy ..."); final ProxyIoSession proxyIoSession = getProxyIoSession(); // Fires reconnection proxyIoSession.getConnector().connect(new IoSessionInitializer() { public void initializeSession(final IoSession session, ConnectFuture future) { LOGGER.debug("Initializing new session: {}", session); session.setAttribute(ProxyIoSession.PROXY_SESSION, proxyIoSession); proxyIoSession.setSession(session); LOGGER.debug(" setting up proxyIoSession: {}", proxyIoSession); future.addListener(new IoFutureListener() { public void operationComplete(ConnectFuture future) { // Reconnection is done so we send the // request to the proxy proxyIoSession.setReconnectionNeeded(false); writeRequest0(nextFilter, request); } }); } }); } /** * Parse a HTTP response from the proxy server. * * @param response The response string. */ protected HttpProxyResponse decodeResponse(final String response) throws Exception { LOGGER.debug(" parseResponse()"); // Break response into lines String[] responseLines = response.split(HttpProxyConstants.CRLF); // Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF // BUG FIX : Trimed to prevent failures with some proxies that add // extra space chars like "Microsoft-IIS/5.0" ... String[] statusLine = responseLines[0].trim().split(" ", 2); if (statusLine.length < 2) { throw new Exception("Invalid response status line (" + statusLine + "). Response: " + response); } // Status code is 3 digits if (statusLine[1].matches("^\\d\\d\\d")) { throw new Exception("Invalid response code (" + statusLine[1] + "). Response: " + response); } Map> headers = new HashMap>(); for (int i = 1; i < responseLines.length; i++) { String[] args = responseLines[i].split(":\\s?", 2); StringUtilities.addValueToHeader(headers, args[0], args[1], false); } return new HttpProxyResponse(statusLine[0], statusLine[1], headers); } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/AbstractAuthLogicHandler.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/AbstractAuthLogicHa0000644000175000017500000000745212032276021032550 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.http; import java.util.List; import java.util.Map; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.proxy.ProxyAuthException; import org.apache.mina.proxy.handlers.ProxyRequest; import org.apache.mina.proxy.session.ProxyIoSession; import org.apache.mina.proxy.utils.StringUtilities; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * AbstractAuthLogicHandler.java - Abstract class that handles an authentication * mechanism logic. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public abstract class AbstractAuthLogicHandler { private final static Logger logger = LoggerFactory.getLogger(AbstractAuthLogicHandler.class); /** * The request to be handled by the proxy. */ protected ProxyRequest request; /** * Object that contains all the proxy authentication session informations. */ protected ProxyIoSession proxyIoSession; /** * The current handshake step. */ protected int step = 0; /** * Instantiates a handler for the given proxy session. * * @param proxyIoSession the proxy session object * @throws ProxyAuthException */ protected AbstractAuthLogicHandler(final ProxyIoSession proxyIoSession) throws ProxyAuthException { this.proxyIoSession = proxyIoSession; this.request = proxyIoSession.getRequest(); if (this.request == null || !(this.request instanceof HttpProxyRequest)) { throw new IllegalArgumentException("request parameter should be a non null HttpProxyRequest instance"); } } /** * Method called at each step of the handshaking process. * * @param nextFilter the next filter * @throws ProxyAuthException */ public abstract void doHandshake(final NextFilter nextFilter) throws ProxyAuthException; /** * Handles a HTTP response from the proxy server. * * @param response The HTTP response. * @throws ProxyAuthException */ public abstract void handleResponse(final HttpProxyResponse response) throws ProxyAuthException; /** * Sends an HTTP request. * * @param nextFilter the next filter * @param request the request to write * @throws ProxyAuthException */ protected void writeRequest(final NextFilter nextFilter, final HttpProxyRequest request) throws ProxyAuthException { logger.debug(" sending HTTP request"); ((AbstractHttpLogicHandler) proxyIoSession.getHandler()).writeRequest(nextFilter, request); } /** * Try to force proxy connection to be kept alive. * * @param headers the request headers */ public static void addKeepAliveHeaders(Map> headers) { StringUtilities.addValueToHeader(headers, "Keep-Alive", HttpProxyConstants.DEFAULT_KEEP_ALIVE_TIME, true); StringUtilities.addValueToHeader(headers, "Proxy-Connection", "keep-Alive", true); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/digest/0000755000175000017500000000000012162575507030277 5ustar ebourgebourg././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/digest/DigestUtilities.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/digest/DigestUtilit0000644000175000017500000001330012032276017032617 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.http.digest; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; import javax.security.sasl.AuthenticationException; import org.apache.mina.core.session.IoSession; import org.apache.mina.proxy.session.ProxyIoSession; import org.apache.mina.proxy.utils.ByteUtilities; import org.apache.mina.proxy.utils.StringUtilities; /** * DigestUtilities.java - A class supporting the HTTP DIGEST authentication (see RFC 2617). * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class DigestUtilities { public final static String SESSION_HA1 = DigestUtilities.class + ".SessionHA1"; private static MessageDigest md5; static { // Initialize secure random generator try { md5 = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } } /** * The supported qualities of protections. */ public final static String[] SUPPORTED_QOPS = new String[] { "auth", "auth-int" }; /** * Computes the response to the DIGEST challenge. * * @param session the current session * @param map the map holding the directives sent by the proxy * @param method the HTTP verb * @param pwd the password * @param charsetName the name of the charset used for the challenge * @param body the html body to be hashed for integrity calculations */ public static String computeResponseValue(IoSession session, HashMap map, String method, String pwd, String charsetName, String body) throws AuthenticationException, UnsupportedEncodingException { byte[] hA1; StringBuilder sb; boolean isMD5Sess = "md5-sess".equalsIgnoreCase(StringUtilities.getDirectiveValue(map, "algorithm", false)); if (!isMD5Sess || (session.getAttribute(SESSION_HA1) == null)) { // Build A1 sb = new StringBuilder(); sb.append(StringUtilities.stringTo8859_1(StringUtilities.getDirectiveValue(map, "username", true))).append( ':'); String realm = StringUtilities.stringTo8859_1(StringUtilities.getDirectiveValue(map, "realm", false)); if (realm != null) { sb.append(realm); } sb.append(':').append(pwd); if (isMD5Sess) { byte[] prehA1; synchronized (md5) { md5.reset(); prehA1 = md5.digest(sb.toString().getBytes(charsetName)); } sb = new StringBuilder(); sb.append(ByteUtilities.asHex(prehA1)); sb.append(':').append( StringUtilities.stringTo8859_1(StringUtilities.getDirectiveValue(map, "nonce", true))); sb.append(':').append( StringUtilities.stringTo8859_1(StringUtilities.getDirectiveValue(map, "cnonce", true))); synchronized (md5) { md5.reset(); hA1 = md5.digest(sb.toString().getBytes(charsetName)); } session.setAttribute(SESSION_HA1, hA1); } else { synchronized (md5) { md5.reset(); hA1 = md5.digest(sb.toString().getBytes(charsetName)); } } } else { hA1 = (byte[]) session.getAttribute(SESSION_HA1); } sb = new StringBuilder(method); sb.append(':'); sb.append(StringUtilities.getDirectiveValue(map, "uri", false)); String qop = StringUtilities.getDirectiveValue(map, "qop", false); if ("auth-int".equalsIgnoreCase(qop)) { ProxyIoSession proxyIoSession = (ProxyIoSession) session.getAttribute(ProxyIoSession.PROXY_SESSION); byte[] hEntity; synchronized (md5) { md5.reset(); hEntity = md5.digest(body.getBytes(proxyIoSession.getCharsetName())); } sb.append(':').append(hEntity); } byte[] hA2; synchronized (md5) { md5.reset(); hA2 = md5.digest(sb.toString().getBytes(charsetName)); } sb = new StringBuilder(); sb.append(ByteUtilities.asHex(hA1)); sb.append(':').append(StringUtilities.getDirectiveValue(map, "nonce", true)); sb.append(":00000001:"); sb.append(StringUtilities.getDirectiveValue(map, "cnonce", true)); sb.append(':').append(qop).append(':'); sb.append(ByteUtilities.asHex(hA2)); byte[] hFinal; synchronized (md5) { md5.reset(); hFinal = md5.digest(sb.toString().getBytes(charsetName)); } return ByteUtilities.asHex(hFinal); } }././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/digest/HttpDigestAuthLogicHandler.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/digest/HttpDigestAu0000644000175000017500000002066112032276017032562 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.http.digest; import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.proxy.ProxyAuthException; import org.apache.mina.proxy.handlers.http.AbstractAuthLogicHandler; import org.apache.mina.proxy.handlers.http.HttpProxyConstants; import org.apache.mina.proxy.handlers.http.HttpProxyRequest; import org.apache.mina.proxy.handlers.http.HttpProxyResponse; import org.apache.mina.proxy.session.ProxyIoSession; import org.apache.mina.proxy.utils.StringUtilities; import org.apache.mina.util.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * HttpDigestAuthLogicHandler.java - HTTP Digest authentication mechanism logic handler. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class HttpDigestAuthLogicHandler extends AbstractAuthLogicHandler { private final static Logger logger = LoggerFactory.getLogger(HttpDigestAuthLogicHandler.class); /** * The challenge directives provided by the server. */ private HashMap directives = null; /** * The response received to the last request. */ private HttpProxyResponse response; private static SecureRandom rnd; static { // Initialize secure random generator try { rnd = SecureRandom.getInstance("SHA1PRNG"); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } } public HttpDigestAuthLogicHandler(final ProxyIoSession proxyIoSession) throws ProxyAuthException { super(proxyIoSession); ((HttpProxyRequest) request).checkRequiredProperties(HttpProxyConstants.USER_PROPERTY, HttpProxyConstants.PWD_PROPERTY); } @Override public void doHandshake(NextFilter nextFilter) throws ProxyAuthException { logger.debug(" doHandshake()"); if (step > 0 && directives == null) { throw new ProxyAuthException("Authentication challenge not received"); } HttpProxyRequest req = (HttpProxyRequest) request; Map> headers = req.getHeaders() != null ? req.getHeaders() : new HashMap>(); if (step > 0) { logger.debug(" sending DIGEST challenge response"); // Build a challenge response HashMap map = new HashMap(); map.put("username", req.getProperties().get(HttpProxyConstants.USER_PROPERTY)); StringUtilities.copyDirective(directives, map, "realm"); StringUtilities.copyDirective(directives, map, "uri"); StringUtilities.copyDirective(directives, map, "opaque"); StringUtilities.copyDirective(directives, map, "nonce"); String algorithm = StringUtilities.copyDirective(directives, map, "algorithm"); // Check for a supported algorithm if (algorithm != null && !"md5".equalsIgnoreCase(algorithm) && !"md5-sess".equalsIgnoreCase(algorithm)) { throw new ProxyAuthException("Unknown algorithm required by server"); } // Check for a supported qop String qop = directives.get("qop"); if (qop != null) { StringTokenizer st = new StringTokenizer(qop, ","); String token = null; while (st.hasMoreTokens()) { String tk = st.nextToken(); if ("auth".equalsIgnoreCase(token)) { break; } int pos = Arrays.binarySearch(DigestUtilities.SUPPORTED_QOPS, tk); if (pos > -1) { token = tk; } } if (token != null) { map.put("qop", token); byte[] nonce = new byte[8]; rnd.nextBytes(nonce); try { String cnonce = new String(Base64.encodeBase64(nonce), proxyIoSession.getCharsetName()); map.put("cnonce", cnonce); } catch (UnsupportedEncodingException e) { throw new ProxyAuthException("Unable to encode cnonce", e); } } else { throw new ProxyAuthException("No supported qop option available"); } } map.put("nc", "00000001"); map.put("uri", req.getHttpURI()); // Compute the response try { map.put("response", DigestUtilities.computeResponseValue(proxyIoSession.getSession(), map, req .getHttpVerb().toUpperCase(), req.getProperties().get(HttpProxyConstants.PWD_PROPERTY), proxyIoSession.getCharsetName(), response.getBody())); } catch (Exception e) { throw new ProxyAuthException("Digest response computing failed", e); } // Prepare the challenge response header and add it to the // request we will send StringBuilder sb = new StringBuilder("Digest "); boolean addSeparator = false; for (String key : map.keySet()) { if (addSeparator) { sb.append(", "); } else { addSeparator = true; } boolean quotedValue = !"qop".equals(key) && !"nc".equals(key); sb.append(key); if (quotedValue) { sb.append("=\"").append(map.get(key)).append('\"'); } else { sb.append('=').append(map.get(key)); } } StringUtilities.addValueToHeader(headers, "Proxy-Authorization", sb.toString(), true); } addKeepAliveHeaders(headers); req.setHeaders(headers); writeRequest(nextFilter, req); step++; } @Override public void handleResponse(final HttpProxyResponse response) throws ProxyAuthException { this.response = response; if (step == 0) { if (response.getStatusCode() != 401 && response.getStatusCode() != 407) { throw new ProxyAuthException("Received unexpected response code (" + response.getStatusLine() + ")."); } // Header should look like this // Proxy-Authenticate: Digest still_some_more_stuff List values = response.getHeaders().get("Proxy-Authenticate"); String challengeResponse = null; for (String s : values) { if (s.startsWith("Digest")) { challengeResponse = s; break; } } if (challengeResponse == null) { throw new ProxyAuthException("Server doesn't support digest authentication method !"); } try { directives = StringUtilities.parseDirectives(challengeResponse.substring(7).getBytes( proxyIoSession.getCharsetName())); } catch (Exception e) { throw new ProxyAuthException("Parsing of server digest directives failed", e); } step = 1; } else { throw new ProxyAuthException("Received unexpected response code (" + response.getStatusLine() + ")."); } } }././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/HttpProxyResponse.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/HttpProxyResponse.j0000644000175000017500000000576112032276021032665 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.http; import java.util.List; import java.util.Map; /** * HttpProxyResponse.java - Wrapper class for HTTP requests. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class HttpProxyResponse { /** * The HTTP response protocol version. */ public final String httpVersion; /** * The HTTP response status line. */ public final String statusLine; /** * The HTTP response status code; */ public final int statusCode; /** * The HTTP response headers. */ public final Map> headers; /** * The HTTP response body. */ public String body; /** * Constructor of an HTTP proxy response. * * @param httpVersion the protocol version * @param statusLine the response status line * @param headers the response headers */ protected HttpProxyResponse(final String httpVersion, final String statusLine, final Map> headers) { this.httpVersion = httpVersion; this.statusLine = statusLine; // parses the status code from the status line this.statusCode = statusLine.charAt(0) == ' ' ? Integer.parseInt(statusLine.substring(1, 4)) : Integer .parseInt(statusLine.substring(0, 3)); this.headers = headers; } /** * Returns the HTTP response protocol version. */ public final String getHttpVersion() { return httpVersion; } /** * Returns the HTTP response status code. */ public final int getStatusCode() { return statusCode; } /** * Returns the HTTP response status line. */ public final String getStatusLine() { return statusLine; } /** * Returns the HTTP response body. */ public String getBody() { return body; } /** * Sets the HTTP response body. */ public void setBody(String body) { this.body = body; } /** * Returns the HTTP response headers. */ public final Map> getHeaders() { return headers; } }././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/HttpProxyConstants.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/HttpProxyConstants.0000644000175000017500000000460412032276021032664 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.http; /** * HttpProxyConstants.java - HTTP Proxy constants. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class HttpProxyConstants { /** * The HTTP CONNECT verb. */ public final static String CONNECT = "CONNECT"; /** * The HTTP GET verb. */ public final static String GET = "GET"; /** * The HTTP PUT verb. */ public final static String PUT = "PUT"; /** * The HTTP 1.0 protocol version string. */ public final static String HTTP_1_0 = "HTTP/1.0"; /** * The HTTP 1.1 protocol version string. */ public final static String HTTP_1_1 = "HTTP/1.1"; /** * The CRLF character sequence used in HTTP protocol to end each line. */ public final static String CRLF = "\r\n"; /** * The default keep-alive timeout we set to make proxy * connection persistent. Set to 300 ms. */ public final static String DEFAULT_KEEP_ALIVE_TIME = "300"; // ProxyRequest properties /** * The username property. Used in auth mechs. */ public final static String USER_PROPERTY = "USER"; /** * The password property. Used in auth mechs. */ public final static String PWD_PROPERTY = "PWD"; /** * The domain name property. Used in auth mechs. */ public final static String DOMAIN_PROPERTY = "DOMAIN"; /** * The workstation name property. Used in auth mechs. */ public final static String WORKSTATION_PROPERTY = "WORKSTATION"; }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/basic/0000755000175000017500000000000012162575507030101 5ustar ebourgebourg././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/basic/HttpNoAuthLogicHandler.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/basic/HttpNoAuthLog0000644000175000017500000000456612032276020032517 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.http.basic; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.proxy.ProxyAuthException; import org.apache.mina.proxy.handlers.http.AbstractAuthLogicHandler; import org.apache.mina.proxy.handlers.http.HttpProxyRequest; import org.apache.mina.proxy.handlers.http.HttpProxyResponse; import org.apache.mina.proxy.session.ProxyIoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * HttpNoAuthLogicHandler.java - HTTP 'no auth' mechanism logic handler. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class HttpNoAuthLogicHandler extends AbstractAuthLogicHandler { private final static Logger logger = LoggerFactory.getLogger(HttpNoAuthLogicHandler.class); /** * {@inheritDoc} */ public HttpNoAuthLogicHandler(final ProxyIoSession proxyIoSession) throws ProxyAuthException { super(proxyIoSession); } /** * {@inheritDoc} */ @Override public void doHandshake(final NextFilter nextFilter) throws ProxyAuthException { logger.debug(" doHandshake()"); // Just send the request, no authentication needed writeRequest(nextFilter, (HttpProxyRequest) request); step++; } /** * {@inheritDoc} */ @Override public void handleResponse(final HttpProxyResponse response) throws ProxyAuthException { // Should never get here ! throw new ProxyAuthException("Received error response code (" + response.getStatusLine() + ")."); } }././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/basic/HttpBasicAuthLogicHandler.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/basic/HttpBasicAuth0000644000175000017500000000746012032276020032516 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.http.basic; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.proxy.ProxyAuthException; import org.apache.mina.proxy.handlers.http.AbstractAuthLogicHandler; import org.apache.mina.proxy.handlers.http.HttpProxyConstants; import org.apache.mina.proxy.handlers.http.HttpProxyRequest; import org.apache.mina.proxy.handlers.http.HttpProxyResponse; import org.apache.mina.proxy.session.ProxyIoSession; import org.apache.mina.proxy.utils.StringUtilities; import org.apache.mina.util.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * HttpBasicAuthLogicHandler.java - HTTP Basic authentication mechanism logic handler. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class HttpBasicAuthLogicHandler extends AbstractAuthLogicHandler { private final static Logger logger = LoggerFactory.getLogger(HttpBasicAuthLogicHandler.class); /** * {@inheritDoc} */ public HttpBasicAuthLogicHandler(final ProxyIoSession proxyIoSession) throws ProxyAuthException { super(proxyIoSession); ((HttpProxyRequest) request).checkRequiredProperties(HttpProxyConstants.USER_PROPERTY, HttpProxyConstants.PWD_PROPERTY); } /** * {@inheritDoc} */ @Override public void doHandshake(final NextFilter nextFilter) throws ProxyAuthException { logger.debug(" doHandshake()"); if (step > 0) { throw new ProxyAuthException("Authentication request already sent"); } // Send request HttpProxyRequest req = (HttpProxyRequest) request; Map> headers = req.getHeaders() != null ? req.getHeaders() : new HashMap>(); String username = req.getProperties().get(HttpProxyConstants.USER_PROPERTY); String password = req.getProperties().get(HttpProxyConstants.PWD_PROPERTY); StringUtilities.addValueToHeader(headers, "Proxy-Authorization", "Basic " + createAuthorization(username, password), true); addKeepAliveHeaders(headers); req.setHeaders(headers); writeRequest(nextFilter, req); step++; } /** * Computes the authorization header value. * * @param username the user name * @param password the user password * @return the authorization header value as a string */ public static String createAuthorization(final String username, final String password) { return new String(Base64.encodeBase64((username + ":" + password).getBytes())); } /** * {@inheritDoc} */ @Override public void handleResponse(final HttpProxyResponse response) throws ProxyAuthException { if (response.getStatusCode() != 407) { throw new ProxyAuthException("Received error response code (" + response.getStatusLine() + ")."); } } }././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/HttpAuthenticationMethods.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/HttpAuthenticationM0000644000175000017500000000572112032276021032665 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.http; import org.apache.mina.proxy.ProxyAuthException; import org.apache.mina.proxy.handlers.http.basic.HttpBasicAuthLogicHandler; import org.apache.mina.proxy.handlers.http.basic.HttpNoAuthLogicHandler; import org.apache.mina.proxy.handlers.http.digest.HttpDigestAuthLogicHandler; import org.apache.mina.proxy.handlers.http.ntlm.HttpNTLMAuthLogicHandler; import org.apache.mina.proxy.session.ProxyIoSession; /** * HttpAuthenticationMethods.java - Enumerates all known http authentication methods. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public enum HttpAuthenticationMethods { NO_AUTH(1), BASIC(2), NTLM(3), DIGEST(4); private final int id; private HttpAuthenticationMethods(int id) { this.id = id; } /** * Returns the authentication mechanism id. * @return the id */ public int getId() { return id; } /** * Creates an {@link AbstractAuthLogicHandler} to handle the authentication mechanism. * * @param proxyIoSession the proxy session object * @return a new logic handler */ public AbstractAuthLogicHandler getNewHandler(ProxyIoSession proxyIoSession) throws ProxyAuthException { return getNewHandler(this.id, proxyIoSession); } /** * Creates an {@link AbstractAuthLogicHandler} to handle the authentication mechanism. * * @param method the authentication mechanism to use * @param proxyIoSession the proxy session object * @return a new logic handler */ public static AbstractAuthLogicHandler getNewHandler(int method, ProxyIoSession proxyIoSession) throws ProxyAuthException { if (method == BASIC.id) return new HttpBasicAuthLogicHandler(proxyIoSession); else if (method == DIGEST.id) return new HttpDigestAuthLogicHandler(proxyIoSession); else if (method == NTLM.id) return new HttpNTLMAuthLogicHandler(proxyIoSession); else if (method == NO_AUTH.id) return new HttpNoAuthLogicHandler(proxyIoSession); else return null; } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/HttpProxyRequest.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/HttpProxyRequest.ja0000644000175000017500000002150412032276021032651 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.http; import java.net.InetSocketAddress; import java.net.MalformedURLException; import java.net.URL; import java.util.List; import java.util.Map; import org.apache.mina.proxy.ProxyAuthException; import org.apache.mina.proxy.handlers.ProxyRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * HttpProxyRequest.java - Wrapper class for HTTP requests. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class HttpProxyRequest extends ProxyRequest { private final static Logger logger = LoggerFactory.getLogger(HttpProxyRequest.class); /** * The HTTP verb. */ public final String httpVerb; /** * The HTTP URI. */ public final String httpURI; /** * The HTTP protocol version. */ private String httpVersion; /** * The target hostname. */ private String host; /** * The request headers. */ private Map> headers; /** * The additionnal properties supplied to use with the proxy for * authentication for example. */ private transient Map properties; /** * Constructor which creates a HTTP/1.0 CONNECT request to the specified * endpoint. * * @param endpointAddress the endpoint to connect to */ public HttpProxyRequest(final InetSocketAddress endpointAddress) { this(endpointAddress, HttpProxyConstants.HTTP_1_0, null); } /** * Constructor which creates a CONNECT request to the specified endpoint * using the provided protocol version. * * @param endpointAddress the endpoint to connect to * @param httpVersion the HTTP protocol version */ public HttpProxyRequest(final InetSocketAddress endpointAddress, final String httpVersion) { this(endpointAddress, httpVersion, null); } /** * Constructor which creates a CONNECT request to the specified endpoint * using the provided protocol version and setting the requested headers. * * @param endpointAddress the endpoint to connect to * @param httpVersion the HTTP protocol version * @param headers the additionnal http headers */ public HttpProxyRequest(final InetSocketAddress endpointAddress, final String httpVersion, final Map> headers) { this.httpVerb = HttpProxyConstants.CONNECT; if (!endpointAddress.isUnresolved()) { this.httpURI = endpointAddress.getHostName() + ":" + endpointAddress.getPort(); } else { this.httpURI = endpointAddress.getAddress().getHostAddress() + ":" + endpointAddress.getPort(); } this.httpVersion = httpVersion; this.headers = headers; } /** * Constructor which creates a HTTP/1.0 GET request to the specified * http URI. * * @param httpURI the target URI */ public HttpProxyRequest(final String httpURI) { this(HttpProxyConstants.GET, httpURI, HttpProxyConstants.HTTP_1_0, null); } /** * Constructor which creates a GET request to the specified http URI * using the provided protocol version * * @param httpURI the target URI * @param httpVersion the HTTP protocol version */ public HttpProxyRequest(final String httpURI, final String httpVersion) { this(HttpProxyConstants.GET, httpURI, httpVersion, null); } /** * Constructor which creates a request using the provided HTTP verb targeted at * the specified http URI using the provided protocol version. * * @param httpVerb the HTTP verb to use * @param httpURI the target URI * @param httpVersion the HTTP protocol version */ public HttpProxyRequest(final String httpVerb, final String httpURI, final String httpVersion) { this(httpVerb, httpURI, httpVersion, null); } /** * Constructor which creates a request using the provided HTTP verb targeted at * the specified http URI using the provided protocol version and setting the * requested headers. * * @param httpVerb the HTTP verb to use * @param httpURI the target URI * @param httpVersion the HTTP protocol version * @param headers the additional http headers */ public HttpProxyRequest(final String httpVerb, final String httpURI, final String httpVersion, final Map> headers) { this.httpVerb = httpVerb; this.httpURI = httpURI; this.httpVersion = httpVersion; this.headers = headers; } /** * Returns the HTTP request verb. */ public final String getHttpVerb() { return httpVerb; } /** * Returns the HTTP version. */ public String getHttpVersion() { return httpVersion; } /** * Sets the HTTP version. * * @param httpVersion the HTTP protocol version */ public void setHttpVersion(String httpVersion) { this.httpVersion = httpVersion; } /** * Returns the host to which we are connecting. */ public synchronized final String getHost() { if (host == null) { if (getEndpointAddress() != null && !getEndpointAddress().isUnresolved()) { host = getEndpointAddress().getHostName(); } if (host == null && httpURI != null) { try { host = (new URL(httpURI)).getHost(); } catch (MalformedURLException e) { logger.debug("Malformed URL", e); } } } return host; } /** * Returns the request HTTP URI. */ public final String getHttpURI() { return httpURI; } /** * Returns the HTTP headers. */ public final Map> getHeaders() { return headers; } /** * Set the HTTP headers. */ public final void setHeaders(Map> headers) { this.headers = headers; } /** * Returns additional properties for the request. */ public Map getProperties() { return properties; } /** * Set additional properties for the request. */ public void setProperties(Map properties) { this.properties = properties; } /** * Check if the given property(ies) is(are) set. Otherwise throws a * {@link ProxyAuthException}. */ public void checkRequiredProperties(String... propNames) throws ProxyAuthException { StringBuilder sb = new StringBuilder(); for (String propertyName : propNames) { if (properties.get(propertyName) == null) { sb.append(propertyName).append(' '); } } if (sb.length() > 0) { sb.append("property(ies) missing in request"); throw new ProxyAuthException(sb.toString()); } } /** * Returns the string representation of the HTTP request . */ public String toHttpString() { StringBuilder sb = new StringBuilder(); sb.append(getHttpVerb()).append(' ').append(getHttpURI()).append(' ').append(getHttpVersion()) .append(HttpProxyConstants.CRLF); boolean hostHeaderFound = false; if (getHeaders() != null) { for (Map.Entry> header : getHeaders().entrySet()) { if (!hostHeaderFound) { hostHeaderFound = header.getKey().equalsIgnoreCase("host"); } for (String value : header.getValue()) { sb.append(header.getKey()).append(": ").append(value).append(HttpProxyConstants.CRLF); } } if (!hostHeaderFound && getHttpVersion() == HttpProxyConstants.HTTP_1_1) { sb.append("Host: ").append(getHost()).append(HttpProxyConstants.CRLF); } } sb.append(HttpProxyConstants.CRLF); return sb.toString(); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/socks/0000755000175000017500000000000012162575507027163 5ustar ebourgebourg././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/socks/Socks4LogicHandler.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/socks/Socks4LogicHandler0000644000175000017500000001207312032276022032515 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.socks; import java.util.Arrays; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.proxy.session.ProxyIoSession; import org.apache.mina.proxy.utils.ByteUtilities; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Socks4LogicHandler.java - SOCKS4/SOCKS4a authentication mechanisms logic handler. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class Socks4LogicHandler extends AbstractSocksLogicHandler { private final static Logger logger = LoggerFactory.getLogger(Socks4LogicHandler.class); /** * {@inheritDoc} */ public Socks4LogicHandler(final ProxyIoSession proxyIoSession) { super(proxyIoSession); } /** * Perform the handshake. * * @param nextFilter the next filter */ public void doHandshake(final NextFilter nextFilter) { logger.debug(" doHandshake()"); // Send request writeRequest(nextFilter, request); } /** * Encode a SOCKS4/SOCKS4a request and writes it to the next filter * so it can be sent to the proxy server. * * @param nextFilter the next filter * @param request the request to send. */ protected void writeRequest(final NextFilter nextFilter, final SocksProxyRequest request) { try { boolean isV4ARequest = Arrays.equals(request.getIpAddress(), SocksProxyConstants.FAKE_IP); byte[] userID = request.getUserName().getBytes("ASCII"); byte[] host = isV4ARequest ? request.getHost().getBytes("ASCII") : null; int len = 9 + userID.length; if (isV4ARequest) { len += host.length + 1; } IoBuffer buf = IoBuffer.allocate(len); buf.put(request.getProtocolVersion()); buf.put(request.getCommandCode()); buf.put(request.getPort()); buf.put(request.getIpAddress()); buf.put(userID); buf.put(SocksProxyConstants.TERMINATOR); if (isV4ARequest) { buf.put(host); buf.put(SocksProxyConstants.TERMINATOR); } if (isV4ARequest) { logger.debug(" sending SOCKS4a request"); } else { logger.debug(" sending SOCKS4 request"); } buf.flip(); writeData(nextFilter, buf); } catch (Exception ex) { closeSession("Unable to send Socks request: ", ex); } } /** * Handle incoming data during the handshake process. Should consume only the * handshake data from the buffer, leaving any extra data in place. * * @param nextFilter the next filter * @param buf the server response data buffer */ public void messageReceived(final NextFilter nextFilter, final IoBuffer buf) { try { if (buf.remaining() >= SocksProxyConstants.SOCKS_4_RESPONSE_SIZE) { handleResponse(buf); } } catch (Exception ex) { closeSession("Proxy handshake failed: ", ex); } } /** * Handle a SOCKS4/SOCKS4a response from the proxy server. Test * the response buffer reply code and call {@link #setHandshakeComplete()} * if access is granted. * * @param buf the buffer holding the server response data. * @throws exception if server response is malformed or if request is rejected * by the proxy server. */ protected void handleResponse(final IoBuffer buf) throws Exception { byte first = buf.get(0); if (first != 0) { throw new Exception("Socks response seems to be malformed"); } byte status = buf.get(1); // Consumes all the response data from the buffer buf.position(buf.position() + SocksProxyConstants.SOCKS_4_RESPONSE_SIZE); if (status == SocksProxyConstants.V4_REPLY_REQUEST_GRANTED) { setHandshakeComplete(); } else { throw new Exception("Proxy handshake failed - Code: 0x" + ByteUtilities.asHex(new byte[] { status }) + " (" + SocksProxyConstants.getReplyCodeAsString(status) + ")"); } } }././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/socks/AbstractSocksLogicHandler.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/socks/AbstractSocksLogic0000644000175000017500000000325112032276022032615 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.socks; import org.apache.mina.proxy.AbstractProxyLogicHandler; import org.apache.mina.proxy.session.ProxyIoSession; /** * AbstractSocksLogicHandler.java - Base class for SOCKS {@link AbstractProxyLogicHandler} * implementations. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public abstract class AbstractSocksLogicHandler extends AbstractProxyLogicHandler { /** * The request sent to the proxy. */ protected final SocksProxyRequest request; /** * Creates a new {@link AbstractSocksLogicHandler}. * * @param proxyIoSession the proxy session object */ public AbstractSocksLogicHandler(final ProxyIoSession proxyIoSession) { super(proxyIoSession); this.request = (SocksProxyRequest) proxyIoSession.getRequest(); } }././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/socks/SocksProxyConstants.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/socks/SocksProxyConstant0000644000175000017500000001345512032276022032736 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.socks; /** * SocksProxyConstants.java - SOCKS proxy constants. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class SocksProxyConstants { /** * SOCKS versions field values. */ public final static byte SOCKS_VERSION_4 = 0x04; public final static byte SOCKS_VERSION_5 = 0x05; public final static byte TERMINATOR = 0x00; /** * The size of a server to client response in a SOCKS4/4a negotiation. */ public final static int SOCKS_4_RESPONSE_SIZE = 8; /** * Invalid IP used in SOCKS 4a protocol to specify that the * client can't resolve the destination host's domain name. */ public final static byte[] FAKE_IP = new byte[] { 0, 0, 0, 10 }; /** * Command codes. */ public final static byte ESTABLISH_TCPIP_STREAM = 0x01; public final static byte ESTABLISH_TCPIP_BIND = 0x02; public final static byte ESTABLISH_UDP_ASSOCIATE = 0x03; /** * SOCKS v4/v4a server reply codes. */ public final static byte V4_REPLY_REQUEST_GRANTED = 0x5a; public final static byte V4_REPLY_REQUEST_REJECTED_OR_FAILED = 0x5b; public final static byte V4_REPLY_REQUEST_FAILED_NO_IDENTD = 0x5c; public final static byte V4_REPLY_REQUEST_FAILED_ID_NOT_CONFIRMED = 0x5d; /** * SOCKS v5 server reply codes. */ public final static byte V5_REPLY_SUCCEEDED = 0x00; public final static byte V5_REPLY_GENERAL_FAILURE = 0x01; public final static byte V5_REPLY_NOT_ALLOWED = 0x02; public final static byte V5_REPLY_NETWORK_UNREACHABLE = 0x03; public final static byte V5_REPLY_HOST_UNREACHABLE = 0x04; public final static byte V5_REPLY_CONNECTION_REFUSED = 0x05; public final static byte V5_REPLY_TTL_EXPIRED = 0x06; public final static byte V5_REPLY_COMMAND_NOT_SUPPORTED = 0x07; public final static byte V5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED = 0x08; /** * SOCKS v5 address types. */ public final static byte IPV4_ADDRESS_TYPE = 0x01; public final static byte DOMAIN_NAME_ADDRESS_TYPE = 0x03; public final static byte IPV6_ADDRESS_TYPE = 0x04; /** * SOCKS v5 handshake steps. */ public final static int SOCKS5_GREETING_STEP = 0; public final static int SOCKS5_AUTH_STEP = 1; public final static int SOCKS5_REQUEST_STEP = 2; /** * SOCKS v5 authentication methods. */ public final static byte NO_AUTH = 0x00; public final static byte GSSAPI_AUTH = 0x01; public final static byte BASIC_AUTH = 0x02; public final static byte NO_ACCEPTABLE_AUTH_METHOD = (byte) 0xFF; public final static byte[] SUPPORTED_AUTH_METHODS = new byte[] { NO_AUTH, GSSAPI_AUTH, BASIC_AUTH }; public final static byte BASIC_AUTH_SUBNEGOTIATION_VERSION = 0x01; public final static byte GSSAPI_AUTH_SUBNEGOTIATION_VERSION = 0x01; public final static byte GSSAPI_MSG_TYPE = 0x01; /** * Kerberos providers OID's. */ public final static String KERBEROS_V5_OID = "1.2.840.113554.1.2.2"; public final static String MS_KERBEROS_V5_OID = "1.2.840.48018.1.2.2"; /** * Microsoft NTLM security support provider. */ public final static String NTLMSSP_OID = "1.3.6.1.4.1.311.2.2.10"; /** * Return the string associated with the specified reply code. * * @param code the reply code * @return the reply string */ public final static String getReplyCodeAsString(byte code) { switch (code) { // v4 & v4a codes case V4_REPLY_REQUEST_GRANTED: return "Request granted"; case V4_REPLY_REQUEST_REJECTED_OR_FAILED: return "Request rejected or failed"; case V4_REPLY_REQUEST_FAILED_NO_IDENTD: return "Request failed because client is not running identd (or not reachable from the server)"; case V4_REPLY_REQUEST_FAILED_ID_NOT_CONFIRMED: return "Request failed because client's identd could not confirm the user ID string in the request"; // v5 codes case V5_REPLY_SUCCEEDED: return "Request succeeded"; case V5_REPLY_GENERAL_FAILURE: return "Request failed: general SOCKS server failure"; case V5_REPLY_NOT_ALLOWED: return "Request failed: connection not allowed by ruleset"; case V5_REPLY_NETWORK_UNREACHABLE: return "Request failed: network unreachable"; case V5_REPLY_HOST_UNREACHABLE: return "Request failed: host unreachable"; case V5_REPLY_CONNECTION_REFUSED: return "Request failed: connection refused"; case V5_REPLY_TTL_EXPIRED: return "Request failed: TTL expired"; case V5_REPLY_COMMAND_NOT_SUPPORTED: return "Request failed: command not supported"; case V5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED: return "Request failed: address type not supported"; default: return "Unknown reply code"; } } }././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/socks/Socks5LogicHandler.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/socks/Socks5LogicHandler0000644000175000017500000004152612032276022032523 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.socks; import java.io.UnsupportedEncodingException; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetSocketAddress; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.proxy.session.ProxyIoSession; import org.apache.mina.proxy.utils.ByteUtilities; import org.ietf.jgss.GSSContext; import org.ietf.jgss.GSSException; import org.ietf.jgss.GSSManager; import org.ietf.jgss.GSSName; import org.ietf.jgss.Oid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Socks5LogicHandler.java - SOCKS5 authentication mechanisms logic handler. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class Socks5LogicHandler extends AbstractSocksLogicHandler { private final static Logger LOGGER = LoggerFactory.getLogger(Socks5LogicHandler.class); /** * The selected authentication method attribute key. */ private final static String SELECTED_AUTH_METHOD = Socks5LogicHandler.class.getName() + ".SelectedAuthMethod"; /** * The current step in the handshake attribute key. */ private final static String HANDSHAKE_STEP = Socks5LogicHandler.class.getName() + ".HandshakeStep"; /** * The Java GSS-API context attribute key. */ private final static String GSS_CONTEXT = Socks5LogicHandler.class.getName() + ".GSSContext"; /** * Last GSS token received attribute key. */ private final static String GSS_TOKEN = Socks5LogicHandler.class.getName() + ".GSSToken"; /** * {@inheritDoc} */ public Socks5LogicHandler(final ProxyIoSession proxyIoSession) { super(proxyIoSession); getSession().setAttribute(HANDSHAKE_STEP, SocksProxyConstants.SOCKS5_GREETING_STEP); } /** * Performs the handshake process. * * @param nextFilter the next filter */ public synchronized void doHandshake(final NextFilter nextFilter) { LOGGER.debug(" doHandshake()"); // Send request writeRequest(nextFilter, request, ((Integer) getSession().getAttribute(HANDSHAKE_STEP)).intValue()); } /** * Encodes the initial greeting packet. * * @param request the socks proxy request data * @return the encoded buffer */ private IoBuffer encodeInitialGreetingPacket(final SocksProxyRequest request) { byte nbMethods = (byte) SocksProxyConstants.SUPPORTED_AUTH_METHODS.length; IoBuffer buf = IoBuffer.allocate(2 + nbMethods); buf.put(request.getProtocolVersion()); buf.put(nbMethods); buf.put(SocksProxyConstants.SUPPORTED_AUTH_METHODS); return buf; } /** * Encodes the proxy authorization request packet. * * @param request the socks proxy request data * @return the encoded buffer * @throws UnsupportedEncodingException if request's hostname charset * can't be converted to ASCII. */ private IoBuffer encodeProxyRequestPacket(final SocksProxyRequest request) throws UnsupportedEncodingException { int len = 6; InetSocketAddress adr = request.getEndpointAddress(); byte addressType = 0; byte[] host = null; if (adr != null && !adr.isUnresolved()) { if (adr.getAddress() instanceof Inet6Address) { len += 16; addressType = SocksProxyConstants.IPV6_ADDRESS_TYPE; } else if (adr.getAddress() instanceof Inet4Address) { len += 4; addressType = SocksProxyConstants.IPV4_ADDRESS_TYPE; } } else { host = request.getHost() != null ? request.getHost().getBytes("ASCII") : null; if (host != null) { len += 1 + host.length; addressType = SocksProxyConstants.DOMAIN_NAME_ADDRESS_TYPE; } else { throw new IllegalArgumentException("SocksProxyRequest object " + "has no suitable endpoint information"); } } IoBuffer buf = IoBuffer.allocate(len); buf.put(request.getProtocolVersion()); buf.put(request.getCommandCode()); buf.put((byte) 0x00); // Reserved buf.put(addressType); if (host == null) { buf.put(request.getIpAddress()); } else { buf.put((byte) host.length); buf.put(host); } buf.put(request.getPort()); return buf; } /** * Encodes the authentication packet for supported authentication methods. * * @param request the socks proxy request data * @return the encoded buffer, if null then authentication step is over * and handshake process can jump immediately to the next step without waiting * for a server reply. * @throws UnsupportedEncodingException if some string charset convertion fails * @throws GSSException when something fails while using GSSAPI */ private IoBuffer encodeAuthenticationPacket(final SocksProxyRequest request) throws UnsupportedEncodingException, GSSException { byte method = ((Byte) getSession().getAttribute(Socks5LogicHandler.SELECTED_AUTH_METHOD)).byteValue(); switch (method) { case SocksProxyConstants.NO_AUTH: // In this case authentication is immediately considered as successfull // Next writeRequest() call will send the proxy request getSession().setAttribute(HANDSHAKE_STEP, SocksProxyConstants.SOCKS5_REQUEST_STEP); break; case SocksProxyConstants.GSSAPI_AUTH: return encodeGSSAPIAuthenticationPacket(request); case SocksProxyConstants.BASIC_AUTH: // The basic auth scheme packet is sent byte[] user = request.getUserName().getBytes("ASCII"); byte[] pwd = request.getPassword().getBytes("ASCII"); IoBuffer buf = IoBuffer.allocate(3 + user.length + pwd.length); buf.put(SocksProxyConstants.BASIC_AUTH_SUBNEGOTIATION_VERSION); buf.put((byte) user.length); buf.put(user); buf.put((byte) pwd.length); buf.put(pwd); return buf; } return null; } /** * Encodes the authentication packet for supported authentication methods. * * @param request the socks proxy request data * @return the encoded buffer * @throws GSSException when something fails while using GSSAPI */ private IoBuffer encodeGSSAPIAuthenticationPacket(final SocksProxyRequest request) throws GSSException { GSSContext ctx = (GSSContext) getSession().getAttribute(GSS_CONTEXT); if (ctx == null) { // first step in the authentication process GSSManager manager = GSSManager.getInstance(); GSSName serverName = manager.createName(request.getServiceKerberosName(), null); Oid krb5OID = new Oid(SocksProxyConstants.KERBEROS_V5_OID); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Available mechs:"); for (Oid o : manager.getMechs()) { if (o.equals(krb5OID)) { LOGGER.debug("Found Kerberos V OID available"); } LOGGER.debug("{} with oid = {}", manager.getNamesForMech(o), o); } } ctx = manager.createContext(serverName, krb5OID, null, GSSContext.DEFAULT_LIFETIME); ctx.requestMutualAuth(true); // Mutual authentication ctx.requestConf(false); ctx.requestInteg(false); getSession().setAttribute(GSS_CONTEXT, ctx); } byte[] token = (byte[]) getSession().getAttribute(GSS_TOKEN); if (token != null) { LOGGER.debug(" Received Token[{}] = {}", token.length, ByteUtilities.asHex(token)); } IoBuffer buf = null; if (!ctx.isEstablished()) { // token is ignored on the first call if (token == null) { token = new byte[32]; } token = ctx.initSecContext(token, 0, token.length); // Send a token to the server if one was generated by // initSecContext if (token != null) { LOGGER.debug(" Sending Token[{}] = {}", token.length, ByteUtilities.asHex(token)); getSession().setAttribute(GSS_TOKEN, token); buf = IoBuffer.allocate(4 + token.length); buf.put(new byte[] { SocksProxyConstants.GSSAPI_AUTH_SUBNEGOTIATION_VERSION, SocksProxyConstants.GSSAPI_MSG_TYPE }); buf.put(ByteUtilities.intToNetworkByteOrder(token.length, 2)); buf.put(token); } } return buf; } /** * Encodes a SOCKS5 request and writes it to the next filter * so it can be sent to the proxy server. * * @param nextFilter the next filter * @param request the request to send. * @param step the current step in the handshake process */ private void writeRequest(final NextFilter nextFilter, final SocksProxyRequest request, int step) { try { IoBuffer buf = null; if (step == SocksProxyConstants.SOCKS5_GREETING_STEP) { buf = encodeInitialGreetingPacket(request); } else if (step == SocksProxyConstants.SOCKS5_AUTH_STEP) { // This step can happen multiple times like in GSSAPI auth for instance buf = encodeAuthenticationPacket(request); // If buf is null then go to the next step if (buf == null) { step = SocksProxyConstants.SOCKS5_REQUEST_STEP; } } if (step == SocksProxyConstants.SOCKS5_REQUEST_STEP) { buf = encodeProxyRequestPacket(request); } buf.flip(); writeData(nextFilter, buf); } catch (Exception ex) { closeSession("Unable to send Socks request: ", ex); } } /** * Handles incoming data during the handshake process. Should consume only the * handshake data from the buffer, leaving any extra data in place. * * @param nextFilter the next filter * @param buf the buffered data received */ public synchronized void messageReceived(final NextFilter nextFilter, final IoBuffer buf) { try { int step = ((Integer) getSession().getAttribute(HANDSHAKE_STEP)).intValue(); if (step == SocksProxyConstants.SOCKS5_GREETING_STEP && buf.get(0) != SocksProxyConstants.SOCKS_VERSION_5) { throw new IllegalStateException("Wrong socks version running on server"); } if ((step == SocksProxyConstants.SOCKS5_GREETING_STEP || step == SocksProxyConstants.SOCKS5_AUTH_STEP) && buf.remaining() >= 2) { handleResponse(nextFilter, buf, step); } else if (step == SocksProxyConstants.SOCKS5_REQUEST_STEP && buf.remaining() >= 5) { handleResponse(nextFilter, buf, step); } } catch (Exception ex) { closeSession("Proxy handshake failed: ", ex); } } /** * Handle a SOCKS v5 response from the proxy server. * * @param nextFilter the next filter * @param buf the buffered data received * @param step the current step in the authentication process */ protected void handleResponse(final NextFilter nextFilter, final IoBuffer buf, int step) throws Exception { int len = 2; if (step == SocksProxyConstants.SOCKS5_GREETING_STEP) { // Send greeting message byte method = buf.get(1); if (method == SocksProxyConstants.NO_ACCEPTABLE_AUTH_METHOD) { throw new IllegalStateException("No acceptable authentication method to use with " + "the socks proxy server"); } getSession().setAttribute(SELECTED_AUTH_METHOD, new Byte(method)); } else if (step == SocksProxyConstants.SOCKS5_AUTH_STEP) { // Authentication to the SOCKS server byte method = ((Byte) getSession().getAttribute(Socks5LogicHandler.SELECTED_AUTH_METHOD)).byteValue(); if (method == SocksProxyConstants.GSSAPI_AUTH) { int oldPos = buf.position(); if (buf.get(0) != 0x01) { throw new IllegalStateException("Authentication failed"); } if (buf.get(1) == 0xFF) { throw new IllegalStateException("Authentication failed: GSS API Security Context Failure"); } if (buf.remaining() >= 2) { byte[] size = new byte[2]; buf.get(size); int s = ByteUtilities.makeIntFromByte2(size); if (buf.remaining() >= s) { byte[] token = new byte[s]; buf.get(token); getSession().setAttribute(GSS_TOKEN, token); len = 0; } else { //buf.position(oldPos); return; } } else { buf.position(oldPos); return; } } else if (buf.get(1) != SocksProxyConstants.V5_REPLY_SUCCEEDED) { throw new IllegalStateException("Authentication failed"); } } else if (step == SocksProxyConstants.SOCKS5_REQUEST_STEP) { // Send the request byte addressType = buf.get(3); len = 6; if (addressType == SocksProxyConstants.IPV6_ADDRESS_TYPE) { len += 16; } else if (addressType == SocksProxyConstants.IPV4_ADDRESS_TYPE) { len += 4; } else if (addressType == SocksProxyConstants.DOMAIN_NAME_ADDRESS_TYPE) { len += 1 + (buf.get(4)); } else { throw new IllegalStateException("Unknwon address type"); } if (buf.remaining() >= len) { // handle response byte status = buf.get(1); LOGGER.debug(" response status: {}", SocksProxyConstants.getReplyCodeAsString(status)); if (status == SocksProxyConstants.V5_REPLY_SUCCEEDED) { buf.position(buf.position() + len); setHandshakeComplete(); return; } throw new Exception("Proxy handshake failed - Code: 0x" + ByteUtilities.asHex(new byte[] { status })); } return; } if (len > 0) { buf.position(buf.position() + len); } // Move to the handshaking next step if not in the middle of // the authentication process boolean isAuthenticating = false; if (step == SocksProxyConstants.SOCKS5_AUTH_STEP) { byte method = ((Byte) getSession().getAttribute(Socks5LogicHandler.SELECTED_AUTH_METHOD)).byteValue(); if (method == SocksProxyConstants.GSSAPI_AUTH) { GSSContext ctx = (GSSContext) getSession().getAttribute(GSS_CONTEXT); if (ctx == null || !ctx.isEstablished()) { isAuthenticating = true; } } } if (!isAuthenticating) { getSession().setAttribute(HANDSHAKE_STEP, ++step); } doHandshake(nextFilter); } /** * Closes the session. If any {@link GSSContext} is present in the session * then it is closed. * * @param message the error message */ @Override protected void closeSession(String message) { GSSContext ctx = (GSSContext) getSession().getAttribute(GSS_CONTEXT); if (ctx != null) { try { ctx.dispose(); } catch (GSSException e) { e.printStackTrace(); super.closeSession(message, e); return; } } super.closeSession(message); } }././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/socks/SocksProxyRequest.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/handlers/socks/SocksProxyRequest.0000644000175000017500000001247512032276022032654 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.handlers.socks; import java.net.InetSocketAddress; import org.apache.mina.proxy.handlers.ProxyRequest; /** * SocksProxyRequest.java - Wrapper class for SOCKS requests. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class SocksProxyRequest extends ProxyRequest { /** * The SOCKS protocol version. */ private byte protocolVersion; /** * The command code. */ private byte commandCode; /** * The user name used when authenticating to the proxy server. */ private String userName; /** * The user's password used when authenticating to the proxy server. */ private String password; /** * The SOCKS server host name. */ private String host; /** * The SOCKS server port. */ private int port; /** * The Kerberos service name used in GSSAPI authentication mode. */ private String serviceKerberosName; /** * Constructor used when building a SOCKS4 request. * * @param protocolVersion the protocol version * @param commandCode the command code * @param endpointAddress the endpoint address * @param userName the user name */ public SocksProxyRequest(byte protocolVersion, byte commandCode, InetSocketAddress endpointAddress, String userName) { super(endpointAddress); this.protocolVersion = protocolVersion; this.commandCode = commandCode; this.userName = userName; } /** * Constructor used when building a SOCKS4a request. * * @param commandCode the command code * @param host the server host name * @param port the server port * @param userName the user name */ public SocksProxyRequest(byte commandCode, String host, int port, String userName) { this.protocolVersion = SocksProxyConstants.SOCKS_VERSION_4; this.commandCode = commandCode; this.userName = userName; this.host = host; this.port = port; } /** * Returns the endpoint address resulting from the {@link #getEndpointAddress()}. * If not set, it will return the {@link SocksProxyConstants#FAKE_IP} constant * value which will be ignored in a SOCKS v4 request. * * @return the endpoint address */ public byte[] getIpAddress() { if (getEndpointAddress() == null) { return SocksProxyConstants.FAKE_IP; } return getEndpointAddress().getAddress().getAddress(); } /** * Return the server port as a byte array. * * @return the server port */ public byte[] getPort() { byte[] port = new byte[2]; int p = (getEndpointAddress() == null ? this.port : getEndpointAddress().getPort()); port[1] = (byte) p; port[0] = (byte) (p >> 8); return port; } /** * Return the command code. * * @return the command code */ public byte getCommandCode() { return commandCode; } /** * Return the protocol version. * * @return the protocol version */ public byte getProtocolVersion() { return protocolVersion; } /** * Return the user name. * * @return the user name */ public String getUserName() { return userName; } /** * Return the server host name. * * @return the server host name */ public synchronized final String getHost() { if (host == null) { InetSocketAddress adr = getEndpointAddress(); if (adr != null && !adr.isUnresolved()) { host = getEndpointAddress().getHostName(); } } return host; } /** * Return the user password. * * @return the user password */ public String getPassword() { return password; } /** * Set the user password * * @param password the user password value */ public void setPassword(String password) { this.password = password; } /** * Return the Kerberos service name. * * @return the Kerberos service name */ public String getServiceKerberosName() { return serviceKerberosName; } /** * Set the Kerberos service name. * * @param serviceKerberosName the Kerberos service name */ public void setServiceKerberosName(String serviceKerberosName) { this.serviceKerberosName = serviceKerberosName; } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/utils/0000755000175000017500000000000012162575507025401 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/utils/ByteUtilities.java0000644000175000017500000002446212032276022031035 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.utils; import java.io.UnsupportedEncodingException; /** * ByteUtilities.java - Byte manipulation functions. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class ByteUtilities { /** * Returns the integer represented by up to 4 bytes in network byte order. * * @param buf the buffer to read the bytes from * @param start * @param count * @return */ public static int networkByteOrderToInt(byte[] buf, int start, int count) { if (count > 4) { throw new IllegalArgumentException("Cannot handle more than 4 bytes"); } int result = 0; for (int i = 0; i < count; i++) { result <<= 8; result |= (buf[start + i] & 0xff); } return result; } /** * Encodes an integer into up to 4 bytes in network byte order. * * @param num the int to convert to a byte array * @param count the number of reserved bytes for the write operation * @return the resulting byte array */ public static byte[] intToNetworkByteOrder(int num, int count) { byte[] buf = new byte[count]; intToNetworkByteOrder(num, buf, 0, count); return buf; } /** * Encodes an integer into up to 4 bytes in network byte order in the * supplied buffer starting at start offset and writing * count bytes. * * @param num the int to convert to a byte array * @param buf the buffer to write the bytes to * @param start the offset from beginning for the write operation * @param count the number of reserved bytes for the write operation */ public static void intToNetworkByteOrder(int num, byte[] buf, int start, int count) { if (count > 4) { throw new IllegalArgumentException("Cannot handle more than 4 bytes"); } for (int i = count - 1; i >= 0; i--) { buf[start + i] = (byte) (num & 0xff); num >>>= 8; } } /** * Write a 16 bit short as LITTLE_ENDIAN. * * @param v the short to write */ public final static byte[] writeShort(short v) { return writeShort(v, new byte[2], 0); } /** * Write a 16 bit short as LITTLE_ENDIAN to * the given array b at offset offset. * * @param v the short to write * @param b the byte array to write to * @param offset the offset at which to start writing in the array */ public final static byte[] writeShort(short v, byte[] b, int offset) { b[offset] = (byte) v; b[offset + 1] = (byte) (v >> 8); return b; } /** * Write a 32 bit int as LITTLE_ENDIAN. * * @param v the int to write */ public final static byte[] writeInt(int v) { return writeInt(v, new byte[4], 0); } /** * Write a 32 bit int as LITTLE_ENDIAN to * the given array b at offset offset. * * @param v the int to write * @param b the byte array to write to * @param offset the offset at which to start writing in the array */ public final static byte[] writeInt(int v, byte[] b, int offset) { b[offset] = (byte) v; b[offset + 1] = (byte) (v >> 8); b[offset + 2] = (byte) (v >> 16); b[offset + 3] = (byte) (v >> 24); return b; } /** * Invert the endianness of words (4 bytes) in the given byte array * starting at the given offset and repeating length/4 times. * eg: b0b1b2b3 -> b3b2b1b0 * * @param b the byte array * @param offset the offset at which to change word start * @param length the number of bytes on which to operate * (should be a multiple of 4) */ public final static void changeWordEndianess(byte[] b, int offset, int length) { byte tmp; for (int i = offset; i < offset + length; i += 4) { tmp = b[i]; b[i] = b[i + 3]; b[i + 3] = tmp; tmp = b[i + 1]; b[i + 1] = b[i + 2]; b[i + 2] = tmp; } } /** * Invert two bytes in the given byte array starting at the given * offset and repeating the inversion length/2 times. * eg: b0b1 -> b1b0 * * @param b the byte array * @param offset the offset at which to change word start * @param length the number of bytes on which to operate * (should be a multiple of 2) */ public final static void changeByteEndianess(byte[] b, int offset, int length) { byte tmp; for (int i = offset; i < offset + length; i += 2) { tmp = b[i]; b[i] = b[i + 1]; b[i + 1] = tmp; } } /** * Converts an OEM string as defined in NTLM protocol (eg ASCII charset) * to a byte array. * * @param s the string to convert * @return the result byte array * @throws UnsupportedEncodingException if the string is not an OEM string */ public final static byte[] getOEMStringAsByteArray(String s) throws UnsupportedEncodingException { return s.getBytes("ASCII"); } /** * Converts an UTF-16LE string as defined in NTLM protocol to a byte array. * * @param s the string to convert * @return the result byte array * @throws UnsupportedEncodingException if the string is not an UTF-16LE string */ public final static byte[] getUTFStringAsByteArray(String s) throws UnsupportedEncodingException { return s.getBytes("UTF-16LE"); } /** * Encodes the string to a byte array using UTF-16LE or the ASCII charset * in function of the useUnicode argument. * * @param s the string to encode * @param useUnicode if true then string is encoded to UTF-16LE * otherwise to ASCII * @return the encoded string as a byte array * @throws UnsupportedEncodingException if encoding fails */ public final static byte[] encodeString(String s, boolean useUnicode) throws UnsupportedEncodingException { if (useUnicode) { return getUTFStringAsByteArray(s); } return getOEMStringAsByteArray(s); } /** * Returns a hexadecimal representation of the given byte array. * * @param bytes the array to output to an hex string * @return the hex representation as a string */ public static String asHex(byte[] bytes) { return asHex(bytes, null); } /** * Returns a hexadecimal representation of the given byte array. * * @param bytes the array to output to an hex string * @param separator the separator to use between each byte in the output * string. If null no char is inserted between each byte value. * @return the hex representation as a string */ public static String asHex(byte[] bytes, String separator) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < bytes.length; i++) { String code = Integer.toHexString(bytes[i] & 0xFF); if ((bytes[i] & 0xFF) < 16) { sb.append('0'); } sb.append(code); if (separator != null && i < bytes.length - 1) { sb.append(separator); } } return sb.toString(); } /** * Converts a hex string representation to a byte array. * * @param hex the string holding the hex values * @return the resulting byte array */ public static byte[] asByteArray(String hex) { byte[] bts = new byte[hex.length() / 2]; for (int i = 0; i < bts.length; i++) { bts[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16); } return bts; } /** * Reads an int from 4 bytes of the given array at offset 0. * * @param b the byte array to read * @param offset the offset at which to start * @return the int value */ public static final int makeIntFromByte4(byte[] b) { return makeIntFromByte4(b, 0); } /** * Reads an int from 4 bytes of the given array at the given offset. * * @param b the byte array to read * @param offset the offset at which to start * @return the int value */ public static final int makeIntFromByte4(byte[] b, int offset) { return b[offset] << 24 | (b[offset + 1] & 0xff) << 16 | (b[offset + 2] & 0xff) << 8 | (b[offset + 3] & 0xff); } /** * Reads an int from 2 bytes of the given array at offset 0. * * @param b the byte array to read * @return the int value */ public static final int makeIntFromByte2(byte[] b) { return makeIntFromByte2(b, 0); } /** * Reads an int from 2 bytes of the given array at the given offset. * * @param b the byte array to read * @param offset the offset at which to start * @return the int value */ public static final int makeIntFromByte2(byte[] b, int offset) { return (b[offset] & 0xff) << 8 | (b[offset + 1] & 0xff); } /** * Returns true if the flag testFlag is set in the * flags flagset. * * @param flagset the flagset to test * @param testFlag the flag we search the presence of * @return true if testFlag is present in the flagset, false otherwise. */ public final static boolean isFlagSet(int flagSet, int testFlag) { return (flagSet & testFlag) > 0; } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/utils/StringUtilities.java0000644000175000017500000002737412032276022031405 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.utils; import java.io.ByteArrayOutputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.security.sasl.AuthenticationException; import javax.security.sasl.SaslException; /** * StringUtilities.java - Various methods to handle strings. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class StringUtilities { /** * A directive is a parameter of the digest authentication process. * Returns the value of a directive from the map. If mandatory is true and the * value is null, then it throws an {@link AuthenticationException}. * * @param directivesMap the directive's map * @param directive the name of the directive we want to retrieve * @param mandatory is the directive mandatory * @return the mandatory value as a String * @throws AuthenticationException if mandatory is true and if * directivesMap.get(directive) == null */ public static String getDirectiveValue(HashMap directivesMap, String directive, boolean mandatory) throws AuthenticationException { String value = directivesMap.get(directive); if (value == null) { if (mandatory) { throw new AuthenticationException("\"" + directive + "\" mandatory directive is missing"); } return ""; } return value; } /** * Copy the directive to the {@link StringBuilder} if not null. * (A directive is a parameter of the digest authentication process.) * * @param directives the directives map * @param sb the output buffer * @param directive the directive name to look for */ public static void copyDirective(HashMap directives, StringBuilder sb, String directive) { String directiveValue = directives.get(directive); if (directiveValue != null) { sb.append(directive).append(" = \"").append(directiveValue).append("\", "); } } /** * Copy the directive from the source map to the destination map, if it's * value isn't null. * (A directive is a parameter of the digest authentication process.) * * @param src the source map * @param dst the destination map * @param directive the directive name * @return the value of the copied directive */ public static String copyDirective(HashMap src, HashMap dst, String directive) { String directiveValue = src.get(directive); if (directiveValue != null) { dst.put(directive, directiveValue); } return directiveValue; } /** * Parses digest-challenge string, extracting each token and value(s). Each token * is a directive. * * @param buf A non-null digest-challenge string. * @throws UnsupportedEncodingException * @throws SaslException if the String cannot be parsed according to RFC 2831 */ public static HashMap parseDirectives(byte[] buf) throws SaslException { HashMap map = new HashMap(); boolean gettingKey = true; boolean gettingQuotedValue = false; boolean expectSeparator = false; byte bch; ByteArrayOutputStream key = new ByteArrayOutputStream(10); ByteArrayOutputStream value = new ByteArrayOutputStream(10); int i = skipLws(buf, 0); while (i < buf.length) { bch = buf[i]; if (gettingKey) { if (bch == ',') { if (key.size() != 0) { throw new SaslException("Directive key contains a ',':" + key); } // Empty element, skip separator and lws i = skipLws(buf, i + 1); } else if (bch == '=') { if (key.size() == 0) { throw new SaslException("Empty directive key"); } gettingKey = false; // Termination of key i = skipLws(buf, i + 1); // Skip to next non whitespace // Check whether value is quoted if (i < buf.length) { if (buf[i] == '"') { gettingQuotedValue = true; ++i; // Skip quote } } else { throw new SaslException("Valueless directive found: " + key.toString()); } } else if (isLws(bch)) { // LWS that occurs after key i = skipLws(buf, i + 1); // Expecting '=' if (i < buf.length) { if (buf[i] != '=') { throw new SaslException("'=' expected after key: " + key.toString()); } } else { throw new SaslException("'=' expected after key: " + key.toString()); } } else { key.write(bch); // Append to key ++i; // Advance } } else if (gettingQuotedValue) { // Getting a quoted value if (bch == '\\') { // quoted-pair = "\" CHAR ==> CHAR ++i; // Skip escape if (i < buf.length) { value.write(buf[i]); ++i; // Advance } else { // Trailing escape in a quoted value throw new SaslException("Unmatched quote found for directive: " + key.toString() + " with value: " + value.toString()); } } else if (bch == '"') { // closing quote ++i; // Skip closing quote gettingQuotedValue = false; expectSeparator = true; } else { value.write(bch); ++i; // Advance } } else if (isLws(bch) || bch == ',') { // Value terminated extractDirective(map, key.toString(), value.toString()); key.reset(); value.reset(); gettingKey = true; gettingQuotedValue = expectSeparator = false; i = skipLws(buf, i + 1); // Skip separator and LWS } else if (expectSeparator) { throw new SaslException("Expecting comma or linear whitespace after quoted string: \"" + value.toString() + "\""); } else { value.write(bch); // Unquoted value ++i; // Advance } } if (gettingQuotedValue) { throw new SaslException("Unmatched quote found for directive: " + key.toString() + " with value: " + value.toString()); } // Get last pair if (key.size() > 0) { extractDirective(map, key.toString(), value.toString()); } return map; } /** * Processes directive/value pairs from the digest-challenge and * fill out the provided map. * * @param key A non-null String challenge token name. * @param value A non-null String token value. * @throws SaslException if either the key or the value is null or * if the key already has a value. */ private static void extractDirective(HashMap map, String key, String value) throws SaslException { if (map.get(key) != null) { throw new SaslException("Peer sent more than one " + key + " directive"); } map.put(key, value); } /** * Is character a linear white space ? * LWS = [CRLF] 1*( SP | HT ) * Note that we're checking individual bytes instead of CRLF * * @param b the byte to check * @return true if it's a linear white space */ public static boolean isLws(byte b) { switch (b) { case 13: // US-ASCII CR, carriage return case 10: // US-ASCII LF, line feed case 32: // US-ASCII SP, space case 9: // US-ASCII HT, horizontal-tab return true; } return false; } /** * Skip all linear white spaces * * @param buf the buf which is being scanned for lws * @param start the offset to start at * @return the next position in buf which isn't a lws character */ private static int skipLws(byte[] buf, int start) { int i; for (i = start; i < buf.length; i++) { if (!isLws(buf[i])) { return i; } } return i; } /** * Used to convert username-value, passwd or realm to 8859_1 encoding * if all chars in string are within the 8859_1 (Latin 1) encoding range. * * @param str a non-null String * @return a non-null String containing the 8859_1 encoded string * @throws AuthenticationException */ public static String stringTo8859_1(String str) throws UnsupportedEncodingException { if (str == null) { return ""; } return new String(str.getBytes("UTF8"), "8859_1"); } /** * Returns the value of the named header. If it has multiple values * then an {@link IllegalArgumentException} is thrown * * @param headers the http headers map * @param key the key of the header * @return the value of the http header */ public static String getSingleValuedHeader(Map> headers, String key) { List values = headers.get(key); if (values == null) { return null; } if (values.size() > 1) { throw new IllegalArgumentException("Header with key [\"" + key + "\"] isn't single valued !"); } return values.get(0); } /** * Adds an header to the provided map of headers. * * @param headers the http headers map * @param key the name of the new header to add * @param value the value of the added header * @param singleValued if true and the map already contains one value * then it is replaced by the new value. Otherwise it simply adds a new * value to this multi-valued header. */ public static void addValueToHeader(Map> headers, String key, String value, boolean singleValued) { List values = headers.get(key); if (values == null) { values = new ArrayList(1); headers.put(key, values); } if (singleValued && values.size() == 1) { values.set(0, value); } else { values.add(value); } } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/utils/IoBufferDecoder.java0000644000175000017500000001775212032276022031231 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.utils; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.textline.LineDelimiter; /** * IoBufferDecoder.java - Handles an {@link IoBuffer} decoder which supports * two methods : * - dynamic delimiter decoding * - fixed length content reading * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class IoBufferDecoder { /** * The class holding the decoding context. */ public class DecodingContext { /** * The buffered data. */ private IoBuffer decodedBuffer; /** * The delimiter in use. Set if delimiter mode is in use. */ private IoBuffer delimiter; /** * The currently matched bytes of the delimiter. */ private int matchCount = 0; /** * Holds the current content length of decoded data if in * content-length mode. */ private int contentLength = -1; /** * Resets the decoding state. */ public void reset() { contentLength = -1; matchCount = 0; decodedBuffer = null; } public int getContentLength() { return contentLength; } public void setContentLength(int contentLength) { this.contentLength = contentLength; } public int getMatchCount() { return matchCount; } public void setMatchCount(int matchCount) { this.matchCount = matchCount; } public IoBuffer getDecodedBuffer() { return decodedBuffer; } public void setDecodedBuffer(IoBuffer decodedBuffer) { this.decodedBuffer = decodedBuffer; } public IoBuffer getDelimiter() { return delimiter; } public void setDelimiter(IoBuffer delimiter) { this.delimiter = delimiter; } } /** * The decoding context. */ private DecodingContext ctx = new DecodingContext(); /** * Creates a new instance that uses specified delimiter byte array as a * message delimiter. * * @param delimiter an array of characters which delimits messages */ public IoBufferDecoder(byte[] delimiter) { setDelimiter(delimiter, true); } /** * Creates a new instance that will read messages of contentLength bytes. * * @param contentLength the exact length to read */ public IoBufferDecoder(int contentLength) { setContentLength(contentLength, false); } /** * Sets the the length of the content line to be decoded. * When set, it overrides the dynamic delimiter setting and content length * method will be used for decoding on the next decodeOnce call. * The default value is -1. * * @param contentLength the content length to match * @param resetMatchCount delimiter matching is reset if true */ public void setContentLength(int contentLength, boolean resetMatchCount) { if (contentLength <= 0) { throw new IllegalArgumentException("contentLength: " + contentLength); } ctx.setContentLength(contentLength); if (resetMatchCount) { ctx.setMatchCount(0); } } /** * Dynamically sets a new delimiter. Next time * {@link IoBufferDecoder#decodeOnce(IoSession, int) } will be called it will use the new * delimiter. Delimiter matching is reset only if resetMatchCount is true but * decoding will continue from current position. * * NB : Delimiter {@link LineDelimiter#AUTO} is not allowed. * * @param delim the new delimiter as a byte array * @param resetMatchCount delimiter matching is reset if true */ public void setDelimiter(byte[] delim, boolean resetMatchCount) { if (delim == null) { throw new IllegalArgumentException("Null delimiter not allowed"); } // Convert delimiter to IoBuffer. IoBuffer delimiter = IoBuffer.allocate(delim.length); delimiter.put(delim); delimiter.flip(); ctx.setDelimiter(delimiter); ctx.setContentLength(-1); if (resetMatchCount) { ctx.setMatchCount(0); } } /** * Will return null unless it has enough data to decode. If contentLength * is set then it tries to retrieve contentLength bytes from the buffer * otherwise it will scan the buffer to find the data delimiter and return * all the data and the trailing delimiter. * * @param in the data to decode */ public IoBuffer decodeFully(IoBuffer in) { int contentLength = ctx.getContentLength(); IoBuffer decodedBuffer = ctx.getDecodedBuffer(); int oldLimit = in.limit(); // Retrieve fixed length content if (contentLength > -1) { if (decodedBuffer == null) { decodedBuffer = IoBuffer.allocate(contentLength).setAutoExpand(true); } // If not enough data to complete the decoding if (in.remaining() < contentLength) { int readBytes = in.remaining(); decodedBuffer.put(in); ctx.setDecodedBuffer(decodedBuffer); ctx.setContentLength(contentLength - readBytes); return null; } int newLimit = in.position() + contentLength; in.limit(newLimit); decodedBuffer.put(in); decodedBuffer.flip(); in.limit(oldLimit); ctx.reset(); return decodedBuffer; } // Not a fixed length matching so try to find a delimiter match int oldPos = in.position(); int matchCount = ctx.getMatchCount(); IoBuffer delimiter = ctx.getDelimiter(); while (in.hasRemaining()) { byte b = in.get(); if (delimiter.get(matchCount) == b) { matchCount++; if (matchCount == delimiter.limit()) { // Found a match. int pos = in.position(); in.position(oldPos); in.limit(pos); if (decodedBuffer == null) { decodedBuffer = IoBuffer.allocate(in.remaining()).setAutoExpand(true); } decodedBuffer.put(in); decodedBuffer.flip(); in.limit(oldLimit); ctx.reset(); return decodedBuffer; } } else { in.position(Math.max(0, in.position() - matchCount)); matchCount = 0; } } // Copy remainder from buf. if (in.remaining() > 0) { in.position(oldPos); decodedBuffer.put(in); in.position(in.limit()); } // Save decoding state ctx.setMatchCount(matchCount); ctx.setDecodedBuffer(decodedBuffer); return decodedBuffer; } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/AbstractProxyIoHandler.java0000644000175000017500000000450112032276023031462 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.proxy.handlers.socks.SocksProxyRequest; import org.apache.mina.proxy.session.ProxyIoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * AbstractProxyIoHandler.java - {@link IoHandler} that intercepts events until handshake is complete. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public abstract class AbstractProxyIoHandler extends IoHandlerAdapter { private final static Logger logger = LoggerFactory.getLogger(AbstractProxyIoHandler.class); /** * Method called only when handshake has completed. * * @param session the io session */ public abstract void proxySessionOpened(IoSession session) throws Exception; /** * Hooked session opened event. * * @param session the io session */ @Override public final void sessionOpened(IoSession session) throws Exception { ProxyIoSession proxyIoSession = (ProxyIoSession) session.getAttribute(ProxyIoSession.PROXY_SESSION); if (proxyIoSession.getRequest() instanceof SocksProxyRequest || proxyIoSession.isAuthenticationFailed() || proxyIoSession.getHandler().isHandshakeComplete()) { proxySessionOpened(session); } else { logger.debug("Filtered session opened event !"); } } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/session/0000755000175000017500000000000012162575507025724 5ustar ebourgebourg././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/session/ProxyIoSessionInitializer.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/session/ProxyIoSessionInitializer0000644000175000017500000000437412032276022033022 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.session; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionInitializer; /** * ProxyIoSessionInitializer.java - {@link IoSessionInitializer} wrapper class to inject the * {@link ProxyIoSession} object that contains all the attributes of the target connection * into the {@link IoSession}. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class ProxyIoSessionInitializer implements IoSessionInitializer { private final IoSessionInitializer wrappedSessionInitializer; private final ProxyIoSession proxyIoSession; public ProxyIoSessionInitializer(final IoSessionInitializer wrappedSessionInitializer, final ProxyIoSession proxyIoSession) { this.wrappedSessionInitializer = wrappedSessionInitializer; this.proxyIoSession = proxyIoSession; } public ProxyIoSession getProxySession() { return proxyIoSession; } public void initializeSession(final IoSession session, T future) { if (wrappedSessionInitializer != null) { wrappedSessionInitializer.initializeSession(session, future); } if (proxyIoSession != null) { proxyIoSession.setSession(session); session.setAttribute(ProxyIoSession.PROXY_SESSION, proxyIoSession); } } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/session/ProxyIoSession.java0000644000175000017500000002133112032276022031526 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.session; import java.net.InetSocketAddress; import java.nio.charset.Charset; import java.util.List; import org.apache.mina.core.session.IoSession; import org.apache.mina.proxy.ProxyConnector; import org.apache.mina.proxy.ProxyLogicHandler; import org.apache.mina.proxy.event.IoSessionEventQueue; import org.apache.mina.proxy.filter.ProxyFilter; import org.apache.mina.proxy.handlers.ProxyRequest; import org.apache.mina.proxy.handlers.http.HttpAuthenticationMethods; import org.apache.mina.proxy.handlers.http.HttpSmartProxyHandler; /** * ProxyIoSession.java - Class that contains all informations for the current proxy * authentication session. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class ProxyIoSession { public final static String PROXY_SESSION = ProxyConnector.class.getName() + ".ProxySession"; private final static String DEFAULT_ENCODING = "ISO-8859-1"; /** * The list contains the authentication methods to use. * The order in the list is revelant : if first method is available * then it will be used etc ... */ private List preferedOrder; /** * The request to send to the proxy. */ private ProxyRequest request; /** * The currently selected proxy handler. */ private ProxyLogicHandler handler; /** * Parent {@link ProxyFilter} handling the session. */ private ProxyFilter proxyFilter; /** * The session. */ private IoSession session; /** * The proxy connector. */ private ProxyConnector connector; /** * Address of the proxy server. */ private InetSocketAddress proxyAddress = null; /** * A flag that indicates that the proxy closed the connection before handshake * is done. So we need to reconnect to the proxy to continue the handshaking * process. */ private boolean reconnectionNeeded = false; /** * Name of the charset used for string encoding & decoding. */ private String charsetName; /** * The session event queue. */ private IoSessionEventQueue eventQueue = new IoSessionEventQueue(this); /** * Set to true when an exception has been thrown or if authentication failed. */ private boolean authenticationFailed; /** * Constructor. * * @param proxyAddress the IP address of the proxy server * @param request the proxy request */ public ProxyIoSession(InetSocketAddress proxyAddress, ProxyRequest request) { setProxyAddress(proxyAddress); setRequest(request); } /** * Returns the pending event queue. */ public IoSessionEventQueue getEventQueue() { return eventQueue; } /** * Returns the list of the prefered order for the authentication methods. * This list is used by the {@link HttpSmartProxyHandler} to determine * which authentication mechanism to use first between those accepted by the * proxy server. This list is only used when connecting to an http proxy. */ public List getPreferedOrder() { return preferedOrder; } /** * Sets the ordered list of prefered authentication mechanisms. * * @param preferedOrder the ordered list */ public void setPreferedOrder(List preferedOrder) { this.preferedOrder = preferedOrder; } /** * Returns the {@link ProxyLogicHandler} currently in use. */ public ProxyLogicHandler getHandler() { return handler; } /** * Sets the {@link ProxyLogicHandler} to use. * * @param handler the {@link ProxyLogicHandler} instance */ public void setHandler(ProxyLogicHandler handler) { this.handler = handler; } /** * Returns the {@link ProxyFilter}. */ public ProxyFilter getProxyFilter() { return proxyFilter; } /** * Sets the {@link ProxyFilter}. * Note : Please do not call this method from your code it could result * in an unexpected behaviour. * * @param proxyFilter the filter */ public void setProxyFilter(ProxyFilter proxyFilter) { this.proxyFilter = proxyFilter; } /** * Returns the proxy request. */ public ProxyRequest getRequest() { return request; } /** * Sets the proxy request. * * @param request the proxy request */ private void setRequest(ProxyRequest request) { if (request == null) { throw new IllegalArgumentException("request cannot be null"); } this.request = request; } /** * Returns the current {@link IoSession}. */ public IoSession getSession() { return session; } /** * Sets the {@link IoSession} in use. * Note : Please do not call this method from your code it could result in an * unexpected behaviour. * * @param session the current io session */ public void setSession(IoSession session) { this.session = session; } /** * Returns the proxy connector. */ public ProxyConnector getConnector() { return connector; } /** * Sets the connector reference of this proxy session. * Note : Please do not call this method from your code it could result in an * unexpected behaviour. * * @param connector the proxy connector */ public void setConnector(ProxyConnector connector) { this.connector = connector; } /** * Returns the IP address of the proxy server. */ public InetSocketAddress getProxyAddress() { return proxyAddress; } /** * Sets the IP address of the proxy server. * * @param proxyAddress the IP address of the proxy server */ private void setProxyAddress(InetSocketAddress proxyAddress) { if (proxyAddress == null) { throw new IllegalArgumentException("proxyAddress object cannot be null"); } this.proxyAddress = proxyAddress; } /** * Returns true if the current authentication process is not finished * but the server has closed the connection. */ public boolean isReconnectionNeeded() { return reconnectionNeeded; } /** * Sets the reconnection needed flag. If set to true, it means that an * authentication process is currently running but the proxy server did not * kept the connection alive. So we need to reconnect to the server to complete * the process. * Note : Please do not call this method from your code it could result in an * unexpected behaviour. * * @param reconnectionNeeded the value to set the flag to */ public void setReconnectionNeeded(boolean reconnectionNeeded) { this.reconnectionNeeded = reconnectionNeeded; } /** * Returns a charset instance of the in use charset name. */ public Charset getCharset() { return Charset.forName(getCharsetName()); } /** * Returns the used charset name or {@link #DEFAULT_ENCODING} if null. */ public String getCharsetName() { if (charsetName == null) { charsetName = DEFAULT_ENCODING; } return charsetName; } /** * Sets the charset to use. * * @param charsetName the charset name */ public void setCharsetName(String charsetName) { this.charsetName = charsetName; } /** * Returns true if authentication failed. */ public boolean isAuthenticationFailed() { return authenticationFailed; } /** * Sets the authentication failed flag. * * @param authenticationFailed the value to set the flag to */ public void setAuthenticationFailed(boolean authenticationFailed) { this.authenticationFailed = authenticationFailed; } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/AbstractProxyLogicHandler.java0000644000175000017500000001532412032276023032155 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy; import java.util.LinkedList; import java.util.Queue; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.future.DefaultWriteFuture; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.DefaultWriteRequest; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.proxy.filter.ProxyFilter; import org.apache.mina.proxy.filter.ProxyHandshakeIoBuffer; import org.apache.mina.proxy.session.ProxyIoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * AbstractProxyLogicHandler.java - Helper class to handle proxy handshaking logic. Derived classes * implement proxy type specific logic. *

* Based upon SSLHandler from mina-filter-ssl. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public abstract class AbstractProxyLogicHandler implements ProxyLogicHandler { private final static Logger LOGGER = LoggerFactory.getLogger(AbstractProxyLogicHandler.class); /** * Object that contains all the proxy authentication session informations. */ private ProxyIoSession proxyIoSession; /** * Queue of write events which occurred before the proxy handshake had completed. */ private Queue writeRequestQueue = null; /** * Has the handshake been completed. */ private boolean handshakeComplete = false; /** * Creates a new {@link AbstractProxyLogicHandler}. * * @param proxyIoSession {@link ProxyIoSession} in use. */ public AbstractProxyLogicHandler(ProxyIoSession proxyIoSession) { this.proxyIoSession = proxyIoSession; } /** * Returns the proxy filter {@link ProxyFilter}. */ protected ProxyFilter getProxyFilter() { return proxyIoSession.getProxyFilter(); } /** * Returns the session. */ protected IoSession getSession() { return proxyIoSession.getSession(); } /** * Returns the {@link ProxyIoSession} object. */ public ProxyIoSession getProxyIoSession() { return proxyIoSession; } /** * Writes data to the proxy server. * * @param nextFilter the next filter * @param data Data buffer to be written. */ protected WriteFuture writeData(final NextFilter nextFilter, final IoBuffer data) { // write net data ProxyHandshakeIoBuffer writeBuffer = new ProxyHandshakeIoBuffer(data); LOGGER.debug(" session write: {}", writeBuffer); WriteFuture writeFuture = new DefaultWriteFuture(getSession()); getProxyFilter().writeData(nextFilter, getSession(), new DefaultWriteRequest(writeBuffer, writeFuture), true); return writeFuture; } /** * Returns true if handshaking is complete and * data can be sent through the proxy. */ public boolean isHandshakeComplete() { synchronized (this) { return handshakeComplete; } } /** * Signals that the handshake has finished. */ protected final void setHandshakeComplete() { synchronized (this) { handshakeComplete = true; } ProxyIoSession proxyIoSession = getProxyIoSession(); proxyIoSession.getConnector().fireConnected(proxyIoSession.getSession()).awaitUninterruptibly(); LOGGER.debug(" handshake completed"); // Connected OK try { proxyIoSession.getEventQueue().flushPendingSessionEvents(); flushPendingWriteRequests(); } catch (Exception ex) { LOGGER.error("Unable to flush pending write requests", ex); } } /** * Send any write requests which were queued whilst waiting for handshaking to complete. */ protected synchronized void flushPendingWriteRequests() throws Exception { LOGGER.debug(" flushPendingWriteRequests()"); if (writeRequestQueue == null) { return; } Event scheduledWrite; while ((scheduledWrite = writeRequestQueue.poll()) != null) { LOGGER.debug(" Flushing buffered write request: {}", scheduledWrite.data); getProxyFilter().filterWrite(scheduledWrite.nextFilter, getSession(), (WriteRequest) scheduledWrite.data); } // Free queue writeRequestQueue = null; } /** * Enqueue a message to be written once handshaking is complete. */ public synchronized void enqueueWriteRequest(final NextFilter nextFilter, final WriteRequest writeRequest) { if (writeRequestQueue == null) { writeRequestQueue = new LinkedList(); } writeRequestQueue.offer(new Event(nextFilter, writeRequest)); } /** * Closes the session. * * @param message the error message * @param t the exception which caused the session closing */ protected void closeSession(final String message, final Throwable t) { if (t != null) { LOGGER.error(message, t); proxyIoSession.setAuthenticationFailed(true); } else { LOGGER.error(message); } getSession().close(true); } /** * Closes the session. * * @param message the error message */ protected void closeSession(final String message) { closeSession(message, null); } /** * Event wrapper class for enqueued events. */ private final static class Event { private final NextFilter nextFilter; private final Object data; Event(final NextFilter nextFilter, final Object data) { this.nextFilter = nextFilter; this.data = data; } public Object getData() { return data; } public NextFilter getNextFilter() { return nextFilter; } } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/filter/0000755000175000017500000000000012162575507025526 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/filter/ProxyFilter.java0000644000175000017500000003407312032276022030651 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.filter; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.proxy.ProxyAuthException; import org.apache.mina.proxy.ProxyConnector; import org.apache.mina.proxy.ProxyLogicHandler; import org.apache.mina.proxy.event.IoSessionEvent; import org.apache.mina.proxy.event.IoSessionEventQueue; import org.apache.mina.proxy.event.IoSessionEventType; import org.apache.mina.proxy.handlers.ProxyRequest; import org.apache.mina.proxy.handlers.http.HttpSmartProxyHandler; import org.apache.mina.proxy.handlers.socks.Socks4LogicHandler; import org.apache.mina.proxy.handlers.socks.Socks5LogicHandler; import org.apache.mina.proxy.handlers.socks.SocksProxyConstants; import org.apache.mina.proxy.handlers.socks.SocksProxyRequest; import org.apache.mina.proxy.session.ProxyIoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * ProxyFilter.java - Proxy {@link IoFilter}. * Automatically inserted into the {@link IoFilter} chain by {@link ProxyConnector}. * Sends the initial handshake message to the proxy and handles any response * to the handshake. Once the handshake has completed and the proxied connection has been * established this filter becomes transparent to data flowing through the connection. *

* Based upon SSLFilter from mina-filter-ssl. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class ProxyFilter extends IoFilterAdapter { private final static Logger LOGGER = LoggerFactory.getLogger(ProxyFilter.class); /** * Create a new {@link ProxyFilter}. */ public ProxyFilter() { // Do nothing } /** * Called before the filter is added into the filter chain. * Checks if chain already holds an {@link ProxyFilter} instance. * * @param chain the filter chain * @param name the name assigned to this filter * @param nextFilter the next filter * @throws IllegalStateException if chain already contains an instance of * {@link ProxyFilter} */ @Override public void onPreAdd(final IoFilterChain chain, final String name, final NextFilter nextFilter) { if (chain.contains(ProxyFilter.class)) { throw new IllegalStateException("A filter chain cannot contain more than one ProxyFilter."); } } /** * Called when the filter is removed from the filter chain. * Cleans the {@link ProxyIoSession} instance from the session. * * @param chain the filter chain * @param name the name assigned to this filter * @param nextFilter the next filter */ @Override public void onPreRemove(final IoFilterChain chain, final String name, final NextFilter nextFilter) { IoSession session = chain.getSession(); session.removeAttribute(ProxyIoSession.PROXY_SESSION); } /** * Called when an exception occurs in the chain. A flag is set in the * {@link ProxyIoSession} session's instance to signal that handshake * failed. * * @param chain the filter chain * @param name the name assigned to this filter * @param nextFilter the next filter */ @Override public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) throws Exception { ProxyIoSession proxyIoSession = (ProxyIoSession) session.getAttribute(ProxyIoSession.PROXY_SESSION); proxyIoSession.setAuthenticationFailed(true); super.exceptionCaught(nextFilter, session, cause); } /** * Get the {@link ProxyLogicHandler} for a given session. * * @param session the session object * @return the handler which will handle handshaking with the proxy */ private ProxyLogicHandler getProxyHandler(final IoSession session) { ProxyLogicHandler handler = ((ProxyIoSession) session.getAttribute(ProxyIoSession.PROXY_SESSION)).getHandler(); if (handler == null) { throw new IllegalStateException(); } // Sanity check if (handler.getProxyIoSession().getProxyFilter() != this) { throw new IllegalArgumentException("Not managed by this filter."); } return handler; } /** * Receives data from the remote host, passes to the handler if a handshake is in progress, * otherwise passes on transparently. * * @param nextFilter the next filter in filter chain * @param session the session object * @param message the object holding the received data */ @Override public void messageReceived(final NextFilter nextFilter, final IoSession session, final Object message) throws ProxyAuthException { ProxyLogicHandler handler = getProxyHandler(session); synchronized (handler) { IoBuffer buf = (IoBuffer) message; if (handler.isHandshakeComplete()) { // Handshake done - pass data on as-is nextFilter.messageReceived(session, buf); } else { LOGGER.debug(" Data Read: {} ({})", handler, buf); // Keep sending handshake data to the handler until we run out // of data or the handshake is finished while (buf.hasRemaining() && !handler.isHandshakeComplete()) { LOGGER.debug(" Pre-handshake - passing to handler"); int pos = buf.position(); handler.messageReceived(nextFilter, buf); // Data not consumed or session closing if (buf.position() == pos || session.isClosing()) { return; } } // Pass on any remaining data to the next filter if (buf.hasRemaining()) { LOGGER.debug(" Passing remaining data to next filter"); nextFilter.messageReceived(session, buf); } } } } /** * Filters outgoing writes, queueing them up if necessary while a handshake * is ongoing. * * @param nextFilter the next filter in filter chain * @param session the session object * @param writeRequest the data to write */ @Override public void filterWrite(final NextFilter nextFilter, final IoSession session, final WriteRequest writeRequest) { writeData(nextFilter, session, writeRequest, false); } /** * Actually write data. Queues the data up unless it relates to the handshake or the * handshake is done. * * @param nextFilter the next filter in filter chain * @param session the session object * @param writeRequest the data to write * @param isHandshakeData true if writeRequest is written by the proxy classes. */ public void writeData(final NextFilter nextFilter, final IoSession session, final WriteRequest writeRequest, final boolean isHandshakeData) { ProxyLogicHandler handler = getProxyHandler(session); synchronized (handler) { if (handler.isHandshakeComplete()) { // Handshake is done - write data as normal nextFilter.filterWrite(session, writeRequest); } else if (isHandshakeData) { LOGGER.debug(" handshake data: {}", writeRequest.getMessage()); // Writing handshake data nextFilter.filterWrite(session, writeRequest); } else { // Writing non-handshake data before the handshake finished if (!session.isConnected()) { // Not even connected - ignore LOGGER.debug(" Write request on closed session. Request ignored."); } else { // Queue the data to be sent as soon as the handshake completes LOGGER.debug(" Handshaking is not complete yet. Buffering write request."); handler.enqueueWriteRequest(nextFilter, writeRequest); } } } } /** * Filter handshake related messages from reaching the messageSent callbacks of * downstream filters. * * @param nextFilter the next filter in filter chain * @param session the session object * @param writeRequest the data written */ @Override public void messageSent(final NextFilter nextFilter, final IoSession session, final WriteRequest writeRequest) throws Exception { if (writeRequest.getMessage() != null && writeRequest.getMessage() instanceof ProxyHandshakeIoBuffer) { // Ignore buffers used in handshaking return; } nextFilter.messageSent(session, writeRequest); } /** * Called when the session is created. Will create the handler able to handle * the {@link ProxyIoSession#getRequest()} request stored in the session. Event * is stored in an {@link IoSessionEventQueue} for later delivery to the next filter * in the chain when the handshake would have succeed. This will prevent the rest of * the filter chain from being affected by this filter internals. * * Please note that this event can occur multiple times because of some http * proxies not handling keep-alive connections thus needing multiple sessions * during the handshake. * * @param nextFilter the next filter in filter chain * @param session the session object */ @Override public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception { LOGGER.debug("Session created: " + session); ProxyIoSession proxyIoSession = (ProxyIoSession) session.getAttribute(ProxyIoSession.PROXY_SESSION); LOGGER.debug(" get proxyIoSession: " + proxyIoSession); proxyIoSession.setProxyFilter(this); // Create a HTTP proxy handler and start handshake. ProxyLogicHandler handler = proxyIoSession.getHandler(); // This test prevents from loosing handler conversationnal state when // reconnection occurs during an http handshake. if (handler == null) { ProxyRequest request = proxyIoSession.getRequest(); if (request instanceof SocksProxyRequest) { SocksProxyRequest req = (SocksProxyRequest) request; if (req.getProtocolVersion() == SocksProxyConstants.SOCKS_VERSION_4) { handler = new Socks4LogicHandler(proxyIoSession); } else { handler = new Socks5LogicHandler(proxyIoSession); } } else { handler = new HttpSmartProxyHandler(proxyIoSession); } proxyIoSession.setHandler(handler); handler.doHandshake(nextFilter); } proxyIoSession.getEventQueue().enqueueEventIfNecessary( new IoSessionEvent(nextFilter, session, IoSessionEventType.CREATED)); } /** * Event is stored in an {@link IoSessionEventQueue} for later delivery to the next filter * in the chain when the handshake would have succeed. This will prevent the rest of * the filter chain from being affected by this filter internals. * * @param nextFilter the next filter in filter chain * @param session the session object */ @Override public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception { ProxyIoSession proxyIoSession = (ProxyIoSession) session.getAttribute(ProxyIoSession.PROXY_SESSION); proxyIoSession.getEventQueue().enqueueEventIfNecessary( new IoSessionEvent(nextFilter, session, IoSessionEventType.OPENED)); } /** * Event is stored in an {@link IoSessionEventQueue} for later delivery to the next filter * in the chain when the handshake would have succeed. This will prevent the rest of * the filter chain from being affected by this filter internals. * * @param nextFilter the next filter in filter chain * @param session the session object */ @Override public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception { ProxyIoSession proxyIoSession = (ProxyIoSession) session.getAttribute(ProxyIoSession.PROXY_SESSION); proxyIoSession.getEventQueue().enqueueEventIfNecessary(new IoSessionEvent(nextFilter, session, status)); } /** * Event is stored in an {@link IoSessionEventQueue} for later delivery to the next filter * in the chain when the handshake would have succeed. This will prevent the rest of * the filter chain from being affected by this filter internals. * * @param nextFilter the next filter in filter chain * @param session the session object */ @Override public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception { ProxyIoSession proxyIoSession = (ProxyIoSession) session.getAttribute(ProxyIoSession.PROXY_SESSION); proxyIoSession.getEventQueue().enqueueEventIfNecessary( new IoSessionEvent(nextFilter, session, IoSessionEventType.CLOSED)); } }././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/filter/ProxyHandshakeIoBuffer.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/filter/ProxyHandshakeIoBuffer.jav0000644000175000017500000000254012032276022032565 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.filter; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.buffer.IoBufferWrapper; /** * ProxyHandshakeIoBuffer.java - {@link IoBuffer} wrapper to indicate handshake * related messages which should not be passed upstream of the {@link ProxyFilter}. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class ProxyHandshakeIoBuffer extends IoBufferWrapper { public ProxyHandshakeIoBuffer(final IoBuffer buf) { super(buf); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/ProxyConnector.java0000644000175000017500000002113712032276023030067 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.concurrent.Executor; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.file.FileRegion; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.DefaultConnectFuture; import org.apache.mina.core.service.AbstractIoConnector; import org.apache.mina.core.service.DefaultTransportMetadata; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionConfig; import org.apache.mina.core.session.IoSessionInitializer; import org.apache.mina.proxy.filter.ProxyFilter; import org.apache.mina.proxy.handlers.socks.SocksProxyRequest; import org.apache.mina.proxy.session.ProxyIoSession; import org.apache.mina.proxy.session.ProxyIoSessionInitializer; import org.apache.mina.transport.socket.DefaultSocketSessionConfig; import org.apache.mina.transport.socket.SocketConnector; import org.apache.mina.transport.socket.SocketSessionConfig; /** * ProxyConnector.java - Decorator for {@link SocketConnector} to provide proxy support, * as suggested by MINA list discussions. *

* Operates by intercepting connect requests and replacing the endpoint address with the * proxy address, then adding a {@link ProxyFilter} as the first {@link IoFilter} which * performs any necessary handshaking with the proxy before allowing data to flow * normally. During the handshake, any outgoing write requests are buffered. * * @see http://www.nabble.com/Meta-Transport%3A-an-idea-on-implementing-reconnection-and-proxy-td12969001.html * @see http://issues.apache.org/jira/browse/DIRMINA-415 * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class ProxyConnector extends AbstractIoConnector { private static final TransportMetadata METADATA = new DefaultTransportMetadata("proxy", "proxyconnector", false, true, InetSocketAddress.class, SocketSessionConfig.class, IoBuffer.class, FileRegion.class); /** * Wrapped connector to use for outgoing TCP connections. */ private SocketConnector connector = null; /** * Proxy filter instance. */ private final ProxyFilter proxyFilter = new ProxyFilter(); /** * The {@link ProxyIoSession} in use. */ private ProxyIoSession proxyIoSession; /** * This future will notify it's listeners when really connected to the target */ private DefaultConnectFuture future; /** * Creates a new proxy connector. */ public ProxyConnector() { super(new DefaultSocketSessionConfig(), null); } /** * Creates a new proxy connector. * * @param connector Connector used to establish proxy connections. */ public ProxyConnector(final SocketConnector connector) { this(connector, new DefaultSocketSessionConfig(), null); } /** * Creates a new proxy connector. * @see AbstractIoConnector(IoSessionConfig, Executor). */ public ProxyConnector(final SocketConnector connector, IoSessionConfig config, Executor executor) { super(config, executor); setConnector(connector); } /** * {@inheritDoc} */ @Override public IoSessionConfig getSessionConfig() { return connector.getSessionConfig(); } /** * Returns the {@link ProxyIoSession} linked with this connector. */ public ProxyIoSession getProxyIoSession() { return proxyIoSession; } /** * Sets the proxy session object of this connector. * @param proxyIoSession the configuration of this connector. */ public void setProxyIoSession(ProxyIoSession proxyIoSession) { if (proxyIoSession == null) { throw new IllegalArgumentException("proxySession object cannot be null"); } if (proxyIoSession.getProxyAddress() == null) { throw new IllegalArgumentException("proxySession.proxyAddress cannot be null"); } proxyIoSession.setConnector(this); setDefaultRemoteAddress(proxyIoSession.getProxyAddress()); this.proxyIoSession = proxyIoSession; } /** * Connects to the specified address. If communication starts * successfully, events are fired to the connector's handler. * * @param remoteAddress the remote address to connect to * @param localAddress the local address * @param sessionInitializer the session initializer * @return {@link ConnectFuture} that will tell the result of the connection attempt */ @SuppressWarnings("unchecked") @Override protected ConnectFuture connect0(final SocketAddress remoteAddress, final SocketAddress localAddress, final IoSessionInitializer sessionInitializer) { if (!proxyIoSession.isReconnectionNeeded()) { // First connection IoHandler handler = getHandler(); if (!(handler instanceof AbstractProxyIoHandler)) { throw new IllegalArgumentException("IoHandler must be an instance of AbstractProxyIoHandler"); } connector.setHandler(handler); future = new DefaultConnectFuture(); } ConnectFuture conFuture = connector.connect(proxyIoSession.getProxyAddress(), new ProxyIoSessionInitializer( sessionInitializer, proxyIoSession)); // If proxy does not use reconnection like socks the connector's // future is returned. If we're in the middle of a reconnection // then we send back the connector's future which is only used // internally while future will be used to notify // the user of the connection state. if (proxyIoSession.getRequest() instanceof SocksProxyRequest || proxyIoSession.isReconnectionNeeded()) { return conFuture; } return future; } /** * Cancels the real connection when reconnection is in use. */ public void cancelConnectFuture() { future.cancel(); } /** * Fires the connection event on the real future to notify the client. * * @param session the current session * @return the future holding the connected session */ protected ConnectFuture fireConnected(final IoSession session) { future.setSession(session); return future; } /** * Get the {@link SocketConnector} to be used for connections * to the proxy server. */ public final SocketConnector getConnector() { return connector; } /** * Sets the {@link SocketConnector} to be used for connections * to the proxy server. * * @param connector the connector to use */ private final void setConnector(final SocketConnector connector) { if (connector == null) { throw new IllegalArgumentException("connector cannot be null"); } this.connector = connector; String className = ProxyFilter.class.getName(); // Removes an old ProxyFilter instance from the chain if (connector.getFilterChain().contains(className)) { connector.getFilterChain().remove(className); } // Insert the ProxyFilter as the first filter in the filter chain builder connector.getFilterChain().addFirst(className, proxyFilter); } /** * {@inheritDoc} */ @Override protected void dispose0() throws Exception { if (connector != null) { connector.dispose(); } } /** * {@inheritDoc} */ public TransportMetadata getTransportMetadata() { return METADATA; } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/ProxyLogicHandler.java0000644000175000017500000000531512032276023030470 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.proxy.session.ProxyIoSession; /** * ProxyLogicHandler.java - Interface implemented by classes containing proxy type specific logic. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public interface ProxyLogicHandler { /** * Tests if handshake process is complete. * * @return true if handshaking is complete and * data can be sent through the proxy, false otherwise. */ public abstract boolean isHandshakeComplete(); /** * Handle incoming data during the handshake process. Should consume only the * handshake data from the buffer, leaving any extra data in place. * * @param nextFilter the next filter in the filter chain * @param buf the buffer holding the received data * @throws ProxyAuthException if authentication fails */ public abstract void messageReceived(NextFilter nextFilter, IoBuffer buf) throws ProxyAuthException; /** * Called at each step of the handshake procedure. * * @param nextFilter the next filter in filter chain * @throws ProxyAuthException if authentication fails */ public abstract void doHandshake(NextFilter nextFilter) throws ProxyAuthException; /** * Returns the {@link ProxyIoSession}. * * @return the proxy session object */ public abstract ProxyIoSession getProxyIoSession(); /** * Enqueue a message to be written once handshaking is complete. * * @param nextFilter the next filter in filter chain * @param writeRequest the data to be written */ public abstract void enqueueWriteRequest(final NextFilter nextFilter, final WriteRequest writeRequest); }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/event/0000755000175000017500000000000012162575507025362 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/event/IoSessionEventQueue.java0000644000175000017500000001102312032276022032126 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.event; import java.util.LinkedList; import java.util.Queue; import org.apache.mina.proxy.handlers.socks.SocksProxyRequest; import org.apache.mina.proxy.session.ProxyIoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * IoSessionEventQueue.java - Queue that contains filtered session events * while handshake isn't done. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class IoSessionEventQueue { private final static Logger logger = LoggerFactory.getLogger(IoSessionEventQueue.class); /** * The proxy session object. */ private ProxyIoSession proxyIoSession; /** * Queue of session events which occurred before the proxy handshake had completed. */ private Queue sessionEventsQueue = new LinkedList(); public IoSessionEventQueue(ProxyIoSession proxyIoSession) { this.proxyIoSession = proxyIoSession; } /** * Discard all events from the queue. */ private void discardSessionQueueEvents() { synchronized (sessionEventsQueue) { // Free queue sessionEventsQueue.clear(); logger.debug("Event queue CLEARED"); } } /** * Event is enqueued only if necessary : * - socks proxies do not need the reconnection feature so events are always * forwarded for these. * - http proxies events will be enqueued while handshake has not been completed * or until connection was closed. * If connection was prematurely closed previous events are discarded and only the * session closed is delivered. * * @param evt the event to enqueue */ public void enqueueEventIfNecessary(final IoSessionEvent evt) { logger.debug("??? >> Enqueue {}", evt); if (proxyIoSession.getRequest() instanceof SocksProxyRequest) { // No reconnection used evt.deliverEvent(); return; } if (proxyIoSession.getHandler().isHandshakeComplete()) { evt.deliverEvent(); } else { if (evt.getType() == IoSessionEventType.CLOSED) { if (proxyIoSession.isAuthenticationFailed()) { proxyIoSession.getConnector().cancelConnectFuture(); discardSessionQueueEvents(); evt.deliverEvent(); } else { discardSessionQueueEvents(); } } else if (evt.getType() == IoSessionEventType.OPENED) { // Enqueue event cause it will not reach IoHandler but deliver it to enable // session creation. enqueueSessionEvent(evt); evt.deliverEvent(); } else { enqueueSessionEvent(evt); } } } /** * Send any session event which were queued while waiting for handshaking to complete. * * Please note this is an internal method. DO NOT USE it in your code. */ public void flushPendingSessionEvents() throws Exception { synchronized (sessionEventsQueue) { IoSessionEvent evt; while ((evt = sessionEventsQueue.poll()) != null) { logger.debug(" Flushing buffered event: {}", evt); evt.deliverEvent(); } } } /** * Enqueue an event to be delivered once handshaking is complete. * * @param evt the session event to enqueue */ private void enqueueSessionEvent(final IoSessionEvent evt) { synchronized (sessionEventsQueue) { logger.debug("Enqueuing event: {}", evt); sessionEventsQueue.offer(evt); } } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/event/IoSessionEvent.java0000644000175000017500000001156312032276022031132 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.event; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * IoSessionEvent.java - Wrapper Class for enqueued events. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class IoSessionEvent { private final static Logger logger = LoggerFactory.getLogger(IoSessionEvent.class); /** * The next filter in the chain. */ private final NextFilter nextFilter; /** * The session. */ private final IoSession session; /** * The event type. */ private final IoSessionEventType type; /** * The idle status if type value is {@link IoSessionEventType#IDLE}, * null otherwise. */ private IdleStatus status; /** * Creates an instance of this class when event type differs from * {@link IoSessionEventType#IDLE}. * * @param nextFilter the next filter * @param session the session * @param type the event type */ public IoSessionEvent(final NextFilter nextFilter, final IoSession session, final IoSessionEventType type) { this.nextFilter = nextFilter; this.session = session; this.type = type; } /** * Creates an instance of this class when event type is * {@link IoSessionEventType#IDLE}. * * @param nextFilter the next filter * @param session the session * @param status the idle status */ public IoSessionEvent(final NextFilter nextFilter, final IoSession session, final IdleStatus status) { this(nextFilter, session, IoSessionEventType.IDLE); this.status = status; } /** * Delivers this event to the next filter. */ public void deliverEvent() { logger.debug("Delivering event {}", this); deliverEvent(this.nextFilter, this.session, this.type, this.status); } /** * Static method which effectively delivers the specified event to the next filter * nextFilter on the session. * * @param nextFilter the next filter * @param session the session on which the event occured * @param type the event type * @param status the idle status should only be non null only if the event type is * {@link IoSessionEventType#IDLE} */ private static void deliverEvent(final NextFilter nextFilter, final IoSession session, final IoSessionEventType type, final IdleStatus status) { switch (type) { case CREATED: nextFilter.sessionCreated(session); break; case OPENED: nextFilter.sessionOpened(session); break; case IDLE: nextFilter.sessionIdle(session, status); break; case CLOSED: nextFilter.sessionClosed(session); break; } } /** * {@inheritDoc} */ @Override public String toString() { StringBuilder sb = new StringBuilder(IoSessionEvent.class.getSimpleName()); sb.append('@'); sb.append(Integer.toHexString(hashCode())); sb.append(" - [ ").append(session); sb.append(", ").append(type); sb.append(']'); return sb.toString(); } /** * Returns the idle status of the event. * * @return the idle status of the event */ public IdleStatus getStatus() { return status; } /** * Returns the next filter to which the event should be sent. * * @return the next filter */ public NextFilter getNextFilter() { return nextFilter; } /** * Returns the session on which the event occured. * * @return the session */ public IoSession getSession() { return session; } /** * Returns the event type that occured. * * @return the event type */ public IoSessionEventType getType() { return type; } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/event/IoSessionEventType.java0000644000175000017500000000341512032276022031771 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy.event; /** * IoSessionEventType.java - Enumerates session event types. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public enum IoSessionEventType { CREATED(1), OPENED(2), IDLE(3), CLOSED(4); /** * The event type id. */ private final int id; private IoSessionEventType(int id) { this.id = id; } /** * Returns the event id. * * @return the event id */ public int getId() { return id; } /** * {@inheritDoc} */ @Override public String toString() { switch (this) { case CREATED: return "- CREATED event -"; case OPENED: return "- OPENED event -"; case IDLE: return "- IDLE event -"; case CLOSED: return "- CLOSED event -"; default: return "- Event Id=" + id + " -"; } } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/proxy/ProxyAuthException.java0000644000175000017500000000274712032276023030723 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.proxy; import javax.security.sasl.SaslException; /** * ProxyAuthException.java - This class extends {@link SaslException} and represents an * authentication failure to the proxy. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class ProxyAuthException extends SaslException { private static final long serialVersionUID = -6511596809517532988L; /** * {@inheritDoc} */ public ProxyAuthException(String message) { super(message); } /** * {@inheritDoc} */ public ProxyAuthException(String message, Throwable ex) { super(message, ex); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/0000755000175000017500000000000012162575507024010 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/0000755000175000017500000000000012162575507025450 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/IoService.java0000644000175000017500000001574012032276027030201 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.service; import java.util.Map; import java.util.Set; import org.apache.mina.core.IoUtil; import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.filterchain.IoFilterChainBuilder; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionConfig; import org.apache.mina.core.session.IoSessionDataStructureFactory; /** * Base interface for all {@link IoAcceptor}s and {@link IoConnector}s * that provide I/O service and manage {@link IoSession}s. * * @author Apache MINA Project */ public interface IoService { /** * Returns the {@link TransportMetadata} that this service runs on. */ TransportMetadata getTransportMetadata(); /** * Adds an {@link IoServiceListener} that listens any events related with * this service. */ void addListener(IoServiceListener listener); /** * Removed an existing {@link IoServiceListener} that listens any events * related with this service. */ void removeListener(IoServiceListener listener); /** * Returns true if and if only {@link #dispose()} method has * been called. Please note that this method will return true * even after all the related resources are released. */ boolean isDisposing(); /** * Returns true if and if only all resources of this processor * have been disposed. */ boolean isDisposed(); /** * Releases any resources allocated by this service. Please note that * this method might block as long as there are any sessions managed by * this service. */ void dispose(); /** * Releases any resources allocated by this service. Please note that * this method might block as long as there are any sessions managed by this service. * * Warning : calling this method from a IoFutureListener with awaitTermination = true * will probably lead to a deadlock. * * @param awaitTermination When true this method will block until the underlying ExecutorService is terminated */ void dispose(boolean awaitTermination); /** * Returns the handler which will handle all connections managed by this service. */ IoHandler getHandler(); /** * Sets the handler which will handle all connections managed by this service. */ void setHandler(IoHandler handler); /** * Returns the map of all sessions which are currently managed by this * service. The key of map is the {@link IoSession#getId() ID} of the * session. * * @return the sessions. An empty collection if there's no session. */ Map getManagedSessions(); /** * Returns the number of all sessions which are currently managed by this * service. */ int getManagedSessionCount(); /** * Returns the default configuration of the new {@link IoSession}s * created by this service. */ IoSessionConfig getSessionConfig(); /** * Returns the {@link IoFilterChainBuilder} which will build the * {@link IoFilterChain} of all {@link IoSession}s which is created * by this service. * The default value is an empty {@link DefaultIoFilterChainBuilder}. */ IoFilterChainBuilder getFilterChainBuilder(); /** * Sets the {@link IoFilterChainBuilder} which will build the * {@link IoFilterChain} of all {@link IoSession}s which is created * by this service. * If you specify null this property will be set to * an empty {@link DefaultIoFilterChainBuilder}. */ void setFilterChainBuilder(IoFilterChainBuilder builder); /** * A shortcut for ( ( DefaultIoFilterChainBuilder ) {@link #getFilterChainBuilder()} ). * Please note that the returned object is not a real {@link IoFilterChain} * but a {@link DefaultIoFilterChainBuilder}. Modifying the returned builder * won't affect the existing {@link IoSession}s at all, because * {@link IoFilterChainBuilder}s affect only newly created {@link IoSession}s. * * @throws IllegalStateException if the current {@link IoFilterChainBuilder} is * not a {@link DefaultIoFilterChainBuilder} */ DefaultIoFilterChainBuilder getFilterChain(); /** * Returns a value of whether or not this service is active * * @return whether of not the service is active. */ boolean isActive(); /** * Returns the time when this service was activated. It returns the last * time when this service was activated if the service is not active now. * * @return The time by using {@link System#currentTimeMillis()} */ long getActivationTime(); /** * Writes the specified {@code message} to all the {@link IoSession}s * managed by this service. This method is a convenience shortcut for * {@link IoUtil#broadcast(Object, Collection)}. */ Set broadcast(Object message); /** * Returns the {@link IoSessionDataStructureFactory} that provides * related data structures for a new session created by this service. */ IoSessionDataStructureFactory getSessionDataStructureFactory(); /** * Sets the {@link IoSessionDataStructureFactory} that provides * related data structures for a new session created by this service. */ void setSessionDataStructureFactory(IoSessionDataStructureFactory sessionDataStructureFactory); /** * Returns the number of bytes scheduled to be written * * @return The number of bytes scheduled to be written */ int getScheduledWriteBytes(); /** * Returns the number of messages scheduled to be written * * @return The number of messages scheduled to be written */ int getScheduledWriteMessages(); /** * Returns the IoServiceStatistics object for this service. * * @return The statistics object for this service. */ IoServiceStatistics getStatistics(); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/IoConnector.java0000644000175000017500000001403012032276027030522 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.service; import java.net.SocketAddress; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionInitializer; /** * Connects to endpoint, communicates with the server, and fires events to * {@link IoHandler}s. *

* Please refer to * NetCat * example. *

* You should connect to the desired socket address to start communication, * and then events for incoming connections will be sent to the specified * default {@link IoHandler}. *

* Threads connect to endpoint start automatically when * {@link #connect(SocketAddress)} is invoked, and stop when all * connection attempts are finished. * * @author Apache MINA Project */ public interface IoConnector extends IoService { /** * Returns the connect timeout in seconds. The default value is 1 minute. * * @deprecated * @see getConnectTimeoutMillis() */ int getConnectTimeout(); /** * Returns the connect timeout in milliseconds. The default value is 1 minute. */ long getConnectTimeoutMillis(); /** * Sets the connect timeout in seconds. The default value is 1 minute. * * @deprecated * @see setConnectTimeoutMillis() */ void setConnectTimeout(int connectTimeout); /** * Sets the connect timeout in milliseconds. The default value is 1 minute. */ void setConnectTimeoutMillis(long connectTimeoutInMillis); /** * Returns the default remote address to connect to when no argument * is specified in {@link #connect()} method. */ SocketAddress getDefaultRemoteAddress(); /** * Sets the default remote address to connect to when no argument is * specified in {@link #connect()} method. */ void setDefaultRemoteAddress(SocketAddress defaultRemoteAddress); /** * Connects to the {@link #setDefaultRemoteAddress(SocketAddress) default remote address}. * * @throws IllegalStateException if no default remoted address is set. */ ConnectFuture connect(); /** * Connects to the {@link #setDefaultRemoteAddress(SocketAddress) default * remote address} and invokes the ioSessionInitializer when * the IoSession is created but before {@link IoHandler#sessionCreated(IoSession)} * is invoked. There is no guarantee that the ioSessionInitializer * will be invoked before this method returns. * * @param sessionInitializer the callback to invoke when the {@link IoSession} object is created * * @throws IllegalStateException if no default remote address is set. */ ConnectFuture connect(IoSessionInitializer sessionInitializer); /** * Connects to the specified remote address. * * @return the {@link ConnectFuture} instance which is completed when the * connection attempt initiated by this call succeeds or fails. */ ConnectFuture connect(SocketAddress remoteAddress); /** * Connects to the specified remote address and invokes * the ioSessionInitializer when the IoSession is created but before * {@link IoHandler#sessionCreated(IoSession)} is invoked. There is no * guarantee that the ioSessionInitializer will be invoked before * this method returns. * * @param remoteAddress the remote address to connect to * @param sessionInitializer the callback to invoke when the {@link IoSession} object is created * * @return the {@link ConnectFuture} instance which is completed when the * connection attempt initiated by this call succeeds or fails. */ ConnectFuture connect(SocketAddress remoteAddress, IoSessionInitializer sessionInitializer); /** * Connects to the specified remote address binding to the specified local address. * * @return the {@link ConnectFuture} instance which is completed when the * connection attempt initiated by this call succeeds or fails. */ ConnectFuture connect(SocketAddress remoteAddress, SocketAddress localAddress); /** * Connects to the specified remote address binding to the specified local * address and and invokes the ioSessionInitializer when the * IoSession is created but before {@link IoHandler#sessionCreated(IoSession)} * is invoked. There is no guarantee that the ioSessionInitializer * will be invoked before this method returns. * * @param remoteAddress the remote address to connect to * @param localAddress the local interface to bind to * @param sessionInitializer the callback to invoke when the {@link IoSession} object is created * * @return the {@link ConnectFuture} instance which is completed when the * connection attempt initiated by this call succeeds or fails. */ ConnectFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, IoSessionInitializer sessionInitializer); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/SimpleIoProcessorPool.java0000644000175000017500000003002412032276027032554 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.service; import java.lang.reflect.Constructor; import java.util.Arrays; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.session.AbstractIoSession; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An {@link IoProcessor} pool that distributes {@link IoSession}s into one or more * {@link IoProcessor}s. Most current transport implementations use this pool internally * to perform better in a multi-core environment, and therefore, you won't need to * use this pool directly unless you are running multiple {@link IoService}s in the * same JVM. *

* If you are running multiple {@link IoService}s, you could want to share the pool * among all services. To do so, you can create a new {@link SimpleIoProcessorPool} * instance by yourself and provide the pool as a constructor parameter when you * create the services. *

* This pool uses Java reflection API to create multiple {@link IoProcessor} instances. * It tries to instantiate the processor in the following order: *

    *
  1. A public constructor with one {@link ExecutorService} parameter.
  2. *
  3. A public constructor with one {@link Executor} parameter.
  4. *
  5. A public default constructor
  6. *
* The following is an example for the NIO socket transport: *

 * // Create a shared pool.
 * SimpleIoProcessorPool<NioSession> pool = 
 *         new SimpleIoProcessorPool<NioSession>(NioProcessor.class, 16);
 * 
 * // Create two services that share the same pool.
 * SocketAcceptor acceptor = new NioSocketAcceptor(pool);
 * SocketConnector connector = new NioSocketConnector(pool);
 * 
 * ...
 * 
 * // Release related resources.
 * connector.dispose();
 * acceptor.dispose();
 * pool.dispose();
 * 
* * @author Apache MINA Project * * @param the type of the {@link IoSession} to be managed by the specified * {@link IoProcessor}. */ public class SimpleIoProcessorPool implements IoProcessor { /** A logger for this class */ private final static Logger LOGGER = LoggerFactory.getLogger(SimpleIoProcessorPool.class); /** The default pool size, when no size is provided. */ private static final int DEFAULT_SIZE = Runtime.getRuntime().availableProcessors() + 1; /** A key used to store the processor pool in the session's Attributes */ private static final AttributeKey PROCESSOR = new AttributeKey(SimpleIoProcessorPool.class, "processor"); /** The pool table */ private final IoProcessor[] pool; /** The contained which is passed to the IoProcessor when they are created */ private final Executor executor; /** A flag set to true if we had to create an executor */ private final boolean createdExecutor; /** A lock to protect the disposal against concurrent calls */ private final Object disposalLock = new Object(); /** A flg set to true if the IoProcessor in the pool are being disposed */ private volatile boolean disposing; /** A flag set to true if all the IoProcessor contained in the pool have been disposed */ private volatile boolean disposed; /** * Creates a new instance of SimpleIoProcessorPool with a default * size of NbCPUs +1. * * @param processorType The type of IoProcessor to use */ public SimpleIoProcessorPool(Class> processorType) { this(processorType, null, DEFAULT_SIZE); } /** * Creates a new instance of SimpleIoProcessorPool with a defined * number of IoProcessors in the pool * * @param processorType The type of IoProcessor to use * @param size The number of IoProcessor in the pool */ public SimpleIoProcessorPool(Class> processorType, int size) { this(processorType, null, size); } /** * Creates a new instance of SimpleIoProcessorPool with an executor * * @param processorType The type of IoProcessor to use * @param executor The {@link Executor} */ public SimpleIoProcessorPool(Class> processorType, Executor executor) { this(processorType, executor, DEFAULT_SIZE); } /** * Creates a new instance of SimpleIoProcessorPool with an executor * * @param processorType The type of IoProcessor to use * @param executor The {@link Executor} * @param size The number of IoProcessor in the pool */ @SuppressWarnings("unchecked") public SimpleIoProcessorPool(Class> processorType, Executor executor, int size) { if (processorType == null) { throw new IllegalArgumentException("processorType"); } if (size <= 0) { throw new IllegalArgumentException("size: " + size + " (expected: positive integer)"); } // Create the executor if none is provided createdExecutor = (executor == null); if (createdExecutor) { this.executor = Executors.newCachedThreadPool(); // Set a default reject handler ((ThreadPoolExecutor) this.executor).setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); } else { this.executor = executor; } pool = new IoProcessor[size]; boolean success = false; Constructor> processorConstructor = null; boolean usesExecutorArg = true; try { // We create at least one processor try { try { processorConstructor = processorType.getConstructor(ExecutorService.class); pool[0] = processorConstructor.newInstance(this.executor); } catch (NoSuchMethodException e1) { // To the next step... try { processorConstructor = processorType.getConstructor(Executor.class); pool[0] = processorConstructor.newInstance(this.executor); } catch (NoSuchMethodException e2) { // To the next step... try { processorConstructor = processorType.getConstructor(); usesExecutorArg = false; pool[0] = processorConstructor.newInstance(); } catch (NoSuchMethodException e3) { // To the next step... } } } } catch (RuntimeException re) { LOGGER.error("Cannot create an IoProcessor :{}", re.getMessage()); throw re; } catch (Exception e) { String msg = "Failed to create a new instance of " + processorType.getName() + ":" + e.getMessage(); LOGGER.error(msg, e); throw new RuntimeIoException(msg, e); } if (processorConstructor == null) { // Raise an exception if no proper constructor is found. String msg = String.valueOf(processorType) + " must have a public constructor with one " + ExecutorService.class.getSimpleName() + " parameter, a public constructor with one " + Executor.class.getSimpleName() + " parameter or a public default constructor."; LOGGER.error(msg); throw new IllegalArgumentException(msg); } // Constructor found now use it for all subsequent instantiations for (int i = 1; i < pool.length; i++) { try { if (usesExecutorArg) { pool[i] = processorConstructor.newInstance(this.executor); } else { pool[i] = processorConstructor.newInstance(); } } catch (Exception e) { // Won't happen because it has been done previously } } success = true; } finally { if (!success) { dispose(); } } } /** * {@inheritDoc} */ public final void add(S session) { getProcessor(session).add(session); } /** * {@inheritDoc} */ public final void flush(S session) { getProcessor(session).flush(session); } /** * {@inheritDoc} */ public final void write(S session, WriteRequest writeRequest) { getProcessor(session).write(session, writeRequest); } /** * {@inheritDoc} */ public final void remove(S session) { getProcessor(session).remove(session); } /** * {@inheritDoc} */ public final void updateTrafficControl(S session) { getProcessor(session).updateTrafficControl(session); } /** * {@inheritDoc} */ public boolean isDisposed() { return disposed; } /** * {@inheritDoc} */ public boolean isDisposing() { return disposing; } /** * {@inheritDoc} */ public final void dispose() { if (disposed) { return; } synchronized (disposalLock) { if (!disposing) { disposing = true; for (IoProcessor ioProcessor : pool) { if (ioProcessor == null) { // Special case if the pool has not been initialized properly continue; } if (ioProcessor.isDisposing()) { continue; } try { ioProcessor.dispose(); } catch (Exception e) { LOGGER.warn("Failed to dispose the {} IoProcessor.", ioProcessor.getClass().getSimpleName(), e); } } if (createdExecutor) { ((ExecutorService) executor).shutdown(); } } Arrays.fill(pool, null); disposed = true; } } /** * Find the processor associated to a session. If it hasen't be stored into * the session's attributes, pick a new processor and stores it. */ @SuppressWarnings("unchecked") private IoProcessor getProcessor(S session) { IoProcessor processor = (IoProcessor) session.getAttribute(PROCESSOR); if (processor == null) { if (disposed || disposing) { throw new IllegalStateException("A disposed processor cannot be accessed."); } processor = pool[Math.abs((int) session.getId()) % pool.length]; if (processor == null) { throw new IllegalStateException("A disposed processor cannot be accessed."); } session.setAttributeIfAbsent(PROCESSOR, processor); } return processor; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/IoHandlerAdapter.java0000644000175000017500000000446512032276027031461 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.service; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An adapter class for {@link IoHandler}. You can extend this * class and selectively override required event handler methods only. All * methods do nothing by default. * * @author Apache MINA Project */ public class IoHandlerAdapter implements IoHandler { private static final Logger LOGGER = LoggerFactory.getLogger(IoHandlerAdapter.class); public void sessionCreated(IoSession session) throws Exception { // Empty handler } public void sessionOpened(IoSession session) throws Exception { // Empty handler } public void sessionClosed(IoSession session) throws Exception { // Empty handler } public void sessionIdle(IoSession session, IdleStatus status) throws Exception { // Empty handler } public void exceptionCaught(IoSession session, Throwable cause) throws Exception { if (LOGGER.isWarnEnabled()) { LOGGER.warn("EXCEPTION, please implement " + getClass().getName() + ".exceptionCaught() for proper handling:", cause); } } public void messageReceived(IoSession session, Object message) throws Exception { // Empty handler } public void messageSent(IoSession session, Object message) throws Exception { // Empty handler } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/TransportMetadata.java0000644000175000017500000000445512032276027031747 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.service; import java.net.SocketAddress; import java.util.Set; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionConfig; /** * Provides meta-information that describes an {@link IoService}. * * @author Apache MINA Project */ public interface TransportMetadata { /** * Returns the name of the service provider (e.g. "nio", "apr" and "rxtx"). */ String getProviderName(); /** * Returns the name of the service. */ String getName(); /** * Returns true if the session of this transport type is * connectionless. */ boolean isConnectionless(); /** * Returns {@code true} if the messages exchanged by the service can be * fragmented * or reassembled by its underlying transport. */ boolean hasFragmentation(); /** * Returns the address type of the service. */ Class getAddressType(); /** * Returns the set of the allowed message type when you write to an * {@link IoSession} that is managed by the service. */ Set> getEnvelopeTypes(); /** * Returns the type of the {@link IoSessionConfig} of the service */ Class getSessionConfigType(); } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/IoServiceListenerSupport.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/IoServiceListenerSupport.j0000644000175000017500000002312312032276027032606 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.service; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.future.IoFuture; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.session.IoSession; import org.apache.mina.util.ExceptionMonitor; /** * A helper class which provides addition and removal of {@link IoServiceListener}s and firing * events. * * @author Apache MINA Project */ public class IoServiceListenerSupport { /** The {@link IoService} that this instance manages. */ private final IoService service; /** A list of {@link IoServiceListener}s. */ private final List listeners = new CopyOnWriteArrayList(); /** Tracks managed sessions. */ private final ConcurrentMap managedSessions = new ConcurrentHashMap(); /** Read only version of {@link #managedSessions}. */ private final Map readOnlyManagedSessions = Collections.unmodifiableMap(managedSessions); private final AtomicBoolean activated = new AtomicBoolean(); /** Time this listenerSupport has been activated */ private volatile long activationTime; /** A counter used to store the maximum sessions we managed since the listenerSupport has been activated */ private volatile int largestManagedSessionCount = 0; /** A global counter to count the number of sessions managed since the start */ private volatile long cumulativeManagedSessionCount = 0; /** * Creates a new instance of the listenerSupport. * * @param service The associated IoService */ public IoServiceListenerSupport(IoService service) { if (service == null) { throw new IllegalArgumentException("service"); } this.service = service; } /** * Adds a new listener. * * @param listener The added listener */ public void add(IoServiceListener listener) { if (listener != null) { listeners.add(listener); } } /** * Removes an existing listener. * * @param listener The listener to remove */ public void remove(IoServiceListener listener) { if (listener != null) { listeners.remove(listener); } } /** * @return The time (in ms) this instance has been activated */ public long getActivationTime() { return activationTime; } public Map getManagedSessions() { return readOnlyManagedSessions; } public int getManagedSessionCount() { return managedSessions.size(); } /** * @return The largest number of managed session since the creation of this * listenerSupport */ public int getLargestManagedSessionCount() { return largestManagedSessionCount; } /** * @return The total number of sessions managed since the initilization of this * ListenerSupport */ public long getCumulativeManagedSessionCount() { return cumulativeManagedSessionCount; } /** * @return true if the instance is active */ public boolean isActive() { return activated.get(); } /** * Calls {@link IoServiceListener#serviceActivated(IoService)} * for all registered listeners. */ public void fireServiceActivated() { if (!activated.compareAndSet(false, true)) { // The instance is already active return; } activationTime = System.currentTimeMillis(); // Activate all the listeners now for (IoServiceListener listener : listeners) { try { listener.serviceActivated(service); } catch (Throwable e) { ExceptionMonitor.getInstance().exceptionCaught(e); } } } /** * Calls {@link IoServiceListener#serviceDeactivated(IoService)} * for all registered listeners. */ public void fireServiceDeactivated() { if (!activated.compareAndSet(true, false)) { // The instance is already desactivated return; } // Desactivate all the listeners try { for (IoServiceListener listener : listeners) { try { listener.serviceDeactivated(service); } catch (Throwable e) { ExceptionMonitor.getInstance().exceptionCaught(e); } } } finally { disconnectSessions(); } } /** * Calls {@link IoServiceListener#sessionCreated(IoSession)} for all registered listeners. * * @param session The session which has been created */ public void fireSessionCreated(IoSession session) { boolean firstSession = false; if (session.getService() instanceof IoConnector) { synchronized (managedSessions) { firstSession = managedSessions.isEmpty(); } } // If already registered, ignore. if (managedSessions.putIfAbsent(session.getId(), session) != null) { return; } // If the first connector session, fire a virtual service activation event. if (firstSession) { fireServiceActivated(); } // Fire session events. IoFilterChain filterChain = session.getFilterChain(); filterChain.fireSessionCreated(); filterChain.fireSessionOpened(); int managedSessionCount = managedSessions.size(); if (managedSessionCount > largestManagedSessionCount) { largestManagedSessionCount = managedSessionCount; } cumulativeManagedSessionCount++; // Fire listener events. for (IoServiceListener l : listeners) { try { l.sessionCreated(session); } catch (Throwable e) { ExceptionMonitor.getInstance().exceptionCaught(e); } } } /** * Calls {@link IoServiceListener#sessionDestroyed(IoSession)} for all registered listeners. * * @param session The session which has been destroyed */ public void fireSessionDestroyed(IoSession session) { // Try to remove the remaining empty session set after removal. if (managedSessions.remove(session.getId()) == null) { return; } // Fire session events. session.getFilterChain().fireSessionClosed(); // Fire listener events. try { for (IoServiceListener l : listeners) { try { l.sessionDestroyed(session); } catch (Throwable e) { ExceptionMonitor.getInstance().exceptionCaught(e); } } } finally { // Fire a virtual service deactivation event for the last session of the connector. if (session.getService() instanceof IoConnector) { boolean lastSession = false; synchronized (managedSessions) { lastSession = managedSessions.isEmpty(); } if (lastSession) { fireServiceDeactivated(); } } } } /** * Close all the sessions * TODO disconnectSessions. * */ private void disconnectSessions() { if (!(service instanceof IoAcceptor)) { // We don't disconnect sessions for anything but an Acceptor return; } if (!((IoAcceptor) service).isCloseOnDeactivation()) { return; } Object lock = new Object(); IoFutureListener listener = new LockNotifyingListener(lock); for (IoSession s : managedSessions.values()) { s.close(true).addListener(listener); } try { synchronized (lock) { while (!managedSessions.isEmpty()) { lock.wait(500); } } } catch (InterruptedException ie) { // Ignored } } /** * A listener in charge of releasing the lock when the close has been completed */ private static class LockNotifyingListener implements IoFutureListener { private final Object lock; public LockNotifyingListener(Object lock) { this.lock = lock; } public void operationComplete(IoFuture future) { synchronized (lock) { lock.notifyAll(); } } } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/DefaultTransportMetadata.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/DefaultTransportMetadata.j0000644000175000017500000001001112032276027032545 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.service; import java.net.SocketAddress; import java.util.Collections; import java.util.Set; import org.apache.mina.core.session.IoSessionConfig; import org.apache.mina.util.IdentityHashSet; /** * A default immutable implementation of {@link TransportMetadata}. * * @author Apache MINA Project */ public class DefaultTransportMetadata implements TransportMetadata { private final String providerName; private final String name; private final boolean connectionless; private final boolean fragmentation; private final Class addressType; private final Class sessionConfigType; private final Set> envelopeTypes; public DefaultTransportMetadata(String providerName, String name, boolean connectionless, boolean fragmentation, Class addressType, Class sessionConfigType, Class... envelopeTypes) { if (providerName == null) { throw new IllegalArgumentException("providerName"); } if (name == null) { throw new IllegalArgumentException("name"); } providerName = providerName.trim().toLowerCase(); if (providerName.length() == 0) { throw new IllegalArgumentException("providerName is empty."); } name = name.trim().toLowerCase(); if (name.length() == 0) { throw new IllegalArgumentException("name is empty."); } if (addressType == null) { throw new IllegalArgumentException("addressType"); } if (envelopeTypes == null) { throw new IllegalArgumentException("envelopeTypes"); } if (envelopeTypes.length == 0) { throw new IllegalArgumentException("envelopeTypes is empty."); } if (sessionConfigType == null) { throw new IllegalArgumentException("sessionConfigType"); } this.providerName = providerName; this.name = name; this.connectionless = connectionless; this.fragmentation = fragmentation; this.addressType = addressType; this.sessionConfigType = sessionConfigType; Set> newEnvelopeTypes = new IdentityHashSet>(); for (Class c : envelopeTypes) { newEnvelopeTypes.add(c); } this.envelopeTypes = Collections.unmodifiableSet(newEnvelopeTypes); } public Class getAddressType() { return addressType; } public Set> getEnvelopeTypes() { return envelopeTypes; } public Class getSessionConfigType() { return sessionConfigType; } public String getProviderName() { return providerName; } public String getName() { return name; } public boolean isConnectionless() { return connectionless; } public boolean hasFragmentation() { return fragmentation; } @Override public String toString() { return name; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/AbstractIoConnector.java0000644000175000017500000002417112032276027032215 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.service; import java.net.SocketAddress; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.IoFuture; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionConfig; import org.apache.mina.core.session.IoSessionInitializer; /** * A base implementation of {@link IoConnector}. * * @author Apache MINA Project */ public abstract class AbstractIoConnector extends AbstractIoService implements IoConnector { /** * The minimum timeout value that is supported (in milliseconds). */ private long connectTimeoutCheckInterval = 50L; private long connectTimeoutInMillis = 60 * 1000L; // 1 minute by default private SocketAddress defaultRemoteAddress; /** * Constructor for {@link AbstractIoConnector}. You need to provide a default * session configuration and an {@link Executor} for handling I/O events. If * null {@link Executor} is provided, a default one will be created using * {@link Executors#newCachedThreadPool()}. * * {@see AbstractIoService#AbstractIoService(IoSessionConfig, Executor)} * * @param sessionConfig * the default configuration for the managed {@link IoSession} * @param executor * the {@link Executor} used for handling execution of I/O * events. Can be null. */ protected AbstractIoConnector(IoSessionConfig sessionConfig, Executor executor) { super(sessionConfig, executor); } /** * Returns the minimum connection timeout value for this connector * * @return * The minimum time that this connector can have for a connection * timeout in milliseconds. */ public long getConnectTimeoutCheckInterval() { return connectTimeoutCheckInterval; } public void setConnectTimeoutCheckInterval(long minimumConnectTimeout) { if (getConnectTimeoutMillis() < minimumConnectTimeout) { this.connectTimeoutInMillis = minimumConnectTimeout; } this.connectTimeoutCheckInterval = minimumConnectTimeout; } /** * @deprecated * Take a look at getConnectTimeoutMillis() */ public final int getConnectTimeout() { return (int) connectTimeoutInMillis / 1000; } /** * {@inheritDoc} */ public final long getConnectTimeoutMillis() { return connectTimeoutInMillis; } /** * @deprecated * Take a look at setConnectTimeoutMillis(long) */ public final void setConnectTimeout(int connectTimeout) { setConnectTimeoutMillis(connectTimeout * 1000L); } /** * Sets the connect timeout value in milliseconds. * */ public final void setConnectTimeoutMillis(long connectTimeoutInMillis) { if (connectTimeoutInMillis <= connectTimeoutCheckInterval) { this.connectTimeoutCheckInterval = connectTimeoutInMillis; } this.connectTimeoutInMillis = connectTimeoutInMillis; } /** * {@inheritDoc} */ public SocketAddress getDefaultRemoteAddress() { return defaultRemoteAddress; } /** * {@inheritDoc} */ public final void setDefaultRemoteAddress(SocketAddress defaultRemoteAddress) { if (defaultRemoteAddress == null) { throw new IllegalArgumentException("defaultRemoteAddress"); } if (!getTransportMetadata().getAddressType().isAssignableFrom(defaultRemoteAddress.getClass())) { throw new IllegalArgumentException("defaultRemoteAddress type: " + defaultRemoteAddress.getClass() + " (expected: " + getTransportMetadata().getAddressType() + ")"); } this.defaultRemoteAddress = defaultRemoteAddress; } /** * {@inheritDoc} */ public final ConnectFuture connect() { SocketAddress defaultRemoteAddress = getDefaultRemoteAddress(); if (defaultRemoteAddress == null) { throw new IllegalStateException("defaultRemoteAddress is not set."); } return connect(defaultRemoteAddress, null, null); } /** * {@inheritDoc} */ public ConnectFuture connect(IoSessionInitializer sessionInitializer) { SocketAddress defaultRemoteAddress = getDefaultRemoteAddress(); if (defaultRemoteAddress == null) { throw new IllegalStateException("defaultRemoteAddress is not set."); } return connect(defaultRemoteAddress, null, sessionInitializer); } /** * {@inheritDoc} */ public final ConnectFuture connect(SocketAddress remoteAddress) { return connect(remoteAddress, null, null); } /** * {@inheritDoc} */ public ConnectFuture connect(SocketAddress remoteAddress, IoSessionInitializer sessionInitializer) { return connect(remoteAddress, null, sessionInitializer); } /** * {@inheritDoc} */ public ConnectFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) { return connect(remoteAddress, localAddress, null); } /** * {@inheritDoc} */ public final ConnectFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, IoSessionInitializer sessionInitializer) { if (isDisposing()) { throw new IllegalStateException("The connector has been disposed."); } if (remoteAddress == null) { throw new IllegalArgumentException("remoteAddress"); } if (!getTransportMetadata().getAddressType().isAssignableFrom(remoteAddress.getClass())) { throw new IllegalArgumentException("remoteAddress type: " + remoteAddress.getClass() + " (expected: " + getTransportMetadata().getAddressType() + ")"); } if (localAddress != null && !getTransportMetadata().getAddressType().isAssignableFrom(localAddress.getClass())) { throw new IllegalArgumentException("localAddress type: " + localAddress.getClass() + " (expected: " + getTransportMetadata().getAddressType() + ")"); } if (getHandler() == null) { if (getSessionConfig().isUseReadOperation()) { setHandler(new IoHandler() { public void exceptionCaught(IoSession session, Throwable cause) throws Exception { // Empty handler } public void messageReceived(IoSession session, Object message) throws Exception { // Empty handler } public void messageSent(IoSession session, Object message) throws Exception { // Empty handler } public void sessionClosed(IoSession session) throws Exception { // Empty handler } public void sessionCreated(IoSession session) throws Exception { // Empty handler } public void sessionIdle(IoSession session, IdleStatus status) throws Exception { // Empty handler } public void sessionOpened(IoSession session) throws Exception { // Empty handler } }); } else { throw new IllegalStateException("handler is not set."); } } return connect0(remoteAddress, localAddress, sessionInitializer); } /** * Implement this method to perform the actual connect operation. * * @param localAddress null if no local address is specified */ protected abstract ConnectFuture connect0(SocketAddress remoteAddress, SocketAddress localAddress, IoSessionInitializer sessionInitializer); /** * Adds required internal attributes and {@link IoFutureListener}s * related with event notifications to the specified {@code session} * and {@code future}. Do not call this method directly; * {@link #finishSessionInitialization(IoSession, IoFuture, IoSessionInitializer)} * will call this method instead. */ @Override protected final void finishSessionInitialization0(final IoSession session, IoFuture future) { // In case that ConnectFuture.cancel() is invoked before // setSession() is invoked, add a listener that closes the // connection immediately on cancellation. future.addListener(new IoFutureListener() { public void operationComplete(ConnectFuture future) { if (future.isCanceled()) { session.close(true); } } }); } /** * {@inheritDoc} */ @Override public String toString() { TransportMetadata m = getTransportMetadata(); return '(' + m.getProviderName() + ' ' + m.getName() + " connector: " + "managedSessionCount: " + getManagedSessionCount() + ')'; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/IoHandler.java0000644000175000017500000000576212032276027030161 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.service; import java.io.IOException; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; /** * Handles all I/O events fired by MINA. * * @author Apache MINA Project * * @see IoHandlerAdapter */ public interface IoHandler { /** * Invoked from an I/O processor thread when a new connection has been created. * Because this method is supposed to be called from the same thread that * handles I/O of multiple sessions, please implement this method to perform * tasks that consumes minimal amount of time such as socket parameter * and user-defined session attribute initialization. */ void sessionCreated(IoSession session) throws Exception; /** * Invoked when a connection has been opened. This method is invoked after * {@link #sessionCreated(IoSession)}. The biggest difference from * {@link #sessionCreated(IoSession)} is that it's invoked from other thread * than an I/O processor thread once thread model is configured properly. */ void sessionOpened(IoSession session) throws Exception; /** * Invoked when a connection is closed. */ void sessionClosed(IoSession session) throws Exception; /** * Invoked with the related {@link IdleStatus} when a connection becomes idle. * This method is not invoked if the transport type is UDP; it's a known bug, * and will be fixed in 2.0. */ void sessionIdle(IoSession session, IdleStatus status) throws Exception; /** * Invoked when any exception is thrown by user {@link IoHandler} * implementation or by MINA. If cause is an instance of * {@link IOException}, MINA will close the connection automatically. */ void exceptionCaught(IoSession session, Throwable cause) throws Exception; /** * Invoked when a message is received. */ void messageReceived(IoSession session, Object message) throws Exception; /** * Invoked when a message written by {@link IoSession#write(Object)} is * sent out. */ void messageSent(IoSession session, Object message) throws Exception; }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/IoServiceListener.java0000644000175000017500000000412512032276027031702 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.service; import java.util.EventListener; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; /** * Listens to events related to an {@link IoService}. * * @author Apache MINA Project */ public interface IoServiceListener extends EventListener { /** * Invoked when a new service is activated by an {@link IoService}. * * @param service the {@link IoService} */ void serviceActivated(IoService service) throws Exception; /** * Invoked when a service is idle. */ void serviceIdle(IoService service, IdleStatus idleStatus) throws Exception; /** * Invoked when a service is deactivated by an {@link IoService}. * * @param service the {@link IoService} */ void serviceDeactivated(IoService service) throws Exception; /** * Invoked when a new session is created by an {@link IoService}. * * @param session the new session */ void sessionCreated(IoSession session) throws Exception; /** * Invoked when a session is being destroyed by an {@link IoService}. * * @param session the session to be destroyed */ void sessionDestroyed(IoSession session) throws Exception; } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/IoServiceStatistics.java0000644000175000017500000003003312032276027032244 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.service; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; /** * Provides usage statistics for an {@link AbstractIoService} instance. * * @author Apache MINA Project * @since 2.0.0-M3 */ public class IoServiceStatistics { private AbstractIoService service; private double readBytesThroughput; private double writtenBytesThroughput; private double readMessagesThroughput; private double writtenMessagesThroughput; private double largestReadBytesThroughput; private double largestWrittenBytesThroughput; private double largestReadMessagesThroughput; private double largestWrittenMessagesThroughput; private final AtomicLong readBytes = new AtomicLong(); private final AtomicLong writtenBytes = new AtomicLong(); private final AtomicLong readMessages = new AtomicLong(); private final AtomicLong writtenMessages = new AtomicLong(); private long lastReadTime; private long lastWriteTime; private long lastReadBytes; private long lastWrittenBytes; private long lastReadMessages; private long lastWrittenMessages; private long lastThroughputCalculationTime; private final AtomicInteger scheduledWriteBytes = new AtomicInteger(); private final AtomicInteger scheduledWriteMessages = new AtomicInteger(); private int throughputCalculationInterval = 3; private final Object throughputCalculationLock = new Object(); public IoServiceStatistics(AbstractIoService service) { this.service = service; } /** * Returns the maximum number of sessions which were being managed at the * same time. */ public final int getLargestManagedSessionCount() { return service.getListeners().getLargestManagedSessionCount(); } /** * Returns the cumulative number of sessions which were managed (or are * being managed) by this service, which means 'currently managed session * count + closed session count'. */ public final long getCumulativeManagedSessionCount() { return service.getListeners().getCumulativeManagedSessionCount(); } /** * Returns the time in millis when I/O occurred lastly. */ public final long getLastIoTime() { return Math.max(lastReadTime, lastWriteTime); } /** * Returns the time in millis when read operation occurred lastly. */ public final long getLastReadTime() { return lastReadTime; } /** * Returns the time in millis when write operation occurred lastly. */ public final long getLastWriteTime() { return lastWriteTime; } /** * Returns the number of bytes read by this service * * @return * The number of bytes this service has read */ public final long getReadBytes() { return readBytes.get(); } /** * Returns the number of bytes written out by this service * * @return * The number of bytes this service has written */ public final long getWrittenBytes() { return writtenBytes.get(); } /** * Returns the number of messages this services has read * * @return * The number of messages this services has read */ public final long getReadMessages() { return readMessages.get(); } /** * Returns the number of messages this service has written * * @return * The number of messages this service has written */ public final long getWrittenMessages() { return writtenMessages.get(); } /** * Returns the number of read bytes per second. */ public final double getReadBytesThroughput() { resetThroughput(); return readBytesThroughput; } /** * Returns the number of written bytes per second. */ public final double getWrittenBytesThroughput() { resetThroughput(); return writtenBytesThroughput; } /** * Returns the number of read messages per second. */ public final double getReadMessagesThroughput() { resetThroughput(); return readMessagesThroughput; } /** * Returns the number of written messages per second. */ public final double getWrittenMessagesThroughput() { resetThroughput(); return writtenMessagesThroughput; } /** * Returns the maximum of the {@link #getReadBytesThroughput() readBytesThroughput}. */ public final double getLargestReadBytesThroughput() { return largestReadBytesThroughput; } /** * Returns the maximum of the {@link #getWrittenBytesThroughput() writtenBytesThroughput}. */ public final double getLargestWrittenBytesThroughput() { return largestWrittenBytesThroughput; } /** * Returns the maximum of the {@link #getReadMessagesThroughput() readMessagesThroughput}. */ public final double getLargestReadMessagesThroughput() { return largestReadMessagesThroughput; } /** * Returns the maximum of the {@link #getWrittenMessagesThroughput() writtenMessagesThroughput}. */ public final double getLargestWrittenMessagesThroughput() { return largestWrittenMessagesThroughput; } /** * Returns the interval (seconds) between each throughput calculation. * The default value is 3 seconds. */ public final int getThroughputCalculationInterval() { return throughputCalculationInterval; } /** * Returns the interval (milliseconds) between each throughput calculation. * The default value is 3 seconds. */ public final long getThroughputCalculationIntervalInMillis() { return throughputCalculationInterval * 1000L; } /** * Sets the interval (seconds) between each throughput calculation. The * default value is 3 seconds. */ public final void setThroughputCalculationInterval(int throughputCalculationInterval) { if (throughputCalculationInterval < 0) { throw new IllegalArgumentException("throughputCalculationInterval: " + throughputCalculationInterval); } this.throughputCalculationInterval = throughputCalculationInterval; } /** * Sets last time at which a read occurred on the service. */ protected final void setLastReadTime(long lastReadTime) { this.lastReadTime = lastReadTime; } /** * Sets last time at which a write occurred on the service. */ protected final void setLastWriteTime(long lastWriteTime) { this.lastWriteTime = lastWriteTime; } /** * Resets the throughput counters of the service if none session * is currently managed. */ private void resetThroughput() { if (service.getManagedSessionCount() == 0) { readBytesThroughput = 0; writtenBytesThroughput = 0; readMessagesThroughput = 0; writtenMessagesThroughput = 0; } } /** * Updates the throughput counters. */ public void updateThroughput(long currentTime) { synchronized (throughputCalculationLock) { int interval = (int) (currentTime - lastThroughputCalculationTime); long minInterval = getThroughputCalculationIntervalInMillis(); if (minInterval == 0 || interval < minInterval) { return; } long readBytes = this.readBytes.get(); long writtenBytes = this.writtenBytes.get(); long readMessages = this.readMessages.get(); long writtenMessages = this.writtenMessages.get(); readBytesThroughput = (readBytes - lastReadBytes) * 1000.0 / interval; writtenBytesThroughput = (writtenBytes - lastWrittenBytes) * 1000.0 / interval; readMessagesThroughput = (readMessages - lastReadMessages) * 1000.0 / interval; writtenMessagesThroughput = (writtenMessages - lastWrittenMessages) * 1000.0 / interval; if (readBytesThroughput > largestReadBytesThroughput) { largestReadBytesThroughput = readBytesThroughput; } if (writtenBytesThroughput > largestWrittenBytesThroughput) { largestWrittenBytesThroughput = writtenBytesThroughput; } if (readMessagesThroughput > largestReadMessagesThroughput) { largestReadMessagesThroughput = readMessagesThroughput; } if (writtenMessagesThroughput > largestWrittenMessagesThroughput) { largestWrittenMessagesThroughput = writtenMessagesThroughput; } lastReadBytes = readBytes; lastWrittenBytes = writtenBytes; lastReadMessages = readMessages; lastWrittenMessages = writtenMessages; lastThroughputCalculationTime = currentTime; } } /** * Increases the count of read bytes by increment and sets * the last read time to currentTime. */ public final void increaseReadBytes(long increment, long currentTime) { readBytes.addAndGet(increment); lastReadTime = currentTime; } /** * Increases the count of read messages by 1 and sets the last read time to * currentTime. */ public final void increaseReadMessages(long currentTime) { readMessages.incrementAndGet(); lastReadTime = currentTime; } /** * Increases the count of written bytes by increment and sets * the last write time to currentTime. */ public final void increaseWrittenBytes(int increment, long currentTime) { writtenBytes.addAndGet(increment); lastWriteTime = currentTime; } /** * Increases the count of written messages by 1 and sets the last write time to * currentTime. */ public final void increaseWrittenMessages(long currentTime) { writtenMessages.incrementAndGet(); lastWriteTime = currentTime; } /** * Returns the count of bytes scheduled for write. */ public final int getScheduledWriteBytes() { return scheduledWriteBytes.get(); } /** * Increments by increment the count of bytes scheduled for write. */ public final void increaseScheduledWriteBytes(int increment) { scheduledWriteBytes.addAndGet(increment); } /** * Returns the count of messages scheduled for write. */ public final int getScheduledWriteMessages() { return scheduledWriteMessages.get(); } /** * Increments by 1 the count of messages scheduled for write. */ public final void increaseScheduledWriteMessages() { scheduledWriteMessages.incrementAndGet(); } /** * Decrements by 1 the count of messages scheduled for write. */ public final void decreaseScheduledWriteMessages() { scheduledWriteMessages.decrementAndGet(); } /** * Sets the time at which throughtput counters where updated. */ protected void setLastThroughputCalculationTime(long lastThroughputCalculationTime) { this.lastThroughputCalculationTime = lastThroughputCalculationTime; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/AbstractIoService.java0000644000175000017500000004104012032276027031655 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.service; import java.util.AbstractSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.apache.mina.core.IoUtil; import org.apache.mina.core.filterchain.DefaultIoFilterChain; import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; import org.apache.mina.core.filterchain.IoFilterChainBuilder; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.DefaultIoFuture; import org.apache.mina.core.future.IoFuture; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.session.AbstractIoSession; import org.apache.mina.core.session.DefaultIoSessionDataStructureFactory; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionConfig; import org.apache.mina.core.session.IoSessionDataStructureFactory; import org.apache.mina.core.session.IoSessionInitializationException; import org.apache.mina.core.session.IoSessionInitializer; import org.apache.mina.util.ExceptionMonitor; import org.apache.mina.util.NamePreservingRunnable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Base implementation of {@link IoService}s. * * An instance of IoService contains an Executor which will handle the incoming * events. * * @author Apache MINA Project */ public abstract class AbstractIoService implements IoService { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractIoService.class); /** * The unique number identifying the Service. It's incremented * for each new IoService created. */ private static final AtomicInteger id = new AtomicInteger(); /** * The thread name built from the IoService inherited * instance class name and the IoService Id **/ private final String threadName; /** * The associated executor, responsible for handling execution of I/O events. */ private final Executor executor; /** * A flag used to indicate that the local executor has been created * inside this instance, and not passed by a caller. * * If the executor is locally created, then it will be an instance * of the ThreadPoolExecutor class. */ private final boolean createdExecutor; /** * The IoHandler in charge of managing all the I/O Events. It is */ private IoHandler handler; /** * The default {@link IoSessionConfig} which will be used to configure new sessions. */ private final IoSessionConfig sessionConfig; private final IoServiceListener serviceActivationListener = new IoServiceListener() { public void serviceActivated(IoService service) { // Update lastIoTime. AbstractIoService s = (AbstractIoService) service; IoServiceStatistics _stats = s.getStatistics(); _stats.setLastReadTime(s.getActivationTime()); _stats.setLastWriteTime(s.getActivationTime()); _stats.setLastThroughputCalculationTime(s.getActivationTime()); } public void serviceDeactivated(IoService service) { // Empty handler } public void serviceIdle(IoService service, IdleStatus idleStatus) { // Empty handler } public void sessionCreated(IoSession session) { // Empty handler } public void sessionDestroyed(IoSession session) { // Empty handler } }; /** * Current filter chain builder. */ private IoFilterChainBuilder filterChainBuilder = new DefaultIoFilterChainBuilder(); private IoSessionDataStructureFactory sessionDataStructureFactory = new DefaultIoSessionDataStructureFactory(); /** * Maintains the {@link IoServiceListener}s of this service. */ private final IoServiceListenerSupport listeners; /** * A lock object which must be acquired when related resources are * destroyed. */ protected final Object disposalLock = new Object(); private volatile boolean disposing; private volatile boolean disposed; /** * {@inheritDoc} */ private IoServiceStatistics stats = new IoServiceStatistics(this); /** * Constructor for {@link AbstractIoService}. You need to provide a default * session configuration and an {@link Executor} for handling I/O events. If * a null {@link Executor} is provided, a default one will be created using * {@link Executors#newCachedThreadPool()}. * * @param sessionConfig * the default configuration for the managed {@link IoSession} * @param executor * the {@link Executor} used for handling execution of I/O * events. Can be null. */ protected AbstractIoService(IoSessionConfig sessionConfig, Executor executor) { if (sessionConfig == null) { throw new IllegalArgumentException("sessionConfig"); } if (getTransportMetadata() == null) { throw new IllegalArgumentException("TransportMetadata"); } if (!getTransportMetadata().getSessionConfigType().isAssignableFrom(sessionConfig.getClass())) { throw new IllegalArgumentException("sessionConfig type: " + sessionConfig.getClass() + " (expected: " + getTransportMetadata().getSessionConfigType() + ")"); } // Create the listeners, and add a first listener : a activation listener // for this service, which will give information on the service state. listeners = new IoServiceListenerSupport(this); listeners.add(serviceActivationListener); // Stores the given session configuration this.sessionConfig = sessionConfig; // Make JVM load the exception monitor before some transports // change the thread context class loader. ExceptionMonitor.getInstance(); if (executor == null) { this.executor = Executors.newCachedThreadPool(); createdExecutor = true; } else { this.executor = executor; createdExecutor = false; } threadName = getClass().getSimpleName() + '-' + id.incrementAndGet(); } /** * {@inheritDoc} */ public final IoFilterChainBuilder getFilterChainBuilder() { return filterChainBuilder; } /** * {@inheritDoc} */ public final void setFilterChainBuilder(IoFilterChainBuilder builder) { if (builder == null) { builder = new DefaultIoFilterChainBuilder(); } filterChainBuilder = builder; } /** * {@inheritDoc} */ public final DefaultIoFilterChainBuilder getFilterChain() { if (filterChainBuilder instanceof DefaultIoFilterChainBuilder) { return (DefaultIoFilterChainBuilder) filterChainBuilder; } throw new IllegalStateException("Current filter chain builder is not a DefaultIoFilterChainBuilder."); } /** * {@inheritDoc} */ public final void addListener(IoServiceListener listener) { listeners.add(listener); } /** * {@inheritDoc} */ public final void removeListener(IoServiceListener listener) { listeners.remove(listener); } /** * {@inheritDoc} */ public final boolean isActive() { return listeners.isActive(); } /** * {@inheritDoc} */ public final boolean isDisposing() { return disposing; } /** * {@inheritDoc} */ public final boolean isDisposed() { return disposed; } /** * {@inheritDoc} */ public final void dispose() { dispose(false); } /** * {@inheritDoc} */ public final void dispose(boolean awaitTermination) { if (disposed) { return; } synchronized (disposalLock) { if (!disposing) { disposing = true; try { dispose0(); } catch (Exception e) { ExceptionMonitor.getInstance().exceptionCaught(e); } } } if (createdExecutor) { ExecutorService e = (ExecutorService) executor; e.shutdownNow(); if (awaitTermination) { //Thread.currentThread().setName(); try { LOGGER.debug("awaitTermination on {} called by thread=[{}]", this, Thread.currentThread().getName()); e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS); LOGGER.debug("awaitTermination on {} finished", this); } catch (InterruptedException e1) { LOGGER.warn("awaitTermination on [{}] was interrupted", this); // Restore the interrupted status Thread.currentThread().interrupt(); } } } disposed = true; } /** * Implement this method to release any acquired resources. This method * is invoked only once by {@link #dispose()}. */ protected abstract void dispose0() throws Exception; /** * {@inheritDoc} */ public final Map getManagedSessions() { return listeners.getManagedSessions(); } /** * {@inheritDoc} */ public final int getManagedSessionCount() { return listeners.getManagedSessionCount(); } /** * {@inheritDoc} */ public final IoHandler getHandler() { return handler; } /** * {@inheritDoc} */ public final void setHandler(IoHandler handler) { if (handler == null) { throw new IllegalArgumentException("handler cannot be null"); } if (isActive()) { throw new IllegalStateException("handler cannot be set while the service is active."); } this.handler = handler; } /** * {@inheritDoc} */ public IoSessionConfig getSessionConfig() { return sessionConfig; } /** * {@inheritDoc} */ public final IoSessionDataStructureFactory getSessionDataStructureFactory() { return sessionDataStructureFactory; } /** * {@inheritDoc} */ public final void setSessionDataStructureFactory(IoSessionDataStructureFactory sessionDataStructureFactory) { if (sessionDataStructureFactory == null) { throw new IllegalArgumentException("sessionDataStructureFactory"); } if (isActive()) { throw new IllegalStateException("sessionDataStructureFactory cannot be set while the service is active."); } this.sessionDataStructureFactory = sessionDataStructureFactory; } /** * {@inheritDoc} */ public IoServiceStatistics getStatistics() { return stats; } /** * {@inheritDoc} */ public final long getActivationTime() { return listeners.getActivationTime(); } /** * {@inheritDoc} */ public final Set broadcast(Object message) { // Convert to Set. We do not return a List here because only the // direct caller of MessageBroadcaster knows the order of write // operations. final List futures = IoUtil.broadcast(message, getManagedSessions().values()); return new AbstractSet() { @Override public Iterator iterator() { return futures.iterator(); } @Override public int size() { return futures.size(); } }; } public final IoServiceListenerSupport getListeners() { return listeners; } protected final void executeWorker(Runnable worker) { executeWorker(worker, null); } protected final void executeWorker(Runnable worker, String suffix) { String actualThreadName = threadName; if (suffix != null) { actualThreadName = actualThreadName + '-' + suffix; } executor.execute(new NamePreservingRunnable(worker, actualThreadName)); } // TODO Figure out make it work without causing a compiler error / warning. @SuppressWarnings("unchecked") protected final void initSession(IoSession session, IoFuture future, IoSessionInitializer sessionInitializer) { // Update lastIoTime if needed. if (stats.getLastReadTime() == 0) { stats.setLastReadTime(getActivationTime()); } if (stats.getLastWriteTime() == 0) { stats.setLastWriteTime(getActivationTime()); } // Every property but attributeMap should be set now. // Now initialize the attributeMap. The reason why we initialize // the attributeMap at last is to make sure all session properties // such as remoteAddress are provided to IoSessionDataStructureFactory. try { ((AbstractIoSession) session).setAttributeMap(session.getService().getSessionDataStructureFactory() .getAttributeMap(session)); } catch (IoSessionInitializationException e) { throw e; } catch (Exception e) { throw new IoSessionInitializationException("Failed to initialize an attributeMap.", e); } try { ((AbstractIoSession) session).setWriteRequestQueue(session.getService().getSessionDataStructureFactory() .getWriteRequestQueue(session)); } catch (IoSessionInitializationException e) { throw e; } catch (Exception e) { throw new IoSessionInitializationException("Failed to initialize a writeRequestQueue.", e); } if ((future != null) && (future instanceof ConnectFuture)) { // DefaultIoFilterChain will notify the future. (We support ConnectFuture only for now). session.setAttribute(DefaultIoFilterChain.SESSION_CREATED_FUTURE, future); } if (sessionInitializer != null) { sessionInitializer.initializeSession(session, future); } finishSessionInitialization0(session, future); } /** * Implement this method to perform additional tasks required for session * initialization. Do not call this method directly; * {@link #initSession(IoSession, IoFuture, IoSessionInitializer)} will call * this method instead. */ protected void finishSessionInitialization0(IoSession session, IoFuture future) { // Do nothing. Extended class might add some specific code } protected static class ServiceOperationFuture extends DefaultIoFuture { public ServiceOperationFuture() { super(null); } public final boolean isDone() { return getValue() == Boolean.TRUE; } public final void setDone() { setValue(Boolean.TRUE); } public final Exception getException() { if (getValue() instanceof Exception) { return (Exception) getValue(); } return null; } public final void setException(Exception exception) { if (exception == null) { throw new IllegalArgumentException("exception"); } setValue(exception); } } /** * {@inheritDoc} */ public int getScheduledWriteBytes() { return stats.getScheduledWriteBytes(); } /** * {@inheritDoc} */ public int getScheduledWriteMessages() { return stats.getScheduledWriteMessages(); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/IoAcceptor.java0000644000175000017500000002061412032276027030335 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.service; import java.io.IOException; import java.net.SocketAddress; import java.util.List; import java.util.Set; import org.apache.mina.core.session.IoSession; /** * Accepts incoming connection, communicates with clients, and fires events to * {@link IoHandler}s. *

* Please refer to * EchoServer * example. *

* You should bind to the desired socket address to accept incoming * connections, and then events for incoming connections will be sent to * the specified default {@link IoHandler}. *

* Threads accept incoming connections start automatically when * {@link #bind()} is invoked, and stop when {@link #unbind()} is invoked. * * @author Apache MINA Project */ public interface IoAcceptor extends IoService { /** * Returns the local address which is bound currently. If more than one * address are bound, only one of them will be returned, but it's not * necessarily the firstly bound address. */ SocketAddress getLocalAddress(); /** * Returns a {@link Set} of the local addresses which are bound currently. */ Set getLocalAddresses(); /** * Returns the default local address to bind when no argument is specified * in {@link #bind()} method. Please note that the default will not be * used if any local address is specified. If more than one address are * set, only one of them will be returned, but it's not necessarily the * firstly specified address in {@link #setDefaultLocalAddresses(List)}. * */ SocketAddress getDefaultLocalAddress(); /** * Returns a {@link List} of the default local addresses to bind when no * argument is specified in {@link #bind()} method. Please note that the * default will not be used if any local address is specified. */ List getDefaultLocalAddresses(); /** * Sets the default local address to bind when no argument is specified in * {@link #bind()} method. Please note that the default will not be used * if any local address is specified. */ void setDefaultLocalAddress(SocketAddress localAddress); /** * Sets the default local addresses to bind when no argument is specified * in {@link #bind()} method. Please note that the default will not be * used if any local address is specified. */ void setDefaultLocalAddresses(SocketAddress firstLocalAddress, SocketAddress... otherLocalAddresses); /** * Sets the default local addresses to bind when no argument is specified * in {@link #bind()} method. Please note that the default will not be * used if any local address is specified. */ void setDefaultLocalAddresses(Iterable localAddresses); /** * Sets the default local addresses to bind when no argument is specified * in {@link #bind()} method. Please note that the default will not be * used if any local address is specified. */ void setDefaultLocalAddresses(List localAddresses); /** * Returns true if and only if all clients are closed when this * acceptor unbinds from all the related local address (i.e. when the * service is deactivated). */ boolean isCloseOnDeactivation(); /** * Sets whether all client sessions are closed when this acceptor unbinds * from all the related local addresses (i.e. when the service is * deactivated). The default value is true. */ void setCloseOnDeactivation(boolean closeOnDeactivation); /** * Binds to the default local address(es) and start to accept incoming * connections. * * @throws IOException if failed to bind */ void bind() throws IOException; /** * Binds to the specified local address and start to accept incoming * connections. * * @param localAddress The SocketAddress to bind to * * @throws IOException if failed to bind */ void bind(SocketAddress localAddress) throws IOException; /** * Binds to the specified local addresses and start to accept incoming * connections. If no address is given, bind on the default local address. * * @param firstLocalAddresses The first address to bind to * @param addresses The SocketAddresses to bind to * * @throws IOException if failed to bind */ void bind(SocketAddress firstLocalAddress, SocketAddress... addresses) throws IOException; /** * Binds to the specified local addresses and start to accept incoming * connections. If no address is given, bind on the default local address. * * @param addresses The SocketAddresses to bind to * * @throws IOException if failed to bind */ void bind(SocketAddress... addresses) throws IOException; /** * Binds to the specified local addresses and start to accept incoming * connections. * * @throws IOException if failed to bind */ void bind(Iterable localAddresses) throws IOException; /** * Unbinds from all local addresses that this service is bound to and stops * to accept incoming connections. All managed connections will be closed * if {@link #setCloseOnDeactivation(boolean) disconnectOnUnbind} property * is true. This method returns silently if no local address is * bound yet. */ void unbind(); /** * Unbinds from the specified local address and stop to accept incoming * connections. All managed connections will be closed if * {@link #setCloseOnDeactivation(boolean) disconnectOnUnbind} property is * true. This method returns silently if the default local * address is not bound yet. */ void unbind(SocketAddress localAddress); /** * Unbinds from the specified local addresses and stop to accept incoming * connections. All managed connections will be closed if * {@link #setCloseOnDeactivation(boolean) disconnectOnUnbind} property is * true. This method returns silently if the default local * addresses are not bound yet. */ void unbind(SocketAddress firstLocalAddress, SocketAddress... otherLocalAddresses); /** * Unbinds from the specified local addresses and stop to accept incoming * connections. All managed connections will be closed if * {@link #setCloseOnDeactivation(boolean) disconnectOnUnbind} property is * true. This method returns silently if the default local * addresses are not bound yet. */ void unbind(Iterable localAddresses); /** * (Optional) Returns an {@link IoSession} that is bound to the specified * localAddress and the specified remoteAddress which * reuses the local address that is already bound by this service. *

* This operation is optional. Please throw {@link UnsupportedOperationException} * if the transport type doesn't support this operation. This operation is * usually implemented for connectionless transport types. * * @throws UnsupportedOperationException if this operation is not supported * @throws IllegalStateException if this service is not running. * @throws IllegalArgumentException if this service is not bound to the * specified localAddress. */ IoSession newSession(SocketAddress remoteAddress, SocketAddress localAddress); }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/AbstractIoAcceptor.java0000644000175000017500000003533112032276027032023 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.service; import java.io.IOException; import java.net.SocketAddress; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionConfig; /** * A base implementation of {@link IoAcceptor}. * * @author Apache MINA Project * @org.apache.xbean.XBean */ public abstract class AbstractIoAcceptor extends AbstractIoService implements IoAcceptor { private final List defaultLocalAddresses = new ArrayList(); private final List unmodifiableDefaultLocalAddresses = Collections .unmodifiableList(defaultLocalAddresses); private final Set boundAddresses = new HashSet(); private boolean disconnectOnUnbind = true; /** * The lock object which is acquired while bind or unbind operation is performed. * Acquire this lock in your property setters which shouldn't be changed while * the service is bound. */ protected final Object bindLock = new Object(); /** * Constructor for {@link AbstractIoAcceptor}. You need to provide a default * session configuration and an {@link Executor} for handling I/O events. If * null {@link Executor} is provided, a default one will be created using * {@link Executors#newCachedThreadPool()}. * * {@see AbstractIoService#AbstractIoService(IoSessionConfig, Executor)} * * @param sessionConfig * the default configuration for the managed {@link IoSession} * @param executor * the {@link Executor} used for handling execution of I/O * events. Can be null. */ protected AbstractIoAcceptor(IoSessionConfig sessionConfig, Executor executor) { super(sessionConfig, executor); defaultLocalAddresses.add(null); } /** * {@inheritDoc} */ public SocketAddress getLocalAddress() { Set localAddresses = getLocalAddresses(); if (localAddresses.isEmpty()) { return null; } return localAddresses.iterator().next(); } /** * {@inheritDoc} */ public final Set getLocalAddresses() { Set localAddresses = new HashSet(); synchronized (boundAddresses) { localAddresses.addAll(boundAddresses); } return localAddresses; } /** * {@inheritDoc} */ public SocketAddress getDefaultLocalAddress() { if (defaultLocalAddresses.isEmpty()) { return null; } return defaultLocalAddresses.iterator().next(); } /** * {@inheritDoc} */ public final void setDefaultLocalAddress(SocketAddress localAddress) { setDefaultLocalAddresses(localAddress); } /** * {@inheritDoc} */ public final List getDefaultLocalAddresses() { return unmodifiableDefaultLocalAddresses; } /** * {@inheritDoc} * @org.apache.xbean.Property nestedType="java.net.SocketAddress" */ public final void setDefaultLocalAddresses(List localAddresses) { if (localAddresses == null) { throw new IllegalArgumentException("localAddresses"); } setDefaultLocalAddresses((Iterable) localAddresses); } /** * {@inheritDoc} */ public final void setDefaultLocalAddresses(Iterable localAddresses) { if (localAddresses == null) { throw new IllegalArgumentException("localAddresses"); } synchronized (bindLock) { synchronized (boundAddresses) { if (!boundAddresses.isEmpty()) { throw new IllegalStateException("localAddress can't be set while the acceptor is bound."); } Collection newLocalAddresses = new ArrayList(); for (SocketAddress a : localAddresses) { checkAddressType(a); newLocalAddresses.add(a); } if (newLocalAddresses.isEmpty()) { throw new IllegalArgumentException("empty localAddresses"); } this.defaultLocalAddresses.clear(); this.defaultLocalAddresses.addAll(newLocalAddresses); } } } /** * {@inheritDoc} * @org.apache.xbean.Property nestedType="java.net.SocketAddress" */ public final void setDefaultLocalAddresses(SocketAddress firstLocalAddress, SocketAddress... otherLocalAddresses) { if (otherLocalAddresses == null) { otherLocalAddresses = new SocketAddress[0]; } Collection newLocalAddresses = new ArrayList(otherLocalAddresses.length + 1); newLocalAddresses.add(firstLocalAddress); for (SocketAddress a : otherLocalAddresses) { newLocalAddresses.add(a); } setDefaultLocalAddresses(newLocalAddresses); } /** * {@inheritDoc} */ public final boolean isCloseOnDeactivation() { return disconnectOnUnbind; } /** * {@inheritDoc} */ public final void setCloseOnDeactivation(boolean disconnectClientsOnUnbind) { this.disconnectOnUnbind = disconnectClientsOnUnbind; } /** * {@inheritDoc} */ public final void bind() throws IOException { bind(getDefaultLocalAddresses()); } /** * {@inheritDoc} */ public final void bind(SocketAddress localAddress) throws IOException { if (localAddress == null) { throw new IllegalArgumentException("localAddress"); } List localAddresses = new ArrayList(1); localAddresses.add(localAddress); bind(localAddresses); } /** * {@inheritDoc} */ public final void bind(SocketAddress... addresses) throws IOException { if ((addresses == null) || (addresses.length == 0)) { bind(getDefaultLocalAddresses()); return; } List localAddresses = new ArrayList(2); for (SocketAddress address : addresses) { localAddresses.add(address); } bind(localAddresses); } /** * {@inheritDoc} */ public final void bind(SocketAddress firstLocalAddress, SocketAddress... addresses) throws IOException { if (firstLocalAddress == null) { bind(getDefaultLocalAddresses()); } if ((addresses == null) || (addresses.length == 0)) { bind(getDefaultLocalAddresses()); return; } List localAddresses = new ArrayList(2); localAddresses.add(firstLocalAddress); for (SocketAddress address : addresses) { localAddresses.add(address); } bind(localAddresses); } /** * {@inheritDoc} */ public final void bind(Iterable localAddresses) throws IOException { if (isDisposing()) { throw new IllegalStateException("Already disposed."); } if (localAddresses == null) { throw new IllegalArgumentException("localAddresses"); } List localAddressesCopy = new ArrayList(); for (SocketAddress a : localAddresses) { checkAddressType(a); localAddressesCopy.add(a); } if (localAddressesCopy.isEmpty()) { throw new IllegalArgumentException("localAddresses is empty."); } boolean activate = false; synchronized (bindLock) { synchronized (boundAddresses) { if (boundAddresses.isEmpty()) { activate = true; } } if (getHandler() == null) { throw new IllegalStateException("handler is not set."); } try { Set addresses = bindInternal(localAddressesCopy); synchronized (boundAddresses) { boundAddresses.addAll(addresses); } } catch (IOException e) { throw e; } catch (RuntimeException e) { throw e; } catch (Throwable e) { throw new RuntimeIoException("Failed to bind to: " + getLocalAddresses(), e); } } if (activate) { getListeners().fireServiceActivated(); } } /** * {@inheritDoc} */ public final void unbind() { unbind(getLocalAddresses()); } /** * {@inheritDoc} */ public final void unbind(SocketAddress localAddress) { if (localAddress == null) { throw new IllegalArgumentException("localAddress"); } List localAddresses = new ArrayList(1); localAddresses.add(localAddress); unbind(localAddresses); } /** * {@inheritDoc} */ public final void unbind(SocketAddress firstLocalAddress, SocketAddress... otherLocalAddresses) { if (firstLocalAddress == null) { throw new IllegalArgumentException("firstLocalAddress"); } if (otherLocalAddresses == null) { throw new IllegalArgumentException("otherLocalAddresses"); } List localAddresses = new ArrayList(); localAddresses.add(firstLocalAddress); Collections.addAll(localAddresses, otherLocalAddresses); unbind(localAddresses); } /** * {@inheritDoc} */ public final void unbind(Iterable localAddresses) { if (localAddresses == null) { throw new IllegalArgumentException("localAddresses"); } boolean deactivate = false; synchronized (bindLock) { synchronized (boundAddresses) { if (boundAddresses.isEmpty()) { return; } List localAddressesCopy = new ArrayList(); int specifiedAddressCount = 0; for (SocketAddress a : localAddresses) { specifiedAddressCount++; if ((a != null) && boundAddresses.contains(a)) { localAddressesCopy.add(a); } } if (specifiedAddressCount == 0) { throw new IllegalArgumentException("localAddresses is empty."); } if (!localAddressesCopy.isEmpty()) { try { unbind0(localAddressesCopy); } catch (RuntimeException e) { throw e; } catch (Throwable e) { throw new RuntimeIoException("Failed to unbind from: " + getLocalAddresses(), e); } boundAddresses.removeAll(localAddressesCopy); if (boundAddresses.isEmpty()) { deactivate = true; } } } } if (deactivate) { getListeners().fireServiceDeactivated(); } } /** * Starts the acceptor, and register the given addresses * @return the {@link Set} of the local addresses which is bound actually */ protected abstract Set bindInternal(List localAddresses) throws Exception; /** * Implement this method to perform the actual unbind operation. */ protected abstract void unbind0(List localAddresses) throws Exception; @Override public String toString() { TransportMetadata m = getTransportMetadata(); return '(' + m.getProviderName() + ' ' + m.getName() + " acceptor: " + (isActive() ? "localAddress(es): " + getLocalAddresses() + ", managedSessionCount: " + getManagedSessionCount() : "not bound") + ')'; } private void checkAddressType(SocketAddress a) { if (a != null && !getTransportMetadata().getAddressType().isAssignableFrom(a.getClass())) { throw new IllegalArgumentException("localAddress type: " + a.getClass().getSimpleName() + " (expected: " + getTransportMetadata().getAddressType().getSimpleName() + ")"); } } public static class AcceptorOperationFuture extends ServiceOperationFuture { private final List localAddresses; public AcceptorOperationFuture(List localAddresses) { this.localAddresses = new ArrayList(localAddresses); } public final List getLocalAddresses() { return Collections.unmodifiableList(localAddresses); } /** * @see Object#toString() */ public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Acceptor operation : "); if (localAddresses != null) { boolean isFirst = true; for (SocketAddress address : localAddresses) { if (isFirst) { isFirst = false; } else { sb.append(", "); } sb.append(address); } } return sb.toString(); } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/service/IoProcessor.java0000644000175000017500000000645612032276027030564 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.service; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; /** * An internal interface to represent an 'I/O processor' that performs * actual I/O operations for {@link IoSession}s. It abstracts existing * reactor frameworks such as Java NIO once again to simplify transport * implementations. * * @author Apache MINA Project * * @param the type of the {@link IoSession} this processor can handle */ public interface IoProcessor { /** * Returns true if and if only {@link #dispose()} method has * been called. Please note that this method will return true * even after all the related resources are released. */ boolean isDisposing(); /** * Returns true if and if only all resources of this processor * have been disposed. */ boolean isDisposed(); /** * Releases any resources allocated by this processor. Please note that * the resources might not be released as long as there are any sessions * managed by this processor. Most implementations will close all sessions * immediately and release the related resources. */ void dispose(); /** * Adds the specified {@code session} to the I/O processor so that * the I/O processor starts to perform any I/O operations related * with the {@code session}. * * @param session The added session */ void add(S session); /** * Flushes the internal write request queue of the specified * {@code session}. * * @param session The session we want the message to be written */ void flush(S session); /** * Writes the WriteRequest for the specified {@code session}. * * @param session The session we want the message to be written * @param writeRequest the WriteRequest to write */ void write(S session, WriteRequest writeRequest); /** * Controls the traffic of the specified {@code session} depending of the * {@link IoSession#isReadSuspended()} and {@link IoSession#isWriteSuspended()} * flags */ void updateTrafficControl(S session); /** * Removes and closes the specified {@code session} from the I/O * processor so that the I/O processor closes the connection * associated with the {@code session} and releases any other related * resources. */ void remove(S session); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/future/0000755000175000017500000000000012162575507025322 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/future/DefaultCloseFuture.java0000644000175000017500000000400012032276032031707 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.future; import org.apache.mina.core.session.IoSession; /** * A default implementation of {@link CloseFuture}. * * @author Apache MINA Project */ public class DefaultCloseFuture extends DefaultIoFuture implements CloseFuture { /** * Creates a new instance. */ public DefaultCloseFuture(IoSession session) { super(session); } public boolean isClosed() { if (isDone()) { return ((Boolean) getValue()).booleanValue(); } else { return false; } } public void setClosed() { setValue(Boolean.TRUE); } @Override public CloseFuture await() throws InterruptedException { return (CloseFuture) super.await(); } @Override public CloseFuture awaitUninterruptibly() { return (CloseFuture) super.awaitUninterruptibly(); } @Override public CloseFuture addListener(IoFutureListener listener) { return (CloseFuture) super.addListener(listener); } @Override public CloseFuture removeListener(IoFutureListener listener) { return (CloseFuture) super.removeListener(listener); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/future/CompositeIoFuture.java0000644000175000017500000000433212032276032031577 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.future; import java.util.concurrent.atomic.AtomicInteger; import org.apache.mina.core.IoUtil; /** * An {@link IoFuture} of {@link IoFuture}s. It is useful when you want to * get notified when all {@link IoFuture}s are complete. It is not recommended * to use {@link CompositeIoFuture} if you just want to wait for all futures. * In that case, please use {@link IoUtil#await(Iterable)} instead * for better performance. * * @author Apache MINA Project * * @param the type of the child futures. */ public class CompositeIoFuture extends DefaultIoFuture { private final NotifyingListener listener = new NotifyingListener(); private final AtomicInteger unnotified = new AtomicInteger(); private volatile boolean constructionFinished; public CompositeIoFuture(Iterable children) { super(null); for (E f : children) { f.addListener(listener); unnotified.incrementAndGet(); } constructionFinished = true; if (unnotified.get() == 0) { setValue(true); } } private class NotifyingListener implements IoFutureListener { public void operationComplete(IoFuture future) { if (unnotified.decrementAndGet() == 0 && constructionFinished) { setValue(true); } } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/future/CloseFuture.java0000644000175000017500000000352612032276032030416 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.future; /** * An {@link IoFuture} for asynchronous close requests. * *

Example

*
 * IoSession session = ...;
 * CloseFuture future = session.close(true);
 * // Wait until the connection is closed
 * future.awaitUninterruptibly();
 * // Now connection should be closed.
 * assert future.isClosed();
 * 
* * @author Apache MINA Project */ public interface CloseFuture extends IoFuture { /** * Returns true if the close request is finished and the session is closed. */ boolean isClosed(); /** * Marks this future as closed and notifies all threads waiting for this * future. This method is invoked by MINA internally. Please do not call * this method directly. */ void setClosed(); CloseFuture await() throws InterruptedException; CloseFuture awaitUninterruptibly(); CloseFuture addListener(IoFutureListener listener); CloseFuture removeListener(IoFutureListener listener); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/future/DefaultWriteFuture.java0000644000175000017500000000667012032276032031753 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.future; import org.apache.mina.core.session.IoSession; /** * A default implementation of {@link WriteFuture}. * * @author Apache MINA Project */ public class DefaultWriteFuture extends DefaultIoFuture implements WriteFuture { /** * Returns a new {@link DefaultWriteFuture} which is already marked as 'written'. */ public static WriteFuture newWrittenFuture(IoSession session) { DefaultWriteFuture unwrittenFuture = new DefaultWriteFuture(session); unwrittenFuture.setWritten(); return unwrittenFuture; } /** * Returns a new {@link DefaultWriteFuture} which is already marked as 'not written'. */ public static WriteFuture newNotWrittenFuture(IoSession session, Throwable cause) { DefaultWriteFuture unwrittenFuture = new DefaultWriteFuture(session); unwrittenFuture.setException(cause); return unwrittenFuture; } /** * Creates a new instance. */ public DefaultWriteFuture(IoSession session) { super(session); } /** * {@inheritDoc} */ public boolean isWritten() { if (isDone()) { Object v = getValue(); if (v instanceof Boolean) { return ((Boolean) v).booleanValue(); } } return false; } /** * {@inheritDoc} */ public Throwable getException() { if (isDone()) { Object v = getValue(); if (v instanceof Throwable) { return (Throwable) v; } } return null; } /** * {@inheritDoc} */ public void setWritten() { setValue(Boolean.TRUE); } /** * {@inheritDoc} */ public void setException(Throwable exception) { if (exception == null) { throw new IllegalArgumentException("exception"); } setValue(exception); } /** * {@inheritDoc} */ @Override public WriteFuture await() throws InterruptedException { return (WriteFuture) super.await(); } /** * {@inheritDoc} */ @Override public WriteFuture awaitUninterruptibly() { return (WriteFuture) super.awaitUninterruptibly(); } /** * {@inheritDoc} */ @Override public WriteFuture addListener(IoFutureListener listener) { return (WriteFuture) super.addListener(listener); } /** * {@inheritDoc} */ @Override public WriteFuture removeListener(IoFutureListener listener) { return (WriteFuture) super.removeListener(listener); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/future/IoFutureListener.java0000644000175000017500000000353012032276032031421 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.future; import java.util.EventListener; import org.apache.mina.core.session.IoSession; /** * Something interested in being notified when the completion * of an asynchronous I/O operation : {@link IoFuture}. * * @author Apache MINA Project */ public interface IoFutureListener extends EventListener { /** * An {@link IoFutureListener} that closes the {@link IoSession} which is * associated with the specified {@link IoFuture}. */ static IoFutureListener CLOSE = new IoFutureListener() { public void operationComplete(IoFuture future) { future.getSession().close(true); } }; /** * Invoked when the operation associated with the {@link IoFuture} * has been completed even if you add the listener after the completion. * * @param future The source {@link IoFuture} which called this * callback. */ void operationComplete(F future); }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/future/WriteFuture.java0000644000175000017500000000547112032276032030444 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.future; /** * An {@link IoFuture} for asynchronous write requests. * *

Example

*
 * IoSession session = ...;
 * WriteFuture future = session.write(...);
 * // Wait until the message is completely written out to the O/S buffer.
 * future.join();
 * if( future.isWritten() )
 * {
 *     // The message has been written successfully.
 * }
 * else
 * {
 *     // The messsage couldn't be written out completely for some reason.
 *     // (e.g. Connection is closed)
 * }
 * 
* * @author Apache MINA Project */ public interface WriteFuture extends IoFuture { /** * Returns true if the write operation is finished successfully. */ boolean isWritten(); /** * Returns the cause of the write failure if and only if the write * operation has failed due to an {@link Exception}. Otherwise, * null is returned. */ Throwable getException(); /** * Sets the message is written, and notifies all threads waiting for * this future. This method is invoked by MINA internally. Please do * not call this method directly. */ void setWritten(); /** * Sets the cause of the write failure, and notifies all threads waiting * for this future. This method is invoked by MINA internally. Please * do not call this method directly. */ void setException(Throwable cause); /** * Wait for the asynchronous operation to complete. * The attached listeners will be notified when the operation is * completed. * * @return the created {@link WriteFuture} * @throws InterruptedException */ WriteFuture await() throws InterruptedException; /** * {@inheritDoc} */ WriteFuture awaitUninterruptibly(); /** * {@inheritDoc} */ WriteFuture addListener(IoFutureListener listener); /** * {@inheritDoc} */ WriteFuture removeListener(IoFutureListener listener); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/future/DefaultConnectFuture.java0000644000175000017500000000700712032276032032245 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.future; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.session.IoSession; /** * A default implementation of {@link ConnectFuture}. * * @author Apache MINA Project */ public class DefaultConnectFuture extends DefaultIoFuture implements ConnectFuture { private static final Object CANCELED = new Object(); /** * Returns a new {@link ConnectFuture} which is already marked as 'failed to connect'. */ public static ConnectFuture newFailedFuture(Throwable exception) { DefaultConnectFuture failedFuture = new DefaultConnectFuture(); failedFuture.setException(exception); return failedFuture; } /** * Creates a new instance. */ public DefaultConnectFuture() { super(null); } @Override public IoSession getSession() { Object v = getValue(); if (v instanceof RuntimeException) { throw (RuntimeException) v; } else if (v instanceof Error) { throw (Error) v; } else if (v instanceof Throwable) { throw (RuntimeIoException) new RuntimeIoException("Failed to get the session.").initCause((Throwable) v); } else if (v instanceof IoSession) { return (IoSession) v; } else { return null; } } public Throwable getException() { Object v = getValue(); if (v instanceof Throwable) { return (Throwable) v; } else { return null; } } public boolean isConnected() { return getValue() instanceof IoSession; } public boolean isCanceled() { return getValue() == CANCELED; } public void setSession(IoSession session) { if (session == null) { throw new IllegalArgumentException("session"); } setValue(session); } public void setException(Throwable exception) { if (exception == null) { throw new IllegalArgumentException("exception"); } setValue(exception); } public void cancel() { setValue(CANCELED); } @Override public ConnectFuture await() throws InterruptedException { return (ConnectFuture) super.await(); } @Override public ConnectFuture awaitUninterruptibly() { return (ConnectFuture) super.awaitUninterruptibly(); } @Override public ConnectFuture addListener(IoFutureListener listener) { return (ConnectFuture) super.addListener(listener); } @Override public ConnectFuture removeListener(IoFutureListener listener) { return (ConnectFuture) super.removeListener(listener); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/future/ConnectFuture.java0000644000175000017500000000572012032276032030740 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.future; import org.apache.mina.core.session.IoSession; /** * An {@link IoFuture} for asynchronous connect requests. * *

Example

*
 * IoConnector connector = ...;
 * ConnectFuture future = connector.connect(...);
 * future.join(); // Wait until the connection attempt is finished.
 * IoSession session = future.getSession();
 * session.write(...);
 * 
* * @author Apache MINA Project */ public interface ConnectFuture extends IoFuture { /** * Returns {@link IoSession} which is the result of connect operation. * * @return null if the connect operation is not finished yet * @throws RuntimeException if connection attempt failed by an exception */ IoSession getSession(); /** * Returns the cause of the connection failure. * * @return null if the connect operation is not finished yet, * or if the connection attempt is successful. */ Throwable getException(); /** * Returns true if the connect operation is finished successfully. */ boolean isConnected(); /** * Returns {@code true} if the connect operation has been canceled by * {@link #cancel()} method. */ boolean isCanceled(); /** * Sets the newly connected session and notifies all threads waiting for * this future. This method is invoked by MINA internally. Please do not * call this method directly. */ void setSession(IoSession session); /** * Sets the exception caught due to connection failure and notifies all * threads waiting for this future. This method is invoked by MINA * internally. Please do not call this method directly. */ void setException(Throwable exception); /** * Cancels the connection attempt and notifies all threads waiting for * this future. */ void cancel(); ConnectFuture await() throws InterruptedException; ConnectFuture awaitUninterruptibly(); ConnectFuture addListener(IoFutureListener listener); ConnectFuture removeListener(IoFutureListener listener); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/future/IoFuture.java0000644000175000017500000000677412032276032027730 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.future; import java.util.concurrent.TimeUnit; import org.apache.mina.core.session.IoSession; /** * Represents the completion of an asynchronous I/O operation on an * {@link IoSession}. * Can be listened for completion using a {@link IoFutureListener}. * * @author Apache MINA Project */ public interface IoFuture { /** * Returns the {@link IoSession} which is associated with this future. */ IoSession getSession(); /** * Wait for the asynchronous operation to complete. * The attached listeners will be notified when the operation is * completed. */ IoFuture await() throws InterruptedException; /** * Wait for the asynchronous operation to complete with the specified timeout. * * @return true if the operation is completed. */ boolean await(long timeout, TimeUnit unit) throws InterruptedException; /** * Wait for the asynchronous operation to complete with the specified timeout. * * @return true if the operation is completed. */ boolean await(long timeoutMillis) throws InterruptedException; /** * Wait for the asynchronous operation to complete uninterruptibly. * The attached listeners will be notified when the operation is * completed. * * @return the current IoFuture */ IoFuture awaitUninterruptibly(); /** * Wait for the asynchronous operation to complete with the specified timeout * uninterruptibly. * * @return true if the operation is completed. */ boolean awaitUninterruptibly(long timeout, TimeUnit unit); /** * Wait for the asynchronous operation to complete with the specified timeout * uninterruptibly. * * @return true if the operation is finished. */ boolean awaitUninterruptibly(long timeoutMillis); /** * @deprecated Replaced with {@link #awaitUninterruptibly()}. */ @Deprecated void join(); /** * @deprecated Replaced with {@link #awaitUninterruptibly(long)}. */ @Deprecated boolean join(long timeoutMillis); /** * Returns if the asynchronous operation is completed. */ boolean isDone(); /** * Adds an event listener which is notified when * this future is completed. If the listener is added * after the completion, the listener is directly notified. */ IoFuture addListener(IoFutureListener listener); /** * Removes an existing event listener so it won't be notified when * the future is completed. */ IoFuture removeListener(IoFutureListener listener); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/future/ReadFuture.java0000644000175000017500000000611012032276032030214 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.future; import org.apache.mina.core.session.IoSession; /** * An {@link IoFuture} for {@link IoSession#read() asynchronous read requests}. * *

Example

*
 * IoSession session = ...;
 * // useReadOperation must be enabled to use read operation.
 * session.getConfig().setUseReadOperation(true);
 * 
 * ReadFuture future = session.read();
 * // Wait until a message is received.
 * future.await();
 * try {
 *     Object message = future.getMessage();
 * } catch (Exception e) {
 *     ...
 * }
 * 
* * @author Apache MINA Project */ public interface ReadFuture extends IoFuture { /** * Returns the received message. It returns null if this * future is not ready or the associated {@link IoSession} has been closed. * * @throws RuntimeException if read or any relevant operation has failed. */ Object getMessage(); /** * Returns true if a message was received successfully. */ boolean isRead(); /** * Returns true if the {@link IoSession} associated with this * future has been closed. */ boolean isClosed(); /** * Returns the cause of the read failure if and only if the read * operation has failed due to an {@link Exception}. Otherwise, * null is returned. */ Throwable getException(); /** * Sets the message is written, and notifies all threads waiting for * this future. This method is invoked by MINA internally. Please do * not call this method directly. */ void setRead(Object message); /** * Sets the associated {@link IoSession} is closed. This method is invoked * by MINA internally. Please do not call this method directly. */ void setClosed(); /** * Sets the cause of the read failure, and notifies all threads waiting * for this future. This method is invoked by MINA internally. Please * do not call this method directly. */ void setException(Throwable cause); ReadFuture await() throws InterruptedException; ReadFuture awaitUninterruptibly(); ReadFuture addListener(IoFutureListener listener); ReadFuture removeListener(IoFutureListener listener); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/future/DefaultIoFuture.java0000644000175000017500000002640112032276032031222 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.future; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import org.apache.mina.core.polling.AbstractPollingIoProcessor; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.session.IoSession; import org.apache.mina.util.ExceptionMonitor; /** * A default implementation of {@link IoFuture} associated with * an {@link IoSession}. * * @author Apache MINA Project */ public class DefaultIoFuture implements IoFuture { /** A number of seconds to wait between two deadlock controls ( 5 seconds ) */ private static final long DEAD_LOCK_CHECK_INTERVAL = 5000L; /** The associated session */ private final IoSession session; /** A lock used by the wait() method */ private final Object lock; private IoFutureListener firstListener; private List> otherListeners; private Object result; private boolean ready; private int waiters; /** * Creates a new instance associated with an {@link IoSession}. * * @param session an {@link IoSession} which is associated with this future */ public DefaultIoFuture(IoSession session) { this.session = session; this.lock = this; } /** * {@inheritDoc} */ public IoSession getSession() { return session; } /** * @deprecated Replaced with {@link #awaitUninterruptibly()}. */ @Deprecated public void join() { awaitUninterruptibly(); } /** * @deprecated Replaced with {@link #awaitUninterruptibly(long)}. */ @Deprecated public boolean join(long timeoutMillis) { return awaitUninterruptibly(timeoutMillis); } /** * {@inheritDoc} */ public IoFuture await() throws InterruptedException { synchronized (lock) { while (!ready) { waiters++; try { // Wait for a notify, or if no notify is called, // assume that we have a deadlock and exit the // loop to check for a potential deadlock. lock.wait(DEAD_LOCK_CHECK_INTERVAL); } finally { waiters--; if (!ready) { checkDeadLock(); } } } } return this; } /** * {@inheritDoc} */ public boolean await(long timeout, TimeUnit unit) throws InterruptedException { return await(unit.toMillis(timeout)); } /** * {@inheritDoc} */ public boolean await(long timeoutMillis) throws InterruptedException { return await0(timeoutMillis, true); } /** * {@inheritDoc} */ public IoFuture awaitUninterruptibly() { try { await0(Long.MAX_VALUE, false); } catch (InterruptedException ie) { // Do nothing : this catch is just mandatory by contract } return this; } /** * {@inheritDoc} */ public boolean awaitUninterruptibly(long timeout, TimeUnit unit) { return awaitUninterruptibly(unit.toMillis(timeout)); } /** * {@inheritDoc} */ public boolean awaitUninterruptibly(long timeoutMillis) { try { return await0(timeoutMillis, false); } catch (InterruptedException e) { throw new InternalError(); } } /** * Wait for the Future to be ready. If the requested delay is 0 or * negative, this method immediately returns the value of the * 'ready' flag. * Every 5 second, the wait will be suspended to be able to check if * there is a deadlock or not. * * @param timeoutMillis The delay we will wait for the Future to be ready * @param interruptable Tells if the wait can be interrupted or not * @return true if the Future is ready * @throws InterruptedException If the thread has been interrupted * when it's not allowed. */ private boolean await0(long timeoutMillis, boolean interruptable) throws InterruptedException { long endTime = System.currentTimeMillis() + timeoutMillis; if (endTime < 0) { endTime = Long.MAX_VALUE; } synchronized (lock) { if (ready) { return ready; } else if (timeoutMillis <= 0) { return ready; } waiters++; try { for (;;) { try { long timeOut = Math.min(timeoutMillis, DEAD_LOCK_CHECK_INTERVAL); lock.wait(timeOut); } catch (InterruptedException e) { if (interruptable) { throw e; } } if (ready) { return true; } if (endTime < System.currentTimeMillis()) { return ready; } } } finally { waiters--; if (!ready) { checkDeadLock(); } } } } /** * * TODO checkDeadLock. * */ private void checkDeadLock() { // Only read / write / connect / write future can cause dead lock. if (!(this instanceof CloseFuture || this instanceof WriteFuture || this instanceof ReadFuture || this instanceof ConnectFuture)) { return; } // Get the current thread stackTrace. // Using Thread.currentThread().getStackTrace() is the best solution, // even if slightly less efficient than doing a new Exception().getStackTrace(), // as internally, it does exactly the same thing. The advantage of using // this solution is that we may benefit some improvement with some // future versions of Java. StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); // Simple and quick check. for (StackTraceElement s : stackTrace) { if (AbstractPollingIoProcessor.class.getName().equals(s.getClassName())) { IllegalStateException e = new IllegalStateException("t"); e.getStackTrace(); throw new IllegalStateException("DEAD LOCK: " + IoFuture.class.getSimpleName() + ".await() was invoked from an I/O processor thread. " + "Please use " + IoFutureListener.class.getSimpleName() + " or configure a proper thread model alternatively."); } } // And then more precisely. for (StackTraceElement s : stackTrace) { try { Class cls = DefaultIoFuture.class.getClassLoader().loadClass(s.getClassName()); if (IoProcessor.class.isAssignableFrom(cls)) { throw new IllegalStateException("DEAD LOCK: " + IoFuture.class.getSimpleName() + ".await() was invoked from an I/O processor thread. " + "Please use " + IoFutureListener.class.getSimpleName() + " or configure a proper thread model alternatively."); } } catch (Exception cnfe) { // Ignore } } } /** * {@inheritDoc} */ public boolean isDone() { synchronized (lock) { return ready; } } /** * Sets the result of the asynchronous operation, and mark it as finished. */ public void setValue(Object newValue) { synchronized (lock) { // Allow only once. if (ready) { return; } result = newValue; ready = true; if (waiters > 0) { lock.notifyAll(); } } notifyListeners(); } /** * Returns the result of the asynchronous operation. */ protected Object getValue() { synchronized (lock) { return result; } } /** * {@inheritDoc} */ public IoFuture addListener(IoFutureListener listener) { if (listener == null) { throw new IllegalArgumentException("listener"); } boolean notifyNow = false; synchronized (lock) { if (ready) { notifyNow = true; } else { if (firstListener == null) { firstListener = listener; } else { if (otherListeners == null) { otherListeners = new ArrayList>(1); } otherListeners.add(listener); } } } if (notifyNow) { notifyListener(listener); } return this; } /** * {@inheritDoc} */ public IoFuture removeListener(IoFutureListener listener) { if (listener == null) { throw new IllegalArgumentException("listener"); } synchronized (lock) { if (!ready) { if (listener == firstListener) { if (otherListeners != null && !otherListeners.isEmpty()) { firstListener = otherListeners.remove(0); } else { firstListener = null; } } else if (otherListeners != null) { otherListeners.remove(listener); } } } return this; } private void notifyListeners() { // There won't be any visibility problem or concurrent modification // because 'ready' flag will be checked against both addListener and // removeListener calls. if (firstListener != null) { notifyListener(firstListener); firstListener = null; if (otherListeners != null) { for (IoFutureListener l : otherListeners) { notifyListener(l); } otherListeners = null; } } } @SuppressWarnings("unchecked") private void notifyListener(IoFutureListener l) { try { l.operationComplete(this); } catch (Throwable t) { ExceptionMonitor.getInstance().exceptionCaught(t); } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/future/DefaultReadFuture.java0000644000175000017500000000745312032276032031534 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.future; import java.io.IOException; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.session.IoSession; /** * A default implementation of {@link WriteFuture}. * * @author Apache MINA Project */ public class DefaultReadFuture extends DefaultIoFuture implements ReadFuture { private static final Object CLOSED = new Object(); /** * Creates a new instance. */ public DefaultReadFuture(IoSession session) { super(session); } public Object getMessage() { if (isDone()) { Object v = getValue(); if (v == CLOSED) { return null; } if (v instanceof ExceptionHolder) { v = ((ExceptionHolder) v).exception; if (v instanceof RuntimeException) { throw (RuntimeException) v; } if (v instanceof Error) { throw (Error) v; } if (v instanceof IOException || v instanceof Exception) { throw new RuntimeIoException((Exception) v); } } return v; } return null; } public boolean isRead() { if (isDone()) { Object v = getValue(); return (v != CLOSED && !(v instanceof ExceptionHolder)); } return false; } public boolean isClosed() { if (isDone()) { return getValue() == CLOSED; } return false; } public Throwable getException() { if (isDone()) { Object v = getValue(); if (v instanceof ExceptionHolder) { return ((ExceptionHolder) v).exception; } } return null; } public void setClosed() { setValue(CLOSED); } public void setRead(Object message) { if (message == null) { throw new IllegalArgumentException("message"); } setValue(message); } public void setException(Throwable exception) { if (exception == null) { throw new IllegalArgumentException("exception"); } setValue(new ExceptionHolder(exception)); } @Override public ReadFuture await() throws InterruptedException { return (ReadFuture) super.await(); } @Override public ReadFuture awaitUninterruptibly() { return (ReadFuture) super.awaitUninterruptibly(); } @Override public ReadFuture addListener(IoFutureListener listener) { return (ReadFuture) super.addListener(listener); } @Override public ReadFuture removeListener(IoFutureListener listener) { return (ReadFuture) super.removeListener(listener); } private static class ExceptionHolder { private final Throwable exception; private ExceptionHolder(Throwable exception) { this.exception = exception; } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/buffer/0000755000175000017500000000000012162575507025261 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/buffer/IoBufferHexDumper.java0000644000175000017500000000604312032276031031434 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.buffer; /** * Provides utility methods to dump an {@link IoBuffer} into a hex formatted string. * * @author Apache MINA Project */ class IoBufferHexDumper { /** * The high digits lookup table. */ private static final byte[] highDigits; /** * The low digits lookup table. */ private static final byte[] lowDigits; /** * Initialize lookup tables. */ static { final byte[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; int i; byte[] high = new byte[256]; byte[] low = new byte[256]; for (i = 0; i < 256; i++) { high[i] = digits[i >>> 4]; low[i] = digits[i & 0x0F]; } highDigits = high; lowDigits = low; } /** * Dumps an {@link IoBuffer} to a hex formatted string. * * @param in the buffer to dump * @param lengthLimit the limit at which hex dumping will stop * @return a hex formatted string representation of the in {@link Iobuffer}. */ public static String getHexdump(IoBuffer in, int lengthLimit) { if (lengthLimit == 0) { throw new IllegalArgumentException("lengthLimit: " + lengthLimit + " (expected: 1+)"); } boolean truncate = in.remaining() > lengthLimit; int size; if (truncate) { size = lengthLimit; } else { size = in.remaining(); } if (size == 0) { return "empty"; } StringBuilder out = new StringBuilder(size * 3 + 3); int mark = in.position(); // fill the first int byteValue = in.get() & 0xFF; out.append((char) highDigits[byteValue]); out.append((char) lowDigits[byteValue]); size--; // and the others, too for (; size > 0; size--) { out.append(' '); byteValue = in.get() & 0xFF; out.append((char) highDigits[byteValue]); out.append((char) lowDigits[byteValue]); } in.position(mark); if (truncate) { out.append("..."); } return out.toString(); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/buffer/IoBuffer.java0000644000175000017500000014237312032276031027621 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.buffer; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.BufferOverflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.CharBuffer; import java.nio.DoubleBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; import java.nio.ReadOnlyBufferException; import java.nio.ShortBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.util.EnumSet; import java.util.Set; import org.apache.mina.core.session.IoSession; /** * A byte buffer used by MINA applications. *

* This is a replacement for {@link ByteBuffer}. Please refer to * {@link ByteBuffer} documentation for preliminary usage. MINA does not use NIO * {@link ByteBuffer} directly for two reasons: *

    *
  • It doesn't provide useful getters and putters such as fill, * get/putString, and get/putAsciiInt() enough.
  • *
  • It is difficult to write variable-length data due to its fixed capacity
  • *
*

* *

Allocation

*

* You can allocate a new heap buffer. * *

 * IoBuffer buf = IoBuffer.allocate(1024, false);
 * 
* * you can also allocate a new direct buffer: * *
 * IoBuffer buf = IoBuffer.allocate(1024, true);
 * 
* * or you can set the default buffer type. * *
 * // Allocate heap buffer by default.
 * IoBuffer.setUseDirectBuffer(false);
 * // A new heap buffer is returned.
 * IoBuffer buf = IoBuffer.allocate(1024);
 * 
* *

* *

Wrapping existing NIO buffers and arrays

*

* This class provides a few wrap(...) methods that wraps any NIO * buffers and byte arrays. * *

AutoExpand

*

* Writing variable-length data using NIO ByteBuffers is not really * easy, and it is because its size is fixed. {@link IoBuffer} introduces * autoExpand property. If autoExpand property is true, you * never get {@link BufferOverflowException} or * {@link IndexOutOfBoundsException} (except when index is negative). It * automatically expands its capacity and limit value. For example: * *

 * String greeting = messageBundle.getMessage("hello");
 * IoBuffer buf = IoBuffer.allocate(16);
 * // Turn on autoExpand (it is off by default)
 * buf.setAutoExpand(true);
 * buf.putString(greeting, utf8encoder);
 * 
* * The underlying {@link ByteBuffer} is reallocated by {@link IoBuffer} behind * the scene if the encoded data is larger than 16 bytes in the example above. * Its capacity will double, and its limit will increase to the last position * the string is written. *

* *

AutoShrink

*

* You might also want to decrease the capacity of the buffer when most of the * allocated memory area is not being used. {@link IoBuffer} provides * autoShrink property to take care of this issue. If * autoShrink is turned on, {@link IoBuffer} halves the capacity of the * buffer when {@link #compact()} is invoked and only 1/4 or less of the current * capacity is being used. *

* You can also {@link #shrink()} method manually to shrink the capacity of the * buffer. *

* The underlying {@link ByteBuffer} is reallocated by {@link IoBuffer} behind * the scene, and therefore {@link #buf()} will return a different * {@link ByteBuffer} instance once capacity changes. Please also note * {@link #compact()} or {@link #shrink()} will not decrease the capacity if the * new capacity is less than the {@link #minimumCapacity()} of the buffer. * *

Derived Buffers

*

* Derived buffers are the buffers which were created by {@link #duplicate()}, * {@link #slice()}, or {@link #asReadOnlyBuffer()}. They are useful especially * when you broadcast the same messages to multiple {@link IoSession}s. Please * note that the buffer derived from and its derived buffers are not both * auto-expandable neither auto-shrinkable. Trying to call * {@link #setAutoExpand(boolean)} or {@link #setAutoShrink(boolean)} with * true parameter will raise an {@link IllegalStateException}. *

* *

Changing Buffer Allocation Policy

*

* {@link IoBufferAllocator} interface lets you override the default buffer * management behavior. There are two allocators provided out-of-the-box: *

    *
  • {@link SimpleBufferAllocator} (default)
  • *
  • {@link CachedBufferAllocator}
  • *
* You can implement your own allocator and use it by calling * {@link #setAllocator(IoBufferAllocator)}. *

* * @author Apache MINA Project */ public abstract class IoBuffer implements Comparable { /** The allocator used to create new buffers */ private static IoBufferAllocator allocator = new SimpleBufferAllocator(); /** A flag indicating which type of buffer we are using : heap or direct */ private static boolean useDirectBuffer = false; /** * Returns the allocator used by existing and new buffers */ public static IoBufferAllocator getAllocator() { return allocator; } /** * Sets the allocator used by existing and new buffers */ public static void setAllocator(IoBufferAllocator newAllocator) { if (newAllocator == null) { throw new IllegalArgumentException("allocator"); } IoBufferAllocator oldAllocator = allocator; allocator = newAllocator; if (null != oldAllocator) { oldAllocator.dispose(); } } /** * Returns true if and only if a direct buffer is allocated by * default when the type of the new buffer is not specified. The default * value is false. */ public static boolean isUseDirectBuffer() { return useDirectBuffer; } /** * Sets if a direct buffer should be allocated by default when the type of * the new buffer is not specified. The default value is false. */ public static void setUseDirectBuffer(boolean useDirectBuffer) { IoBuffer.useDirectBuffer = useDirectBuffer; } /** * Returns the direct or heap buffer which is capable to store the specified * amount of bytes. * * @param capacity * the capacity of the buffer * * @see #setUseDirectBuffer(boolean) */ public static IoBuffer allocate(int capacity) { return allocate(capacity, useDirectBuffer); } /** * Returns the buffer which is capable of the specified size. * * @param capacity * the capacity of the buffer * @param direct * true to get a direct buffer, false to get a * heap buffer. */ public static IoBuffer allocate(int capacity, boolean direct) { if (capacity < 0) { throw new IllegalArgumentException("capacity: " + capacity); } return allocator.allocate(capacity, direct); } /** * Wraps the specified NIO {@link ByteBuffer} into MINA buffer. */ public static IoBuffer wrap(ByteBuffer nioBuffer) { return allocator.wrap(nioBuffer); } /** * Wraps the specified byte array into MINA heap buffer. */ public static IoBuffer wrap(byte[] byteArray) { return wrap(ByteBuffer.wrap(byteArray)); } /** * Wraps the specified byte array into MINA heap buffer. */ public static IoBuffer wrap(byte[] byteArray, int offset, int length) { return wrap(ByteBuffer.wrap(byteArray, offset, length)); } /** * Normalizes the specified capacity of the buffer to power of 2, which is * often helpful for optimal memory usage and performance. If it is greater * than or equal to {@link Integer#MAX_VALUE}, it returns * {@link Integer#MAX_VALUE}. If it is zero, it returns zero. */ protected static int normalizeCapacity(int requestedCapacity) { if (requestedCapacity < 0) { return Integer.MAX_VALUE; } int newCapacity = Integer.highestOneBit(requestedCapacity); newCapacity <<= (newCapacity < requestedCapacity ? 1 : 0); return newCapacity < 0 ? Integer.MAX_VALUE : newCapacity; } /** * Creates a new instance. This is an empty constructor. */ protected IoBuffer() { // Do nothing } /** * Declares this buffer and all its derived buffers are not used anymore so * that it can be reused by some {@link IoBufferAllocator} implementations. * It is not mandatory to call this method, but you might want to invoke * this method for maximum performance. */ public abstract void free(); /** * Returns the underlying NIO buffer instance. */ public abstract ByteBuffer buf(); /** * @see ByteBuffer#isDirect() */ public abstract boolean isDirect(); /** * returns true if and only if this buffer is derived from other * buffer via {@link #duplicate()}, {@link #slice()} or * {@link #asReadOnlyBuffer()}. */ public abstract boolean isDerived(); /** * @see ByteBuffer#isReadOnly() */ public abstract boolean isReadOnly(); /** * Returns the minimum capacity of this buffer which is used to determine * the new capacity of the buffer shrunk by {@link #compact()} and * {@link #shrink()} operation. The default value is the initial capacity of * the buffer. */ public abstract int minimumCapacity(); /** * Sets the minimum capacity of this buffer which is used to determine the * new capacity of the buffer shrunk by {@link #compact()} and * {@link #shrink()} operation. The default value is the initial capacity of * the buffer. */ public abstract IoBuffer minimumCapacity(int minimumCapacity); /** * @see ByteBuffer#capacity() */ public abstract int capacity(); /** * Increases the capacity of this buffer. If the new capacity is less than * or equal to the current capacity, this method returns silently. If the * new capacity is greater than the current capacity, the buffer is * reallocated while retaining the position, limit, mark and the content of * the buffer. */ public abstract IoBuffer capacity(int newCapacity); /** * Returns true if and only if autoExpand is turned on. */ public abstract boolean isAutoExpand(); /** * Turns on or off autoExpand. */ public abstract IoBuffer setAutoExpand(boolean autoExpand); /** * Returns true if and only if autoShrink is turned on. */ public abstract boolean isAutoShrink(); /** * Turns on or off autoShrink. */ public abstract IoBuffer setAutoShrink(boolean autoShrink); /** * Changes the capacity and limit of this buffer so this buffer get the * specified expectedRemaining room from the current position. This * method works even if you didn't set autoExpand to true. */ public abstract IoBuffer expand(int expectedRemaining); /** * Changes the capacity and limit of this buffer so this buffer get the * specified expectedRemaining room from the specified * position. This method works even if you didn't set * autoExpand to true. */ public abstract IoBuffer expand(int position, int expectedRemaining); /** * Changes the capacity of this buffer so this buffer occupies as less * memory as possible while retaining the position, limit and the buffer * content between the position and limit. The capacity of the buffer never * becomes less than {@link #minimumCapacity()}. The mark is discarded once * the capacity changes. */ public abstract IoBuffer shrink(); /** * @see java.nio.Buffer#position() */ public abstract int position(); /** * @see java.nio.Buffer#position(int) */ public abstract IoBuffer position(int newPosition); /** * @see java.nio.Buffer#limit() */ public abstract int limit(); /** * @see java.nio.Buffer#limit(int) */ public abstract IoBuffer limit(int newLimit); /** * @see java.nio.Buffer#mark() */ public abstract IoBuffer mark(); /** * Returns the position of the current mark. This method returns -1 * if no mark is set. */ public abstract int markValue(); /** * @see java.nio.Buffer#reset() */ public abstract IoBuffer reset(); /** * @see java.nio.Buffer#clear() */ public abstract IoBuffer clear(); /** * Clears this buffer and fills its content with NUL. The position * is set to zero, the limit is set to the capacity, and the mark is * discarded. */ public abstract IoBuffer sweep(); /** * double Clears this buffer and fills its content with value. The * position is set to zero, the limit is set to the capacity, and the mark * is discarded. */ public abstract IoBuffer sweep(byte value); /** * @see java.nio.Buffer#flip() */ public abstract IoBuffer flip(); /** * @see java.nio.Buffer#rewind() */ public abstract IoBuffer rewind(); /** * @see java.nio.Buffer#remaining() */ public abstract int remaining(); /** * @see java.nio.Buffer#hasRemaining() */ public abstract boolean hasRemaining(); /** * @see ByteBuffer#duplicate() */ public abstract IoBuffer duplicate(); /** * @see ByteBuffer#slice() */ public abstract IoBuffer slice(); /** * @see ByteBuffer#asReadOnlyBuffer() */ public abstract IoBuffer asReadOnlyBuffer(); /** * @see ByteBuffer#hasArray() */ public abstract boolean hasArray(); /** * @see ByteBuffer#array() */ public abstract byte[] array(); /** * @see ByteBuffer#arrayOffset() */ public abstract int arrayOffset(); /** * @see ByteBuffer#get() */ public abstract byte get(); /** * Reads one unsigned byte as a short integer. */ public abstract short getUnsigned(); /** * @see ByteBuffer#put(byte) */ public abstract IoBuffer put(byte b); /** * @see ByteBuffer#get(int) */ public abstract byte get(int index); /** * Reads one byte as an unsigned short integer. */ public abstract short getUnsigned(int index); /** * @see ByteBuffer#put(int, byte) */ public abstract IoBuffer put(int index, byte b); /** * @see ByteBuffer#get(byte[], int, int) */ public abstract IoBuffer get(byte[] dst, int offset, int length); /** * @see ByteBuffer#get(byte[]) */ public abstract IoBuffer get(byte[] dst); /** * TODO document me. */ public abstract IoBuffer getSlice(int index, int length); /** * TODO document me. */ public abstract IoBuffer getSlice(int length); /** * Writes the content of the specified src into this buffer. */ public abstract IoBuffer put(ByteBuffer src); /** * Writes the content of the specified src into this buffer. */ public abstract IoBuffer put(IoBuffer src); /** * @see ByteBuffer#put(byte[], int, int) */ public abstract IoBuffer put(byte[] src, int offset, int length); /** * @see ByteBuffer#put(byte[]) */ public abstract IoBuffer put(byte[] src); /** * @see ByteBuffer#compact() */ public abstract IoBuffer compact(); /** * @see ByteBuffer#order() */ public abstract ByteOrder order(); /** * @see ByteBuffer#order(ByteOrder) */ public abstract IoBuffer order(ByteOrder bo); /** * @see ByteBuffer#getChar() */ public abstract char getChar(); /** * @see ByteBuffer#putChar(char) */ public abstract IoBuffer putChar(char value); /** * @see ByteBuffer#getChar(int) */ public abstract char getChar(int index); /** * @see ByteBuffer#putChar(int, char) */ public abstract IoBuffer putChar(int index, char value); /** * @see ByteBuffer#asCharBuffer() */ public abstract CharBuffer asCharBuffer(); /** * @see ByteBuffer#getShort() */ public abstract short getShort(); /** * Reads two bytes unsigned integer. */ public abstract int getUnsignedShort(); /** * @see ByteBuffer#putShort(short) */ public abstract IoBuffer putShort(short value); /** * @see ByteBuffer#getShort() */ public abstract short getShort(int index); /** * Reads two bytes unsigned integer. */ public abstract int getUnsignedShort(int index); /** * @see ByteBuffer#putShort(int, short) */ public abstract IoBuffer putShort(int index, short value); /** * @see ByteBuffer#asShortBuffer() */ public abstract ShortBuffer asShortBuffer(); /** * @see ByteBuffer#getInt() */ public abstract int getInt(); /** * Reads four bytes unsigned integer. */ public abstract long getUnsignedInt(); /** * Relative get method for reading a medium int value. * *

* Reads the next three bytes at this buffer's current position, composing * them into an int value according to the current byte order, and then * increments the position by three. *

* * @return The medium int value at the buffer's current position */ public abstract int getMediumInt(); /** * Relative get method for reading an unsigned medium int value. * *

* Reads the next three bytes at this buffer's current position, composing * them into an int value according to the current byte order, and then * increments the position by three. *

* * @return The unsigned medium int value at the buffer's current position */ public abstract int getUnsignedMediumInt(); /** * Absolute get method for reading a medium int value. * *

* Reads the next three bytes at this buffer's current position, composing * them into an int value according to the current byte order. *

* * @param index * The index from which the medium int will be read * @return The medium int value at the given index * * @throws IndexOutOfBoundsException * If index is negative or not smaller than the * buffer's limit */ public abstract int getMediumInt(int index); /** * Absolute get method for reading an unsigned medium int value. * *

* Reads the next three bytes at this buffer's current position, composing * them into an int value according to the current byte order. *

* * @param index * The index from which the unsigned medium int will be read * @return The unsigned medium int value at the given index * * @throws IndexOutOfBoundsException * If index is negative or not smaller than the * buffer's limit */ public abstract int getUnsignedMediumInt(int index); /** * Relative put method for writing a medium int value. * *

* Writes three bytes containing the given int value, in the current byte * order, into this buffer at the current position, and then increments the * position by three. *

* * @param value * The medium int value to be written * * @return This buffer * * @throws BufferOverflowException * If there are fewer than three bytes remaining in this buffer * * @throws ReadOnlyBufferException * If this buffer is read-only */ public abstract IoBuffer putMediumInt(int value); /** * Absolute put method for writing a medium int value. * *

* Writes three bytes containing the given int value, in the current byte * order, into this buffer at the given index. *

* * @param index * The index at which the bytes will be written * * @param value * The medium int value to be written * * @return This buffer * * @throws IndexOutOfBoundsException * If index is negative or not smaller than the * buffer's limit, minus three * * @throws ReadOnlyBufferException * If this buffer is read-only */ public abstract IoBuffer putMediumInt(int index, int value); /** * @see ByteBuffer#putInt(int) */ public abstract IoBuffer putInt(int value); /** * Writes an unsigned byte into the ByteBuffer * @param value the byte to write */ public abstract IoBuffer putUnsigned(byte value); /** * Writes an unsigned byte into the ByteBuffer at a specified position * @param index the position in the buffer to write the value * @param value the byte to write */ public abstract IoBuffer putUnsigned(int index, byte value); /** * Writes an unsigned byte into the ByteBuffer * @param value the short to write */ public abstract IoBuffer putUnsigned(short value); /** * Writes an unsigned byte into the ByteBuffer at a specified position * @param index the position in the buffer to write the value * @param value the short to write */ public abstract IoBuffer putUnsigned(int index, short value); /** * Writes an unsigned byte into the ByteBuffer * @param value the int to write */ public abstract IoBuffer putUnsigned(int value); /** * Writes an unsigned byte into the ByteBuffer at a specified position * @param index the position in the buffer to write the value * @param value the int to write */ public abstract IoBuffer putUnsigned(int index, int value); /** * Writes an unsigned byte into the ByteBuffer * @param value the long to write */ public abstract IoBuffer putUnsigned(long value); /** * Writes an unsigned byte into the ByteBuffer at a specified position * @param index the position in the buffer to write the value * @param value the long to write */ public abstract IoBuffer putUnsigned(int index, long value); /** * Writes an unsigned int into the ByteBuffer * @param value the byte to write */ public abstract IoBuffer putUnsignedInt(byte value); /** * Writes an unsigned int into the ByteBuffer at a specified position * @param index the position in the buffer to write the value * @param value the byte to write */ public abstract IoBuffer putUnsignedInt(int index, byte value); /** * Writes an unsigned int into the ByteBuffer * @param value the short to write */ public abstract IoBuffer putUnsignedInt(short value); /** * Writes an unsigned int into the ByteBuffer at a specified position * @param index the position in the buffer to write the value * @param value the short to write */ public abstract IoBuffer putUnsignedInt(int index, short value); /** * Writes an unsigned int into the ByteBuffer * @param value the int to write */ public abstract IoBuffer putUnsignedInt(int value); /** * Writes an unsigned int into the ByteBuffer at a specified position * @param index the position in the buffer to write the value * @param value the int to write */ public abstract IoBuffer putUnsignedInt(int index, int value); /** * Writes an unsigned int into the ByteBuffer * @param value the long to write */ public abstract IoBuffer putUnsignedInt(long value); /** * Writes an unsigned int into the ByteBuffer at a specified position * @param index the position in the buffer to write the value * @param value the long to write */ public abstract IoBuffer putUnsignedInt(int index, long value); /** * Writes an unsigned short into the ByteBuffer * @param value the byte to write */ public abstract IoBuffer putUnsignedShort(byte value); /** * Writes an unsigned Short into the ByteBuffer at a specified position * @param index the position in the buffer to write the value * @param value the byte to write */ public abstract IoBuffer putUnsignedShort(int index, byte value); /** * Writes an unsigned Short into the ByteBuffer * @param value the short to write */ public abstract IoBuffer putUnsignedShort(short value); /** * Writes an unsigned Short into the ByteBuffer at a specified position * @param index the position in the buffer to write the value * @param value the short to write */ public abstract IoBuffer putUnsignedShort(int index, short value); /** * Writes an unsigned Short into the ByteBuffer * @param value the int to write */ public abstract IoBuffer putUnsignedShort(int value); /** * Writes an unsigned Short into the ByteBuffer at a specified position * @param index the position in the buffer to write the value * @param value the int to write */ public abstract IoBuffer putUnsignedShort(int index, int value); /** * Writes an unsigned Short into the ByteBuffer * @param value the long to write */ public abstract IoBuffer putUnsignedShort(long value); /** * Writes an unsigned Short into the ByteBuffer at a specified position * @param index the position in the buffer to write the value * @param value the long to write */ public abstract IoBuffer putUnsignedShort(int index, long value); /** * @see ByteBuffer#getInt(int) */ public abstract int getInt(int index); /** * Reads four bytes unsigned integer. * @param index the position in the buffer to write the value */ public abstract long getUnsignedInt(int index); /** * @see ByteBuffer#putInt(int, int) */ public abstract IoBuffer putInt(int index, int value); /** * @see ByteBuffer#asIntBuffer() */ public abstract IntBuffer asIntBuffer(); /** * @see ByteBuffer#getLong() */ public abstract long getLong(); /** * @see ByteBuffer#putLong(int, long) */ public abstract IoBuffer putLong(long value); /** * @see ByteBuffer#getLong(int) */ public abstract long getLong(int index); /** * @see ByteBuffer#putLong(int, long) */ public abstract IoBuffer putLong(int index, long value); /** * @see ByteBuffer#asLongBuffer() */ public abstract LongBuffer asLongBuffer(); /** * @see ByteBuffer#getFloat() */ public abstract float getFloat(); /** * @see ByteBuffer#putFloat(float) */ public abstract IoBuffer putFloat(float value); /** * @see ByteBuffer#getFloat(int) */ public abstract float getFloat(int index); /** * @see ByteBuffer#putFloat(int, float) */ public abstract IoBuffer putFloat(int index, float value); /** * @see ByteBuffer#asFloatBuffer() */ public abstract FloatBuffer asFloatBuffer(); /** * @see ByteBuffer#getDouble() */ public abstract double getDouble(); /** * @see ByteBuffer#putDouble(double) */ public abstract IoBuffer putDouble(double value); /** * @see ByteBuffer#getDouble(int) */ public abstract double getDouble(int index); /** * @see ByteBuffer#putDouble(int, double) */ public abstract IoBuffer putDouble(int index, double value); /** * @see ByteBuffer#asDoubleBuffer() */ public abstract DoubleBuffer asDoubleBuffer(); /** * Returns an {@link InputStream} that reads the data from this buffer. * {@link InputStream#read()} returns -1 if the buffer position * reaches to the limit. */ public abstract InputStream asInputStream(); /** * Returns an {@link OutputStream} that appends the data into this buffer. * Please note that the {@link OutputStream#write(int)} will throw a * {@link BufferOverflowException} instead of an {@link IOException} in case * of buffer overflow. Please set autoExpand property by calling * {@link #setAutoExpand(boolean)} to prevent the unexpected runtime * exception. */ public abstract OutputStream asOutputStream(); /** * Returns hexdump of this buffer. The data and pointer are not changed as a * result of this method call. * * @return hexidecimal representation of this buffer */ public abstract String getHexDump(); /** * Return hexdump of this buffer with limited length. * * @param lengthLimit * The maximum number of bytes to dump from the current buffer * position. * @return hexidecimal representation of this buffer */ public abstract String getHexDump(int lengthLimit); // ////////////////////////////// // String getters and putters // // ////////////////////////////// /** * Reads a NUL-terminated string from this buffer using the * specified decoder and returns it. This method reads until * the limit of this buffer if no NUL is found. */ public abstract String getString(CharsetDecoder decoder) throws CharacterCodingException; /** * Reads a NUL-terminated string from this buffer using the * specified decoder and returns it. * * @param fieldSize * the maximum number of bytes to read */ public abstract String getString(int fieldSize, CharsetDecoder decoder) throws CharacterCodingException; /** * Writes the content of in into this buffer using the * specified encoder. This method doesn't terminate string with * NUL. You have to do it by yourself. * * @throws BufferOverflowException * if the specified string doesn't fit */ public abstract IoBuffer putString(CharSequence val, CharsetEncoder encoder) throws CharacterCodingException; /** * Writes the content of in into this buffer as a * NUL-terminated string using the specified * encoder. *

* If the charset name of the encoder is UTF-16, you cannot specify odd * fieldSize, and this method will append two NULs * as a terminator. *

* Please note that this method doesn't terminate with NUL if * the input string is longer than fieldSize. * * @param fieldSize * the maximum number of bytes to write */ public abstract IoBuffer putString(CharSequence val, int fieldSize, CharsetEncoder encoder) throws CharacterCodingException; /** * Reads a string which has a 16-bit length field before the actual encoded * string, using the specified decoder and returns it. This * method is a shortcut for getPrefixedString(2, decoder). */ public abstract String getPrefixedString(CharsetDecoder decoder) throws CharacterCodingException; /** * Reads a string which has a length field before the actual encoded string, * using the specified decoder and returns it. * * @param prefixLength * the length of the length field (1, 2, or 4) */ public abstract String getPrefixedString(int prefixLength, CharsetDecoder decoder) throws CharacterCodingException; /** * Writes the content of in into this buffer as a string which * has a 16-bit length field before the actual encoded string, using the * specified encoder. This method is a shortcut for * putPrefixedString(in, 2, 0, encoder). * * @throws BufferOverflowException * if the specified string doesn't fit */ public abstract IoBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder) throws CharacterCodingException; /** * Writes the content of in into this buffer as a string which * has a 16-bit length field before the actual encoded string, using the * specified encoder. This method is a shortcut for * putPrefixedString(in, prefixLength, 0, encoder). * * @param prefixLength * the length of the length field (1, 2, or 4) * * @throws BufferOverflowException * if the specified string doesn't fit */ public abstract IoBuffer putPrefixedString(CharSequence in, int prefixLength, CharsetEncoder encoder) throws CharacterCodingException; /** * Writes the content of in into this buffer as a string which * has a 16-bit length field before the actual encoded string, using the * specified encoder. This method is a shortcut for * putPrefixedString(in, prefixLength, padding, ( byte ) 0, encoder) * . * * @param prefixLength * the length of the length field (1, 2, or 4) * @param padding * the number of padded NULs (1 (or 0), 2, or 4) * * @throws BufferOverflowException * if the specified string doesn't fit */ public abstract IoBuffer putPrefixedString(CharSequence in, int prefixLength, int padding, CharsetEncoder encoder) throws CharacterCodingException; /** * Writes the content of in into this buffer as a string which * has a 16-bit length field before the actual encoded string, using the * specified encoder. * * @param prefixLength * the length of the length field (1, 2, or 4) * @param padding * the number of padded bytes (1 (or 0), 2, or 4) * @param padValue * the value of padded bytes * * @throws BufferOverflowException * if the specified string doesn't fit */ public abstract IoBuffer putPrefixedString(CharSequence val, int prefixLength, int padding, byte padValue, CharsetEncoder encoder) throws CharacterCodingException; /** * Reads a Java object from the buffer using the context {@link ClassLoader} * of the current thread. */ public abstract Object getObject() throws ClassNotFoundException; /** * Reads a Java object from the buffer using the specified * classLoader. */ public abstract Object getObject(final ClassLoader classLoader) throws ClassNotFoundException; /** * Writes the specified Java object to the buffer. */ public abstract IoBuffer putObject(Object o); /** * Returns true if this buffer contains a data which has a data * length as a prefix and the buffer has remaining data as enough as * specified in the data length field. This method is identical with * prefixedDataAvailable( prefixLength, Integer.MAX_VALUE ). Please * not that using this method can allow DoS (Denial of Service) attack in * case the remote peer sends too big data length value. It is recommended * to use {@link #prefixedDataAvailable(int, int)} instead. * * @param prefixLength * the length of the prefix field (1, 2, or 4) * * @throws IllegalArgumentException * if prefixLength is wrong * @throws BufferDataException * if data length is negative */ public abstract boolean prefixedDataAvailable(int prefixLength); /** * Returns true if this buffer contains a data which has a data * length as a prefix and the buffer has remaining data as enough as * specified in the data length field. * * @param prefixLength * the length of the prefix field (1, 2, or 4) * @param maxDataLength * the allowed maximum of the read data length * * @throws IllegalArgumentException * if prefixLength is wrong * @throws BufferDataException * if data length is negative or greater then * maxDataLength */ public abstract boolean prefixedDataAvailable(int prefixLength, int maxDataLength); // /////////////////// // IndexOf methods // // /////////////////// /** * Returns the first occurence position of the specified byte from the * current position to the current limit. * * @return -1 if the specified byte is not found */ public abstract int indexOf(byte b); // //////////////////////// // Skip or fill methods // // //////////////////////// /** * Forwards the position of this buffer as the specified size * bytes. */ public abstract IoBuffer skip(int size); /** * Fills this buffer with the specified value. This method moves buffer * position forward. */ public abstract IoBuffer fill(byte value, int size); /** * Fills this buffer with the specified value. This method does not change * buffer position. */ public abstract IoBuffer fillAndReset(byte value, int size); /** * Fills this buffer with NUL (0x00). This method moves buffer * position forward. */ public abstract IoBuffer fill(int size); /** * Fills this buffer with NUL (0x00). This method does not * change buffer position. */ public abstract IoBuffer fillAndReset(int size); // //////////////////////// // Enum methods // // //////////////////////// /** * Reads a byte from the buffer and returns the correlating enum constant * defined by the specified enum type. * * @param * The enum type to return * @param enumClass * The enum's class object */ public abstract > E getEnum(Class enumClass); /** * Reads a byte from the buffer and returns the correlating enum constant * defined by the specified enum type. * * @param * The enum type to return * @param index * the index from which the byte will be read * @param enumClass * The enum's class object */ public abstract > E getEnum(int index, Class enumClass); /** * Reads a short from the buffer and returns the correlating enum constant * defined by the specified enum type. * * @param * The enum type to return * @param enumClass * The enum's class object */ public abstract > E getEnumShort(Class enumClass); /** * Reads a short from the buffer and returns the correlating enum constant * defined by the specified enum type. * * @param * The enum type to return * @param index * the index from which the bytes will be read * @param enumClass * The enum's class object */ public abstract > E getEnumShort(int index, Class enumClass); /** * Reads an int from the buffer and returns the correlating enum constant * defined by the specified enum type. * * @param * The enum type to return * @param enumClass * The enum's class object */ public abstract > E getEnumInt(Class enumClass); /** * Reads an int from the buffer and returns the correlating enum constant * defined by the specified enum type. * * @param * The enum type to return * @param index * the index from which the bytes will be read * @param enumClass * The enum's class object */ public abstract > E getEnumInt(int index, Class enumClass); /** * Writes an enum's ordinal value to the buffer as a byte. * * @param e * The enum to write to the buffer */ public abstract IoBuffer putEnum(Enum e); /** * Writes an enum's ordinal value to the buffer as a byte. * * @param index * The index at which the byte will be written * @param e * The enum to write to the buffer */ public abstract IoBuffer putEnum(int index, Enum e); /** * Writes an enum's ordinal value to the buffer as a short. * * @param e * The enum to write to the buffer */ public abstract IoBuffer putEnumShort(Enum e); /** * Writes an enum's ordinal value to the buffer as a short. * * @param index * The index at which the bytes will be written * @param e * The enum to write to the buffer */ public abstract IoBuffer putEnumShort(int index, Enum e); /** * Writes an enum's ordinal value to the buffer as an integer. * * @param e * The enum to write to the buffer */ public abstract IoBuffer putEnumInt(Enum e); /** * Writes an enum's ordinal value to the buffer as an integer. * * @param index * The index at which the bytes will be written * @param e * The enum to write to the buffer */ public abstract IoBuffer putEnumInt(int index, Enum e); // //////////////////////// // EnumSet methods // // //////////////////////// /** * Reads a byte sized bit vector and converts it to an {@link EnumSet}. * *

* Each bit is mapped to a value in the specified enum. The least * significant bit maps to the first entry in the specified enum and each * subsequent bit maps to each subsequent bit as mapped to the subsequent * enum value. *

* * @param * the enum type * @param enumClass * the enum class used to create the EnumSet * @return the EnumSet representation of the bit vector */ public abstract > EnumSet getEnumSet(Class enumClass); /** * Reads a byte sized bit vector and converts it to an {@link EnumSet}. * * @see #getEnumSet(Class) * @param * the enum type * @param index * the index from which the byte will be read * @param enumClass * the enum class used to create the EnumSet * @return the EnumSet representation of the bit vector */ public abstract > EnumSet getEnumSet(int index, Class enumClass); /** * Reads a short sized bit vector and converts it to an {@link EnumSet}. * * @see #getEnumSet(Class) * @param * the enum type * @param enumClass * the enum class used to create the EnumSet * @return the EnumSet representation of the bit vector */ public abstract > EnumSet getEnumSetShort(Class enumClass); /** * Reads a short sized bit vector and converts it to an {@link EnumSet}. * * @see #getEnumSet(Class) * @param * the enum type * @param index * the index from which the bytes will be read * @param enumClass * the enum class used to create the EnumSet * @return the EnumSet representation of the bit vector */ public abstract > EnumSet getEnumSetShort(int index, Class enumClass); /** * Reads an int sized bit vector and converts it to an {@link EnumSet}. * * @see #getEnumSet(Class) * @param * the enum type * @param enumClass * the enum class used to create the EnumSet * @return the EnumSet representation of the bit vector */ public abstract > EnumSet getEnumSetInt(Class enumClass); /** * Reads an int sized bit vector and converts it to an {@link EnumSet}. * * @see #getEnumSet(Class) * @param * the enum type * @param index * the index from which the bytes will be read * @param enumClass * the enum class used to create the EnumSet * @return the EnumSet representation of the bit vector */ public abstract > EnumSet getEnumSetInt(int index, Class enumClass); /** * Reads a long sized bit vector and converts it to an {@link EnumSet}. * * @see #getEnumSet(Class) * @param * the enum type * @param enumClass * the enum class used to create the EnumSet * @return the EnumSet representation of the bit vector */ public abstract > EnumSet getEnumSetLong(Class enumClass); /** * Reads a long sized bit vector and converts it to an {@link EnumSet}. * * @see #getEnumSet(Class) * @param * the enum type * @param index * the index from which the bytes will be read * @param enumClass * the enum class used to create the EnumSet * @return the EnumSet representation of the bit vector */ public abstract > EnumSet getEnumSetLong(int index, Class enumClass); /** * Writes the specified {@link Set} to the buffer as a byte sized bit * vector. * * @param * the enum type of the Set * @param set * the enum set to write to the buffer */ public abstract > IoBuffer putEnumSet(Set set); /** * Writes the specified {@link Set} to the buffer as a byte sized bit * vector. * * @param * the enum type of the Set * @param index * the index at which the byte will be written * @param set * the enum set to write to the buffer */ public abstract > IoBuffer putEnumSet(int index, Set set); /** * Writes the specified {@link Set} to the buffer as a short sized bit * vector. * * @param * the enum type of the Set * @param set * the enum set to write to the buffer */ public abstract > IoBuffer putEnumSetShort(Set set); /** * Writes the specified {@link Set} to the buffer as a short sized bit * vector. * * @param * the enum type of the Set * @param index * the index at which the bytes will be written * @param set * the enum set to write to the buffer */ public abstract > IoBuffer putEnumSetShort(int index, Set set); /** * Writes the specified {@link Set} to the buffer as an int sized bit * vector. * * @param * the enum type of the Set * @param set * the enum set to write to the buffer */ public abstract > IoBuffer putEnumSetInt(Set set); /** * Writes the specified {@link Set} to the buffer as an int sized bit * vector. * * @param * the enum type of the Set * @param index * the index at which the bytes will be written * @param set * the enum set to write to the buffer */ public abstract > IoBuffer putEnumSetInt(int index, Set set); /** * Writes the specified {@link Set} to the buffer as a long sized bit * vector. * * @param * the enum type of the Set * @param set * the enum set to write to the buffer */ public abstract > IoBuffer putEnumSetLong(Set set); /** * Writes the specified {@link Set} to the buffer as a long sized bit * vector. * * @param * the enum type of the Set * @param index * the index at which the bytes will be written * @param set * the enum set to write to the buffer */ public abstract > IoBuffer putEnumSetLong(int index, Set set); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/buffer/BufferDataException.java0000644000175000017500000000274312032276031031776 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.buffer; /** * A {@link RuntimeException} which is thrown when the data the {@link IoBuffer} * contains is corrupt. * * @author Apache MINA Project * */ public class BufferDataException extends RuntimeException { private static final long serialVersionUID = -4138189188602563502L; public BufferDataException() { super(); } public BufferDataException(String message) { super(message); } public BufferDataException(String message, Throwable cause) { super(message, cause); } public BufferDataException(Throwable cause) { super(cause); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/buffer/IoBufferWrapper.java0000644000175000017500000005506612032276031031164 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.buffer; import java.io.FilterOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.CharBuffer; import java.nio.DoubleBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; import java.nio.ShortBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.util.EnumSet; import java.util.Set; /** * A {@link IoBuffer} that wraps a buffer and proxies any operations to it. *

* You can think this class like a {@link FilterOutputStream}. All operations * are proxied by default so that you can extend this class and override existing * operations selectively. You can introduce new operations, too. * * @author Apache MINA Project */ public class IoBufferWrapper extends IoBuffer { /** * The buffer proxied by this proxy. */ private final IoBuffer buf; /** * Create a new instance. * @param buf the buffer to be proxied */ protected IoBufferWrapper(IoBuffer buf) { if (buf == null) { throw new IllegalArgumentException("buf"); } this.buf = buf; } /** * Returns the parent buffer that this buffer wrapped. */ public IoBuffer getParentBuffer() { return buf; } @Override public boolean isDirect() { return buf.isDirect(); } @Override public ByteBuffer buf() { return buf.buf(); } @Override public int capacity() { return buf.capacity(); } @Override public int position() { return buf.position(); } @Override public IoBuffer position(int newPosition) { buf.position(newPosition); return this; } @Override public int limit() { return buf.limit(); } @Override public IoBuffer limit(int newLimit) { buf.limit(newLimit); return this; } @Override public IoBuffer mark() { buf.mark(); return this; } @Override public IoBuffer reset() { buf.reset(); return this; } @Override public IoBuffer clear() { buf.clear(); return this; } @Override public IoBuffer sweep() { buf.sweep(); return this; } @Override public IoBuffer sweep(byte value) { buf.sweep(value); return this; } @Override public IoBuffer flip() { buf.flip(); return this; } @Override public IoBuffer rewind() { buf.rewind(); return this; } @Override public int remaining() { return buf.remaining(); } @Override public boolean hasRemaining() { return buf.hasRemaining(); } @Override public byte get() { return buf.get(); } @Override public short getUnsigned() { return buf.getUnsigned(); } @Override public IoBuffer put(byte b) { buf.put(b); return this; } @Override public byte get(int index) { return buf.get(index); } @Override public short getUnsigned(int index) { return buf.getUnsigned(index); } @Override public IoBuffer put(int index, byte b) { buf.put(index, b); return this; } @Override public IoBuffer get(byte[] dst, int offset, int length) { buf.get(dst, offset, length); return this; } @Override public IoBuffer getSlice(int index, int length) { return buf.getSlice(index, length); } @Override public IoBuffer getSlice(int length) { return buf.getSlice(length); } @Override public IoBuffer get(byte[] dst) { buf.get(dst); return this; } @Override public IoBuffer put(IoBuffer src) { buf.put(src); return this; } @Override public IoBuffer put(ByteBuffer src) { buf.put(src); return this; } @Override public IoBuffer put(byte[] src, int offset, int length) { buf.put(src, offset, length); return this; } @Override public IoBuffer put(byte[] src) { buf.put(src); return this; } @Override public IoBuffer compact() { buf.compact(); return this; } @Override public String toString() { return buf.toString(); } @Override public int hashCode() { return buf.hashCode(); } @Override public boolean equals(Object ob) { return buf.equals(ob); } public int compareTo(IoBuffer that) { return buf.compareTo(that); } @Override public ByteOrder order() { return buf.order(); } @Override public IoBuffer order(ByteOrder bo) { buf.order(bo); return this; } @Override public char getChar() { return buf.getChar(); } @Override public IoBuffer putChar(char value) { buf.putChar(value); return this; } @Override public char getChar(int index) { return buf.getChar(index); } @Override public IoBuffer putChar(int index, char value) { buf.putChar(index, value); return this; } @Override public CharBuffer asCharBuffer() { return buf.asCharBuffer(); } @Override public short getShort() { return buf.getShort(); } @Override public int getUnsignedShort() { return buf.getUnsignedShort(); } @Override public IoBuffer putShort(short value) { buf.putShort(value); return this; } @Override public short getShort(int index) { return buf.getShort(index); } @Override public int getUnsignedShort(int index) { return buf.getUnsignedShort(index); } @Override public IoBuffer putShort(int index, short value) { buf.putShort(index, value); return this; } @Override public ShortBuffer asShortBuffer() { return buf.asShortBuffer(); } @Override public int getInt() { return buf.getInt(); } @Override public long getUnsignedInt() { return buf.getUnsignedInt(); } @Override public IoBuffer putInt(int value) { buf.putInt(value); return this; } @Override public IoBuffer putUnsignedInt(byte value) { buf.putUnsignedInt(value); return this; } @Override public IoBuffer putUnsignedInt(int index, byte value) { buf.putUnsignedInt(index, value); return this; } @Override public IoBuffer putUnsignedInt(short value) { buf.putUnsignedInt(value); return this; } @Override public IoBuffer putUnsignedInt(int index, short value) { buf.putUnsignedInt(index, value); return this; } @Override public IoBuffer putUnsignedInt(int value) { buf.putUnsignedInt(value); return this; } @Override public IoBuffer putUnsignedInt(int index, int value) { buf.putUnsignedInt(index, value); return this; } @Override public IoBuffer putUnsignedInt(long value) { buf.putUnsignedInt(value); return this; } @Override public IoBuffer putUnsignedInt(int index, long value) { buf.putUnsignedInt(index, value); return this; } @Override public IoBuffer putUnsignedShort(byte value) { buf.putUnsignedShort(value); return this; } @Override public IoBuffer putUnsignedShort(int index, byte value) { buf.putUnsignedShort(index, value); return this; } @Override public IoBuffer putUnsignedShort(short value) { buf.putUnsignedShort(value); return this; } @Override public IoBuffer putUnsignedShort(int index, short value) { buf.putUnsignedShort(index, value); return this; } @Override public IoBuffer putUnsignedShort(int value) { buf.putUnsignedShort(value); return this; } @Override public IoBuffer putUnsignedShort(int index, int value) { buf.putUnsignedShort(index, value); return this; } @Override public IoBuffer putUnsignedShort(long value) { buf.putUnsignedShort(value); return this; } @Override public IoBuffer putUnsignedShort(int index, long value) { buf.putUnsignedShort(index, value); return this; } @Override public int getInt(int index) { return buf.getInt(index); } @Override public long getUnsignedInt(int index) { return buf.getUnsignedInt(index); } @Override public IoBuffer putInt(int index, int value) { buf.putInt(index, value); return this; } @Override public IntBuffer asIntBuffer() { return buf.asIntBuffer(); } @Override public long getLong() { return buf.getLong(); } @Override public IoBuffer putLong(long value) { buf.putLong(value); return this; } @Override public long getLong(int index) { return buf.getLong(index); } @Override public IoBuffer putLong(int index, long value) { buf.putLong(index, value); return this; } @Override public LongBuffer asLongBuffer() { return buf.asLongBuffer(); } @Override public float getFloat() { return buf.getFloat(); } @Override public IoBuffer putFloat(float value) { buf.putFloat(value); return this; } @Override public float getFloat(int index) { return buf.getFloat(index); } @Override public IoBuffer putFloat(int index, float value) { buf.putFloat(index, value); return this; } @Override public FloatBuffer asFloatBuffer() { return buf.asFloatBuffer(); } @Override public double getDouble() { return buf.getDouble(); } @Override public IoBuffer putDouble(double value) { buf.putDouble(value); return this; } @Override public double getDouble(int index) { return buf.getDouble(index); } @Override public IoBuffer putDouble(int index, double value) { buf.putDouble(index, value); return this; } @Override public DoubleBuffer asDoubleBuffer() { return buf.asDoubleBuffer(); } @Override public String getHexDump() { return buf.getHexDump(); } @Override public String getString(int fieldSize, CharsetDecoder decoder) throws CharacterCodingException { return buf.getString(fieldSize, decoder); } @Override public String getString(CharsetDecoder decoder) throws CharacterCodingException { return buf.getString(decoder); } @Override public String getPrefixedString(CharsetDecoder decoder) throws CharacterCodingException { return buf.getPrefixedString(decoder); } @Override public String getPrefixedString(int prefixLength, CharsetDecoder decoder) throws CharacterCodingException { return buf.getPrefixedString(prefixLength, decoder); } @Override public IoBuffer putString(CharSequence in, int fieldSize, CharsetEncoder encoder) throws CharacterCodingException { buf.putString(in, fieldSize, encoder); return this; } @Override public IoBuffer putString(CharSequence in, CharsetEncoder encoder) throws CharacterCodingException { buf.putString(in, encoder); return this; } @Override public IoBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder) throws CharacterCodingException { buf.putPrefixedString(in, encoder); return this; } @Override public IoBuffer putPrefixedString(CharSequence in, int prefixLength, CharsetEncoder encoder) throws CharacterCodingException { buf.putPrefixedString(in, prefixLength, encoder); return this; } @Override public IoBuffer putPrefixedString(CharSequence in, int prefixLength, int padding, CharsetEncoder encoder) throws CharacterCodingException { buf.putPrefixedString(in, prefixLength, padding, encoder); return this; } @Override public IoBuffer putPrefixedString(CharSequence in, int prefixLength, int padding, byte padValue, CharsetEncoder encoder) throws CharacterCodingException { buf.putPrefixedString(in, prefixLength, padding, padValue, encoder); return this; } @Override public IoBuffer skip(int size) { buf.skip(size); return this; } @Override public IoBuffer fill(byte value, int size) { buf.fill(value, size); return this; } @Override public IoBuffer fillAndReset(byte value, int size) { buf.fillAndReset(value, size); return this; } @Override public IoBuffer fill(int size) { buf.fill(size); return this; } @Override public IoBuffer fillAndReset(int size) { buf.fillAndReset(size); return this; } @Override public boolean isAutoExpand() { return buf.isAutoExpand(); } @Override public IoBuffer setAutoExpand(boolean autoExpand) { buf.setAutoExpand(autoExpand); return this; } @Override public IoBuffer expand(int pos, int expectedRemaining) { buf.expand(pos, expectedRemaining); return this; } @Override public IoBuffer expand(int expectedRemaining) { buf.expand(expectedRemaining); return this; } @Override public Object getObject() throws ClassNotFoundException { return buf.getObject(); } @Override public Object getObject(ClassLoader classLoader) throws ClassNotFoundException { return buf.getObject(classLoader); } @Override public IoBuffer putObject(Object o) { buf.putObject(o); return this; } @Override public InputStream asInputStream() { return buf.asInputStream(); } @Override public OutputStream asOutputStream() { return buf.asOutputStream(); } @Override public IoBuffer duplicate() { return buf.duplicate(); } @Override public IoBuffer slice() { return buf.slice(); } @Override public IoBuffer asReadOnlyBuffer() { return buf.asReadOnlyBuffer(); } @Override public byte[] array() { return buf.array(); } @Override public int arrayOffset() { return buf.arrayOffset(); } @Override public int minimumCapacity() { return buf.minimumCapacity(); } @Override public IoBuffer minimumCapacity(int minimumCapacity) { buf.minimumCapacity(minimumCapacity); return this; } @Override public IoBuffer capacity(int newCapacity) { buf.capacity(newCapacity); return this; } @Override public boolean isReadOnly() { return buf.isReadOnly(); } @Override public int markValue() { return buf.markValue(); } @Override public boolean hasArray() { return buf.hasArray(); } @Override public void free() { buf.free(); } @Override public boolean isDerived() { return buf.isDerived(); } @Override public boolean isAutoShrink() { return buf.isAutoShrink(); } @Override public IoBuffer setAutoShrink(boolean autoShrink) { buf.setAutoShrink(autoShrink); return this; } @Override public IoBuffer shrink() { buf.shrink(); return this; } @Override public int getMediumInt() { return buf.getMediumInt(); } @Override public int getUnsignedMediumInt() { return buf.getUnsignedMediumInt(); } @Override public int getMediumInt(int index) { return buf.getMediumInt(index); } @Override public int getUnsignedMediumInt(int index) { return buf.getUnsignedMediumInt(index); } @Override public IoBuffer putMediumInt(int value) { buf.putMediumInt(value); return this; } @Override public IoBuffer putMediumInt(int index, int value) { buf.putMediumInt(index, value); return this; } @Override public String getHexDump(int lengthLimit) { return buf.getHexDump(lengthLimit); } @Override public boolean prefixedDataAvailable(int prefixLength) { return buf.prefixedDataAvailable(prefixLength); } @Override public boolean prefixedDataAvailable(int prefixLength, int maxDataLength) { return buf.prefixedDataAvailable(prefixLength, maxDataLength); } @Override public int indexOf(byte b) { return buf.indexOf(b); } @Override public > E getEnum(Class enumClass) { return buf.getEnum(enumClass); } @Override public > E getEnum(int index, Class enumClass) { return buf.getEnum(index, enumClass); } @Override public > E getEnumShort(Class enumClass) { return buf.getEnumShort(enumClass); } @Override public > E getEnumShort(int index, Class enumClass) { return buf.getEnumShort(index, enumClass); } @Override public > E getEnumInt(Class enumClass) { return buf.getEnumInt(enumClass); } @Override public > E getEnumInt(int index, Class enumClass) { return buf.getEnumInt(index, enumClass); } @Override public IoBuffer putEnum(Enum e) { buf.putEnum(e); return this; } @Override public IoBuffer putEnum(int index, Enum e) { buf.putEnum(index, e); return this; } @Override public IoBuffer putEnumShort(Enum e) { buf.putEnumShort(e); return this; } @Override public IoBuffer putEnumShort(int index, Enum e) { buf.putEnumShort(index, e); return this; } @Override public IoBuffer putEnumInt(Enum e) { buf.putEnumInt(e); return this; } @Override public IoBuffer putEnumInt(int index, Enum e) { buf.putEnumInt(index, e); return this; } @Override public > EnumSet getEnumSet(Class enumClass) { return buf.getEnumSet(enumClass); } @Override public > EnumSet getEnumSet(int index, Class enumClass) { return buf.getEnumSet(index, enumClass); } @Override public > EnumSet getEnumSetShort(Class enumClass) { return buf.getEnumSetShort(enumClass); } @Override public > EnumSet getEnumSetShort(int index, Class enumClass) { return buf.getEnumSetShort(index, enumClass); } @Override public > EnumSet getEnumSetInt(Class enumClass) { return buf.getEnumSetInt(enumClass); } @Override public > EnumSet getEnumSetInt(int index, Class enumClass) { return buf.getEnumSetInt(index, enumClass); } @Override public > EnumSet getEnumSetLong(Class enumClass) { return buf.getEnumSetLong(enumClass); } @Override public > EnumSet getEnumSetLong(int index, Class enumClass) { return buf.getEnumSetLong(index, enumClass); } @Override public > IoBuffer putEnumSet(Set set) { buf.putEnumSet(set); return this; } @Override public > IoBuffer putEnumSet(int index, Set set) { buf.putEnumSet(index, set); return this; } @Override public > IoBuffer putEnumSetShort(Set set) { buf.putEnumSetShort(set); return this; } @Override public > IoBuffer putEnumSetShort(int index, Set set) { buf.putEnumSetShort(index, set); return this; } @Override public > IoBuffer putEnumSetInt(Set set) { buf.putEnumSetInt(set); return this; } @Override public > IoBuffer putEnumSetInt(int index, Set set) { buf.putEnumSetInt(index, set); return this; } @Override public > IoBuffer putEnumSetLong(Set set) { buf.putEnumSetLong(set); return this; } @Override public > IoBuffer putEnumSetLong(int index, Set set) { buf.putEnumSetLong(index, set); return this; } @Override public IoBuffer putUnsigned(byte value) { buf.putUnsigned(value); return this; } @Override public IoBuffer putUnsigned(int index, byte value) { buf.putUnsigned(index, value); return this; } @Override public IoBuffer putUnsigned(short value) { buf.putUnsigned(value); return this; } @Override public IoBuffer putUnsigned(int index, short value) { buf.putUnsigned(index, value); return this; } @Override public IoBuffer putUnsigned(int value) { buf.putUnsigned(value); return this; } @Override public IoBuffer putUnsigned(int index, int value) { buf.putUnsigned(index, value); return this; } @Override public IoBuffer putUnsigned(long value) { buf.putUnsigned(value); return this; } @Override public IoBuffer putUnsigned(int index, long value) { buf.putUnsigned(index, value); return this; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/buffer/IoBufferAllocator.java0000644000175000017500000000367212032276031031460 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.buffer; import java.nio.ByteBuffer; /** * Allocates {@link IoBuffer}s and manages them. Please implement this * interface if you need more advanced memory management scheme. * * @author Apache MINA Project */ public interface IoBufferAllocator { /** * Returns the buffer which is capable of the specified size. * * @param capacity the capacity of the buffer * @param direct true to get a direct buffer, * false to get a heap buffer. */ IoBuffer allocate(int capacity, boolean direct); /** * Returns the NIO buffer which is capable of the specified size. * * @param capacity the capacity of the buffer * @param direct true to get a direct buffer, * false to get a heap buffer. */ ByteBuffer allocateNioBuffer(int capacity, boolean direct); /** * Wraps the specified NIO {@link ByteBuffer} into MINA buffer. */ IoBuffer wrap(ByteBuffer nioBuffer); /** * Dispose of this allocator. */ void dispose(); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/buffer/SimpleBufferAllocator.java0000644000175000017500000000612112032276031032332 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; /** * A simplistic {@link IoBufferAllocator} which simply allocates a new * buffer every time. * * @author Apache MINA Project */ public class SimpleBufferAllocator implements IoBufferAllocator { public IoBuffer allocate(int capacity, boolean direct) { return wrap(allocateNioBuffer(capacity, direct)); } public ByteBuffer allocateNioBuffer(int capacity, boolean direct) { ByteBuffer nioBuffer; if (direct) { nioBuffer = ByteBuffer.allocateDirect(capacity); } else { nioBuffer = ByteBuffer.allocate(capacity); } return nioBuffer; } public IoBuffer wrap(ByteBuffer nioBuffer) { return new SimpleBuffer(nioBuffer); } public void dispose() { // Do nothing } private class SimpleBuffer extends AbstractIoBuffer { private ByteBuffer buf; protected SimpleBuffer(ByteBuffer buf) { super(SimpleBufferAllocator.this, buf.capacity()); this.buf = buf; buf.order(ByteOrder.BIG_ENDIAN); } protected SimpleBuffer(SimpleBuffer parent, ByteBuffer buf) { super(parent); this.buf = buf; } @Override public ByteBuffer buf() { return buf; } @Override protected void buf(ByteBuffer buf) { this.buf = buf; } @Override protected IoBuffer duplicate0() { return new SimpleBuffer(this, this.buf.duplicate()); } @Override protected IoBuffer slice0() { return new SimpleBuffer(this, this.buf.slice()); } @Override protected IoBuffer asReadOnlyBuffer0() { return new SimpleBuffer(this, this.buf.asReadOnlyBuffer()); } @Override public byte[] array() { return buf.array(); } @Override public int arrayOffset() { return buf.arrayOffset(); } @Override public boolean hasArray() { return buf.hasArray(); } @Override public void free() { // Do nothing } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/buffer/CachedBufferAllocator.java0000644000175000017500000002327112032276031032255 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.HashMap; import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; /** * An {@link IoBufferAllocator} that caches the buffers which are likely to * be reused during auto-expansion of the buffers. *

* In {@link SimpleBufferAllocator}, the underlying {@link ByteBuffer} of * the {@link IoBuffer} is reallocated on its capacity change, which means * the newly allocated bigger {@link ByteBuffer} replaces the old small * {@link ByteBuffer}. Consequently, the old {@link ByteBuffer} is marked * for garbage collection. *

* It's not a problem in most cases as long as the capacity change doesn't * happen frequently. However, once it happens too often, it burdens the * VM and the cost of filling the newly allocated {@link ByteBuffer} with * {@code NUL} surpass the cost of accessing the cache. In 2 dual-core * Opteron Italy 270 processors, {@link CachedBufferAllocator} outperformed * {@link SimpleBufferAllocator} in the following situation: *

    *
  • when a 32 bytes buffer is expanded 4 or more times,
  • *
  • when a 64 bytes buffer is expanded 4 or more times,
  • *
  • when a 128 bytes buffer is expanded 2 or more times,
  • *
  • and when a 256 bytes or bigger buffer is expanded 1 or more times.
  • *
* Please note the observation above is subject to change in a different * environment. *

* {@link CachedBufferAllocator} uses {@link ThreadLocal} to store the cached * buffer, allocates buffers whose capacity is power of 2 only and provides * performance advantage if {@link IoBuffer#free()} is called properly. * * @author Apache MINA Project */ public class CachedBufferAllocator implements IoBufferAllocator { private static final int DEFAULT_MAX_POOL_SIZE = 8; private static final int DEFAULT_MAX_CACHED_BUFFER_SIZE = 1 << 18; // 256KB private final int maxPoolSize; private final int maxCachedBufferSize; private final ThreadLocal>> heapBuffers; private final ThreadLocal>> directBuffers; /** * Creates a new instance with the default parameters * ({@literal #DEFAULT_MAX_POOL_SIZE} and {@literal #DEFAULT_MAX_CACHED_BUFFER_SIZE}). */ public CachedBufferAllocator() { this(DEFAULT_MAX_POOL_SIZE, DEFAULT_MAX_CACHED_BUFFER_SIZE); } /** * Creates a new instance. * * @param maxPoolSize the maximum number of buffers with the same capacity per thread. * 0 disables this limitation. * @param maxCachedBufferSize the maximum capacity of a cached buffer. * A buffer whose capacity is bigger than this value is * not pooled. 0 disables this limitation. */ public CachedBufferAllocator(int maxPoolSize, int maxCachedBufferSize) { if (maxPoolSize < 0) { throw new IllegalArgumentException("maxPoolSize: " + maxPoolSize); } if (maxCachedBufferSize < 0) { throw new IllegalArgumentException("maxCachedBufferSize: " + maxCachedBufferSize); } this.maxPoolSize = maxPoolSize; this.maxCachedBufferSize = maxCachedBufferSize; this.heapBuffers = new ThreadLocal>>() { @Override protected Map> initialValue() { return newPoolMap(); } }; this.directBuffers = new ThreadLocal>>() { @Override protected Map> initialValue() { return newPoolMap(); } }; } /** * Returns the maximum number of buffers with the same capacity per thread. * 0 means 'no limitation'. */ public int getMaxPoolSize() { return maxPoolSize; } /** * Returns the maximum capacity of a cached buffer. A buffer whose * capacity is bigger than this value is not pooled. 0 means * 'no limitation'. */ public int getMaxCachedBufferSize() { return maxCachedBufferSize; } Map> newPoolMap() { Map> poolMap = new HashMap>(); int poolSize = maxPoolSize == 0 ? DEFAULT_MAX_POOL_SIZE : maxPoolSize; for (int i = 0; i < 31; i++) { poolMap.put(1 << i, new ConcurrentLinkedQueue()); } poolMap.put(0, new ConcurrentLinkedQueue()); poolMap.put(Integer.MAX_VALUE, new ConcurrentLinkedQueue()); return poolMap; } public IoBuffer allocate(int requestedCapacity, boolean direct) { int actualCapacity = IoBuffer.normalizeCapacity(requestedCapacity); IoBuffer buf; if ((maxCachedBufferSize != 0) && (actualCapacity > maxCachedBufferSize)) { if (direct) { buf = wrap(ByteBuffer.allocateDirect(actualCapacity)); } else { buf = wrap(ByteBuffer.allocate(actualCapacity)); } } else { Queue pool; if (direct) { pool = directBuffers.get().get(actualCapacity); } else { pool = heapBuffers.get().get(actualCapacity); } // Recycle if possible. buf = pool.poll(); if (buf != null) { buf.clear(); buf.setAutoExpand(false); buf.order(ByteOrder.BIG_ENDIAN); } else { if (direct) { buf = wrap(ByteBuffer.allocateDirect(actualCapacity)); } else { buf = wrap(ByteBuffer.allocate(actualCapacity)); } } } buf.limit(requestedCapacity); return buf; } public ByteBuffer allocateNioBuffer(int capacity, boolean direct) { return allocate(capacity, direct).buf(); } public IoBuffer wrap(ByteBuffer nioBuffer) { return new CachedBuffer(nioBuffer); } public void dispose() { // Do nothing } private class CachedBuffer extends AbstractIoBuffer { private final Thread ownerThread; private ByteBuffer buf; protected CachedBuffer(ByteBuffer buf) { super(CachedBufferAllocator.this, buf.capacity()); this.ownerThread = Thread.currentThread(); this.buf = buf; buf.order(ByteOrder.BIG_ENDIAN); } protected CachedBuffer(CachedBuffer parent, ByteBuffer buf) { super(parent); this.ownerThread = Thread.currentThread(); this.buf = buf; } @Override public ByteBuffer buf() { if (buf == null) { throw new IllegalStateException("Buffer has been freed already."); } return buf; } @Override protected void buf(ByteBuffer buf) { ByteBuffer oldBuf = this.buf; this.buf = buf; free(oldBuf); } @Override protected IoBuffer duplicate0() { return new CachedBuffer(this, buf().duplicate()); } @Override protected IoBuffer slice0() { return new CachedBuffer(this, buf().slice()); } @Override protected IoBuffer asReadOnlyBuffer0() { return new CachedBuffer(this, buf().asReadOnlyBuffer()); } @Override public byte[] array() { return buf().array(); } @Override public int arrayOffset() { return buf().arrayOffset(); } @Override public boolean hasArray() { return buf().hasArray(); } @Override public void free() { free(buf); buf = null; } private void free(ByteBuffer oldBuf) { if ((oldBuf == null) || ((maxCachedBufferSize != 0) && (oldBuf.capacity() > maxCachedBufferSize)) || oldBuf.isReadOnly() || isDerived() || (Thread.currentThread() != ownerThread)) { return; } // Add to the cache. Queue pool; if (oldBuf.isDirect()) { pool = directBuffers.get().get(oldBuf.capacity()); } else { pool = heapBuffers.get().get(oldBuf.capacity()); } if (pool == null) { return; } // Restrict the size of the pool to prevent OOM. if ((maxPoolSize == 0) || (pool.size() < maxPoolSize)) { pool.offer(new CachedBuffer(oldBuf)); } } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/buffer/AbstractIoBuffer.java0000644000175000017500000020234412032276031031300 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.buffer; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import java.io.OutputStream; import java.io.Serializable; import java.io.StreamCorruptedException; import java.nio.BufferOverflowException; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.CharBuffer; import java.nio.DoubleBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; import java.nio.ShortBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; import java.util.EnumSet; import java.util.Set; /** * A base implementation of {@link IoBuffer}. This implementation * assumes that {@link IoBuffer#buf()} always returns a correct NIO * {@link ByteBuffer} instance. Most implementations could * extend this class and implement their own buffer management mechanism. * * @author Apache MINA Project * @see IoBufferAllocator */ public abstract class AbstractIoBuffer extends IoBuffer { /** Tells if a buffer has been created from an existing buffer */ private final boolean derived; /** A flag set to true if the buffer can extend automatically */ private boolean autoExpand; /** A flag set to true if the buffer can shrink automatically */ private boolean autoShrink; /** Tells if a buffer can be expanded */ private boolean recapacityAllowed = true; /** The minimum number of bytes the IoBuffer can hold */ private int minimumCapacity; /** A mask for a byte */ private static final long BYTE_MASK = 0xFFL; /** A mask for a short */ private static final long SHORT_MASK = 0xFFFFL; /** A mask for an int */ private static final long INT_MASK = 0xFFFFFFFFL; /** * We don't have any access to Buffer.markValue(), so we need to track it down, * which will cause small extra overhead. */ private int mark = -1; /** * Creates a new parent buffer. * * @param allocator The allocator to use to create new buffers * @param initialCapacity The initial buffer capacity when created */ protected AbstractIoBuffer(IoBufferAllocator allocator, int initialCapacity) { setAllocator(allocator); this.recapacityAllowed = true; this.derived = false; this.minimumCapacity = initialCapacity; } /** * Creates a new derived buffer. A derived buffer uses an existing * buffer properties - the allocator and capacity -. * * @param parent The buffer we get the properties from */ protected AbstractIoBuffer(AbstractIoBuffer parent) { setAllocator(parent.getAllocator()); this.recapacityAllowed = false; this.derived = true; this.minimumCapacity = parent.minimumCapacity; } /** * {@inheritDoc} */ @Override public final boolean isDirect() { return buf().isDirect(); } /** * {@inheritDoc} */ @Override public final boolean isReadOnly() { return buf().isReadOnly(); } /** * Sets the underlying NIO buffer instance. * * @param newBuf The buffer to store within this IoBuffer */ protected abstract void buf(ByteBuffer newBuf); /** * {@inheritDoc} */ @Override public final int minimumCapacity() { return minimumCapacity; } /** * {@inheritDoc} */ @Override public final IoBuffer minimumCapacity(int minimumCapacity) { if (minimumCapacity < 0) { throw new IllegalArgumentException("minimumCapacity: " + minimumCapacity); } this.minimumCapacity = minimumCapacity; return this; } /** * {@inheritDoc} */ @Override public final int capacity() { return buf().capacity(); } /** * {@inheritDoc} */ @Override public final IoBuffer capacity(int newCapacity) { if (!recapacityAllowed) { throw new IllegalStateException("Derived buffers and their parent can't be expanded."); } // Allocate a new buffer and transfer all settings to it. if (newCapacity > capacity()) { // Expand: //// Save the state. int pos = position(); int limit = limit(); ByteOrder bo = order(); //// Reallocate. ByteBuffer oldBuf = buf(); ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, isDirect()); oldBuf.clear(); newBuf.put(oldBuf); buf(newBuf); //// Restore the state. buf().limit(limit); if (mark >= 0) { buf().position(mark); buf().mark(); } buf().position(pos); buf().order(bo); } return this; } /** * {@inheritDoc} */ @Override public final boolean isAutoExpand() { return autoExpand && recapacityAllowed; } /** * {@inheritDoc} */ @Override public final boolean isAutoShrink() { return autoShrink && recapacityAllowed; } /** * {@inheritDoc} */ @Override public final boolean isDerived() { return derived; } /** * {@inheritDoc} */ @Override public final IoBuffer setAutoExpand(boolean autoExpand) { if (!recapacityAllowed) { throw new IllegalStateException("Derived buffers and their parent can't be expanded."); } this.autoExpand = autoExpand; return this; } /** * {@inheritDoc} */ @Override public final IoBuffer setAutoShrink(boolean autoShrink) { if (!recapacityAllowed) { throw new IllegalStateException("Derived buffers and their parent can't be shrinked."); } this.autoShrink = autoShrink; return this; } /** * {@inheritDoc} */ @Override public final IoBuffer expand(int expectedRemaining) { return expand(position(), expectedRemaining, false); } private IoBuffer expand(int expectedRemaining, boolean autoExpand) { return expand(position(), expectedRemaining, autoExpand); } /** * {@inheritDoc} */ @Override public final IoBuffer expand(int pos, int expectedRemaining) { return expand(pos, expectedRemaining, false); } private IoBuffer expand(int pos, int expectedRemaining, boolean autoExpand) { if (!recapacityAllowed) { throw new IllegalStateException("Derived buffers and their parent can't be expanded."); } int end = pos + expectedRemaining; int newCapacity; if (autoExpand) { newCapacity = IoBuffer.normalizeCapacity(end); } else { newCapacity = end; } if (newCapacity > capacity()) { // The buffer needs expansion. capacity(newCapacity); } if (end > limit()) { // We call limit() directly to prevent StackOverflowError buf().limit(end); } return this; } /** * {@inheritDoc} */ @Override public final IoBuffer shrink() { if (!recapacityAllowed) { throw new IllegalStateException("Derived buffers and their parent can't be expanded."); } int position = position(); int capacity = capacity(); int limit = limit(); if (capacity == limit) { return this; } int newCapacity = capacity; int minCapacity = Math.max(minimumCapacity, limit); for (;;) { if (newCapacity >>> 1 < minCapacity) { break; } newCapacity >>>= 1; } newCapacity = Math.max(minCapacity, newCapacity); if (newCapacity == capacity) { return this; } // Shrink and compact: //// Save the state. ByteOrder bo = order(); //// Reallocate. ByteBuffer oldBuf = buf(); ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, isDirect()); oldBuf.position(0); oldBuf.limit(limit); newBuf.put(oldBuf); buf(newBuf); //// Restore the state. buf().position(position); buf().limit(limit); buf().order(bo); mark = -1; return this; } /** * {@inheritDoc} */ @Override public final int position() { return buf().position(); } /** * {@inheritDoc} */ @Override public final IoBuffer position(int newPosition) { autoExpand(newPosition, 0); buf().position(newPosition); if (mark > newPosition) { mark = -1; } return this; } /** * {@inheritDoc} */ @Override public final int limit() { return buf().limit(); } /** * {@inheritDoc} */ @Override public final IoBuffer limit(int newLimit) { autoExpand(newLimit, 0); buf().limit(newLimit); if (mark > newLimit) { mark = -1; } return this; } /** * {@inheritDoc} */ @Override public final IoBuffer mark() { ByteBuffer byteBuffer = buf(); byteBuffer.mark(); mark = byteBuffer.position(); return this; } /** * {@inheritDoc} */ @Override public final int markValue() { return mark; } /** * {@inheritDoc} */ @Override public final IoBuffer reset() { buf().reset(); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer clear() { buf().clear(); mark = -1; return this; } /** * {@inheritDoc} */ @Override public final IoBuffer sweep() { clear(); return fillAndReset(remaining()); } /** * {@inheritDoc} */ @Override public final IoBuffer sweep(byte value) { clear(); return fillAndReset(value, remaining()); } /** * {@inheritDoc} */ @Override public final IoBuffer flip() { buf().flip(); mark = -1; return this; } /** * {@inheritDoc} */ @Override public final IoBuffer rewind() { buf().rewind(); mark = -1; return this; } /** * {@inheritDoc} */ @Override public final int remaining() { ByteBuffer byteBuffer = buf(); return byteBuffer.limit() - byteBuffer.position(); } /** * {@inheritDoc} */ @Override public final boolean hasRemaining() { ByteBuffer byteBuffer = buf(); return byteBuffer.limit() > byteBuffer.position(); } /** * {@inheritDoc} */ @Override public final byte get() { return buf().get(); } /** * {@inheritDoc} */ @Override public final short getUnsigned() { return (short) (get() & 0xff); } /** * {@inheritDoc} */ @Override public final IoBuffer put(byte b) { autoExpand(1); buf().put(b); return this; } /** * {@inheritDoc} */ public IoBuffer putUnsigned(byte value) { autoExpand(1); buf().put((byte) (value & 0xff)); return this; } /** * {@inheritDoc} */ public IoBuffer putUnsigned(int index, byte value) { autoExpand(index, 1); buf().put(index, (byte) (value & 0xff)); return this; } /** * {@inheritDoc} */ public IoBuffer putUnsigned(short value) { autoExpand(1); buf().put((byte) (value & 0x00ff)); return this; } /** * {@inheritDoc} */ public IoBuffer putUnsigned(int index, short value) { autoExpand(index, 1); buf().put(index, (byte) (value & 0x00ff)); return this; } /** * {@inheritDoc} */ public IoBuffer putUnsigned(int value) { autoExpand(1); buf().put((byte) (value & 0x000000ff)); return this; } /** * {@inheritDoc} */ public IoBuffer putUnsigned(int index, int value) { autoExpand(index, 1); buf().put(index, (byte) (value & 0x000000ff)); return this; } /** * {@inheritDoc} */ public IoBuffer putUnsigned(long value) { autoExpand(1); buf().put((byte) (value & 0x00000000000000ffL)); return this; } /** * {@inheritDoc} */ public IoBuffer putUnsigned(int index, long value) { autoExpand(index, 1); buf().put(index, (byte) (value & 0x00000000000000ffL)); return this; } /** * {@inheritDoc} */ @Override public final byte get(int index) { return buf().get(index); } /** * {@inheritDoc} */ @Override public final short getUnsigned(int index) { return (short) (get(index) & 0xff); } /** * {@inheritDoc} */ @Override public final IoBuffer put(int index, byte b) { autoExpand(index, 1); buf().put(index, b); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer get(byte[] dst, int offset, int length) { buf().get(dst, offset, length); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer put(ByteBuffer src) { autoExpand(src.remaining()); buf().put(src); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer put(byte[] src, int offset, int length) { autoExpand(length); buf().put(src, offset, length); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer compact() { int remaining = remaining(); int capacity = capacity(); if (capacity == 0) { return this; } if (isAutoShrink() && remaining <= capacity >>> 2 && capacity > minimumCapacity) { int newCapacity = capacity; int minCapacity = Math.max(minimumCapacity, remaining << 1); for (;;) { if (newCapacity >>> 1 < minCapacity) { break; } newCapacity >>>= 1; } newCapacity = Math.max(minCapacity, newCapacity); if (newCapacity == capacity) { return this; } // Shrink and compact: //// Save the state. ByteOrder bo = order(); //// Sanity check. if (remaining > newCapacity) { throw new IllegalStateException("The amount of the remaining bytes is greater than " + "the new capacity."); } //// Reallocate. ByteBuffer oldBuf = buf(); ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, isDirect()); newBuf.put(oldBuf); buf(newBuf); //// Restore the state. buf().order(bo); } else { buf().compact(); } mark = -1; return this; } /** * {@inheritDoc} */ @Override public final ByteOrder order() { return buf().order(); } /** * {@inheritDoc} */ @Override public final IoBuffer order(ByteOrder bo) { buf().order(bo); return this; } /** * {@inheritDoc} */ @Override public final char getChar() { return buf().getChar(); } /** * {@inheritDoc} */ @Override public final IoBuffer putChar(char value) { autoExpand(2); buf().putChar(value); return this; } /** * {@inheritDoc} */ @Override public final char getChar(int index) { return buf().getChar(index); } /** * {@inheritDoc} */ @Override public final IoBuffer putChar(int index, char value) { autoExpand(index, 2); buf().putChar(index, value); return this; } /** * {@inheritDoc} */ @Override public final CharBuffer asCharBuffer() { return buf().asCharBuffer(); } /** * {@inheritDoc} */ @Override public final short getShort() { return buf().getShort(); } /** * {@inheritDoc} */ @Override public final IoBuffer putShort(short value) { autoExpand(2); buf().putShort(value); return this; } /** * {@inheritDoc} */ @Override public final short getShort(int index) { return buf().getShort(index); } /** * {@inheritDoc} */ @Override public final IoBuffer putShort(int index, short value) { autoExpand(index, 2); buf().putShort(index, value); return this; } /** * {@inheritDoc} */ @Override public final ShortBuffer asShortBuffer() { return buf().asShortBuffer(); } /** * {@inheritDoc} */ @Override public final int getInt() { return buf().getInt(); } /** * {@inheritDoc} */ @Override public final IoBuffer putInt(int value) { autoExpand(4); buf().putInt(value); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer putUnsignedInt(byte value) { autoExpand(4); buf().putInt((value & 0x00ff)); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer putUnsignedInt(int index, byte value) { autoExpand(index, 4); buf().putInt(index, (value & 0x00ff)); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer putUnsignedInt(short value) { autoExpand(4); buf().putInt((value & 0x0000ffff)); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer putUnsignedInt(int index, short value) { autoExpand(index, 4); buf().putInt(index, (value & 0x0000ffff)); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer putUnsignedInt(int value) { autoExpand(4); buf().putInt(value); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer putUnsignedInt(int index, int value) { autoExpand(index, 4); buf().putInt(index, value); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer putUnsignedInt(long value) { autoExpand(4); buf().putInt((int) (value & 0x00000000ffffffff)); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer putUnsignedInt(int index, long value) { autoExpand(index, 4); buf().putInt(index, (int) (value & 0x00000000ffffffffL)); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer putUnsignedShort(byte value) { autoExpand(2); buf().putShort((short) (value & 0x00ff)); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer putUnsignedShort(int index, byte value) { autoExpand(index, 2); buf().putShort(index, (short) (value & 0x00ff)); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer putUnsignedShort(short value) { autoExpand(2); buf().putShort(value); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer putUnsignedShort(int index, short value) { autoExpand(index, 2); buf().putShort(index, value); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer putUnsignedShort(int value) { autoExpand(2); buf().putShort((short) value); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer putUnsignedShort(int index, int value) { autoExpand(index, 2); buf().putShort(index, (short) value); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer putUnsignedShort(long value) { autoExpand(2); buf().putShort((short) (value)); return this; } /** * {@inheritDoc} */ @Override public final IoBuffer putUnsignedShort(int index, long value) { autoExpand(index, 2); buf().putShort(index, (short) (value)); return this; } /** * {@inheritDoc} */ @Override public final int getInt(int index) { return buf().getInt(index); } /** * {@inheritDoc} */ @Override public final IoBuffer putInt(int index, int value) { autoExpand(index, 4); buf().putInt(index, value); return this; } /** * {@inheritDoc} */ @Override public final IntBuffer asIntBuffer() { return buf().asIntBuffer(); } /** * {@inheritDoc} */ @Override public final long getLong() { return buf().getLong(); } /** * {@inheritDoc} */ @Override public final IoBuffer putLong(long value) { autoExpand(8); buf().putLong(value); return this; } /** * {@inheritDoc} */ @Override public final long getLong(int index) { return buf().getLong(index); } /** * {@inheritDoc} */ @Override public final IoBuffer putLong(int index, long value) { autoExpand(index, 8); buf().putLong(index, value); return this; } /** * {@inheritDoc} */ @Override public final LongBuffer asLongBuffer() { return buf().asLongBuffer(); } /** * {@inheritDoc} */ @Override public final float getFloat() { return buf().getFloat(); } /** * {@inheritDoc} */ @Override public final IoBuffer putFloat(float value) { autoExpand(4); buf().putFloat(value); return this; } /** * {@inheritDoc} */ @Override public final float getFloat(int index) { return buf().getFloat(index); } /** * {@inheritDoc} */ @Override public final IoBuffer putFloat(int index, float value) { autoExpand(index, 4); buf().putFloat(index, value); return this; } /** * {@inheritDoc} */ @Override public final FloatBuffer asFloatBuffer() { return buf().asFloatBuffer(); } /** * {@inheritDoc} */ @Override public final double getDouble() { return buf().getDouble(); } /** * {@inheritDoc} */ @Override public final IoBuffer putDouble(double value) { autoExpand(8); buf().putDouble(value); return this; } /** * {@inheritDoc} */ @Override public final double getDouble(int index) { return buf().getDouble(index); } /** * {@inheritDoc} */ @Override public final IoBuffer putDouble(int index, double value) { autoExpand(index, 8); buf().putDouble(index, value); return this; } /** * {@inheritDoc} */ @Override public final DoubleBuffer asDoubleBuffer() { return buf().asDoubleBuffer(); } /** * {@inheritDoc} */ @Override public final IoBuffer asReadOnlyBuffer() { recapacityAllowed = false; return asReadOnlyBuffer0(); } /** * Implement this method to return the unexpandable read only version of * this buffer. */ protected abstract IoBuffer asReadOnlyBuffer0(); /** * {@inheritDoc} */ @Override public final IoBuffer duplicate() { recapacityAllowed = false; return duplicate0(); } /** * Implement this method to return the unexpandable duplicate of this * buffer. */ protected abstract IoBuffer duplicate0(); /** * {@inheritDoc} */ @Override public final IoBuffer slice() { recapacityAllowed = false; return slice0(); } /** * {@inheritDoc} */ @Override public final IoBuffer getSlice(int index, int length) { if (length < 0) { throw new IllegalArgumentException("length: " + length); } int pos = position(); int limit = limit(); if (index > limit) { throw new IllegalArgumentException("index: " + index); } int endIndex = index + length; if (endIndex > limit) { throw new IndexOutOfBoundsException("index + length (" + endIndex + ") is greater " + "than limit (" + limit + ")."); } clear(); position(index); limit(endIndex); IoBuffer slice = slice(); position(pos); limit(limit); return slice; } /** * {@inheritDoc} */ @Override public final IoBuffer getSlice(int length) { if (length < 0) { throw new IllegalArgumentException("length: " + length); } int pos = position(); int limit = limit(); int nextPos = pos + length; if (limit < nextPos) { throw new IndexOutOfBoundsException("position + length (" + nextPos + ") is greater " + "than limit (" + limit + ")."); } limit(pos + length); IoBuffer slice = slice(); position(nextPos); limit(limit); return slice; } /** * Implement this method to return the unexpandable slice of this * buffer. */ protected abstract IoBuffer slice0(); /** * {@inheritDoc} */ @Override public int hashCode() { int h = 1; int p = position(); for (int i = limit() - 1; i >= p; i--) { h = 31 * h + get(i); } return h; } /** * {@inheritDoc} */ @Override public boolean equals(Object o) { if (!(o instanceof IoBuffer)) { return false; } IoBuffer that = (IoBuffer) o; if (this.remaining() != that.remaining()) { return false; } int p = this.position(); for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) { byte v1 = this.get(i); byte v2 = that.get(j); if (v1 != v2) { return false; } } return true; } /** * {@inheritDoc} */ public int compareTo(IoBuffer that) { int n = this.position() + Math.min(this.remaining(), that.remaining()); for (int i = this.position(), j = that.position(); i < n; i++, j++) { byte v1 = this.get(i); byte v2 = that.get(j); if (v1 == v2) { continue; } if (v1 < v2) { return -1; } return +1; } return this.remaining() - that.remaining(); } /** * {@inheritDoc} */ @Override public String toString() { StringBuilder buf = new StringBuilder(); if (isDirect()) { buf.append("DirectBuffer"); } else { buf.append("HeapBuffer"); } buf.append("[pos="); buf.append(position()); buf.append(" lim="); buf.append(limit()); buf.append(" cap="); buf.append(capacity()); buf.append(": "); buf.append(getHexDump(16)); buf.append(']'); return buf.toString(); } /** * {@inheritDoc} */ @Override public IoBuffer get(byte[] dst) { return get(dst, 0, dst.length); } /** * {@inheritDoc} */ @Override public IoBuffer put(IoBuffer src) { return put(src.buf()); } /** * {@inheritDoc} */ @Override public IoBuffer put(byte[] src) { return put(src, 0, src.length); } /** * {@inheritDoc} */ @Override public int getUnsignedShort() { return getShort() & 0xffff; } /** * {@inheritDoc} */ @Override public int getUnsignedShort(int index) { return getShort(index) & 0xffff; } /** * {@inheritDoc} */ @Override public long getUnsignedInt() { return getInt() & 0xffffffffL; } /** * {@inheritDoc} */ @Override public int getMediumInt() { byte b1 = get(); byte b2 = get(); byte b3 = get(); if (ByteOrder.BIG_ENDIAN.equals(order())) { return getMediumInt(b1, b2, b3); } return getMediumInt(b3, b2, b1); } /** * {@inheritDoc} */ @Override public int getUnsignedMediumInt() { int b1 = getUnsigned(); int b2 = getUnsigned(); int b3 = getUnsigned(); if (ByteOrder.BIG_ENDIAN.equals(order())) { return b1 << 16 | b2 << 8 | b3; } return b3 << 16 | b2 << 8 | b1; } /** * {@inheritDoc} */ @Override public int getMediumInt(int index) { byte b1 = get(index); byte b2 = get(index + 1); byte b3 = get(index + 2); if (ByteOrder.BIG_ENDIAN.equals(order())) { return getMediumInt(b1, b2, b3); } return getMediumInt(b3, b2, b1); } /** * {@inheritDoc} */ @Override public int getUnsignedMediumInt(int index) { int b1 = getUnsigned(index); int b2 = getUnsigned(index + 1); int b3 = getUnsigned(index + 2); if (ByteOrder.BIG_ENDIAN.equals(order())) { return b1 << 16 | b2 << 8 | b3; } return b3 << 16 | b2 << 8 | b1; } /** * {@inheritDoc} */ private int getMediumInt(byte b1, byte b2, byte b3) { int ret = b1 << 16 & 0xff0000 | b2 << 8 & 0xff00 | b3 & 0xff; // Check to see if the medium int is negative (high bit in b1 set) if ((b1 & 0x80) == 0x80) { // Make the the whole int negative ret |= 0xff000000; } return ret; } /** * {@inheritDoc} */ @Override public IoBuffer putMediumInt(int value) { byte b1 = (byte) (value >> 16); byte b2 = (byte) (value >> 8); byte b3 = (byte) value; if (ByteOrder.BIG_ENDIAN.equals(order())) { put(b1).put(b2).put(b3); } else { put(b3).put(b2).put(b1); } return this; } /** * {@inheritDoc} */ @Override public IoBuffer putMediumInt(int index, int value) { byte b1 = (byte) (value >> 16); byte b2 = (byte) (value >> 8); byte b3 = (byte) value; if (ByteOrder.BIG_ENDIAN.equals(order())) { put(index, b1).put(index + 1, b2).put(index + 2, b3); } else { put(index, b3).put(index + 1, b2).put(index + 2, b1); } return this; } /** * {@inheritDoc} */ @Override public long getUnsignedInt(int index) { return getInt(index) & 0xffffffffL; } /** * {@inheritDoc} */ @Override public InputStream asInputStream() { return new InputStream() { @Override public int available() { return AbstractIoBuffer.this.remaining(); } @Override public synchronized void mark(int readlimit) { AbstractIoBuffer.this.mark(); } @Override public boolean markSupported() { return true; } @Override public int read() { if (AbstractIoBuffer.this.hasRemaining()) { return AbstractIoBuffer.this.get() & 0xff; } return -1; } @Override public int read(byte[] b, int off, int len) { int remaining = AbstractIoBuffer.this.remaining(); if (remaining > 0) { int readBytes = Math.min(remaining, len); AbstractIoBuffer.this.get(b, off, readBytes); return readBytes; } return -1; } @Override public synchronized void reset() { AbstractIoBuffer.this.reset(); } @Override public long skip(long n) { int bytes; if (n > Integer.MAX_VALUE) { bytes = AbstractIoBuffer.this.remaining(); } else { bytes = Math.min(AbstractIoBuffer.this.remaining(), (int) n); } AbstractIoBuffer.this.skip(bytes); return bytes; } }; } /** * {@inheritDoc} */ @Override public OutputStream asOutputStream() { return new OutputStream() { @Override public void write(byte[] b, int off, int len) { AbstractIoBuffer.this.put(b, off, len); } @Override public void write(int b) { AbstractIoBuffer.this.put((byte) b); } }; } /** * {@inheritDoc} */ @Override public String getHexDump() { return this.getHexDump(Integer.MAX_VALUE); } /** * {@inheritDoc} */ @Override public String getHexDump(int lengthLimit) { return IoBufferHexDumper.getHexdump(this, lengthLimit); } /** * {@inheritDoc} */ @Override public String getString(CharsetDecoder decoder) throws CharacterCodingException { if (!hasRemaining()) { return ""; } boolean utf16 = decoder.charset().name().startsWith("UTF-16"); int oldPos = position(); int oldLimit = limit(); int end = -1; int newPos; if (!utf16) { end = indexOf((byte) 0x00); if (end < 0) { newPos = end = oldLimit; } else { newPos = end + 1; } } else { int i = oldPos; for (;;) { boolean wasZero = get(i) == 0; i++; if (i >= oldLimit) { break; } if (get(i) != 0) { i++; if (i >= oldLimit) { break; } continue; } if (wasZero) { end = i - 1; break; } } if (end < 0) { newPos = end = oldPos + (oldLimit - oldPos & 0xFFFFFFFE); } else { if (end + 2 <= oldLimit) { newPos = end + 2; } else { newPos = end; } } } if (oldPos == end) { position(newPos); return ""; } limit(end); decoder.reset(); int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1; CharBuffer out = CharBuffer.allocate(expectedLength); for (;;) { CoderResult cr; if (hasRemaining()) { cr = decoder.decode(buf(), out, true); } else { cr = decoder.flush(out); } if (cr.isUnderflow()) { break; } if (cr.isOverflow()) { CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength); out.flip(); o.put(out); out = o; continue; } if (cr.isError()) { // Revert the buffer back to the previous state. limit(oldLimit); position(oldPos); cr.throwException(); } } limit(oldLimit); position(newPos); return out.flip().toString(); } /** * {@inheritDoc} */ @Override public String getString(int fieldSize, CharsetDecoder decoder) throws CharacterCodingException { checkFieldSize(fieldSize); if (fieldSize == 0) { return ""; } if (!hasRemaining()) { return ""; } boolean utf16 = decoder.charset().name().startsWith("UTF-16"); if (utf16 && (fieldSize & 1) != 0) { throw new IllegalArgumentException("fieldSize is not even."); } int oldPos = position(); int oldLimit = limit(); int end = oldPos + fieldSize; if (oldLimit < end) { throw new BufferUnderflowException(); } int i; if (!utf16) { for (i = oldPos; i < end; i++) { if (get(i) == 0) { break; } } if (i == end) { limit(end); } else { limit(i); } } else { for (i = oldPos; i < end; i += 2) { if (get(i) == 0 && get(i + 1) == 0) { break; } } if (i == end) { limit(end); } else { limit(i); } } if (!hasRemaining()) { limit(oldLimit); position(end); return ""; } decoder.reset(); int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1; CharBuffer out = CharBuffer.allocate(expectedLength); for (;;) { CoderResult cr; if (hasRemaining()) { cr = decoder.decode(buf(), out, true); } else { cr = decoder.flush(out); } if (cr.isUnderflow()) { break; } if (cr.isOverflow()) { CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength); out.flip(); o.put(out); out = o; continue; } if (cr.isError()) { // Revert the buffer back to the previous state. limit(oldLimit); position(oldPos); cr.throwException(); } } limit(oldLimit); position(end); return out.flip().toString(); } /** * {@inheritDoc} */ @Override public IoBuffer putString(CharSequence val, CharsetEncoder encoder) throws CharacterCodingException { if (val.length() == 0) { return this; } CharBuffer in = CharBuffer.wrap(val); encoder.reset(); int expandedState = 0; for (;;) { CoderResult cr; if (in.hasRemaining()) { cr = encoder.encode(in, buf(), true); } else { cr = encoder.flush(buf()); } if (cr.isUnderflow()) { break; } if (cr.isOverflow()) { if (isAutoExpand()) { switch (expandedState) { case 0: autoExpand((int) Math.ceil(in.remaining() * encoder.averageBytesPerChar())); expandedState++; break; case 1: autoExpand((int) Math.ceil(in.remaining() * encoder.maxBytesPerChar())); expandedState++; break; default: throw new RuntimeException("Expanded by " + (int) Math.ceil(in.remaining() * encoder.maxBytesPerChar()) + " but that wasn't enough for '" + val + "'"); } continue; } } else { expandedState = 0; } cr.throwException(); } return this; } /** * {@inheritDoc} */ @Override public IoBuffer putString(CharSequence val, int fieldSize, CharsetEncoder encoder) throws CharacterCodingException { checkFieldSize(fieldSize); if (fieldSize == 0) { return this; } autoExpand(fieldSize); boolean utf16 = encoder.charset().name().startsWith("UTF-16"); if (utf16 && (fieldSize & 1) != 0) { throw new IllegalArgumentException("fieldSize is not even."); } int oldLimit = limit(); int end = position() + fieldSize; if (oldLimit < end) { throw new BufferOverflowException(); } if (val.length() == 0) { if (!utf16) { put((byte) 0x00); } else { put((byte) 0x00); put((byte) 0x00); } position(end); return this; } CharBuffer in = CharBuffer.wrap(val); limit(end); encoder.reset(); for (;;) { CoderResult cr; if (in.hasRemaining()) { cr = encoder.encode(in, buf(), true); } else { cr = encoder.flush(buf()); } if (cr.isUnderflow() || cr.isOverflow()) { break; } cr.throwException(); } limit(oldLimit); if (position() < end) { if (!utf16) { put((byte) 0x00); } else { put((byte) 0x00); put((byte) 0x00); } } position(end); return this; } /** * {@inheritDoc} */ @Override public String getPrefixedString(CharsetDecoder decoder) throws CharacterCodingException { return getPrefixedString(2, decoder); } /** * Reads a string which has a length field before the actual * encoded string, using the specified decoder and returns it. * * @param prefixLength the length of the length field (1, 2, or 4) * @param decoder the decoder to use for decoding the string * @return the prefixed string * @throws CharacterCodingException when decoding fails * @throws BufferUnderflowException when there is not enough data available */ @Override public String getPrefixedString(int prefixLength, CharsetDecoder decoder) throws CharacterCodingException { if (!prefixedDataAvailable(prefixLength)) { throw new BufferUnderflowException(); } int fieldSize = 0; switch (prefixLength) { case 1: fieldSize = getUnsigned(); break; case 2: fieldSize = getUnsignedShort(); break; case 4: fieldSize = getInt(); break; } if (fieldSize == 0) { return ""; } boolean utf16 = decoder.charset().name().startsWith("UTF-16"); if (utf16 && (fieldSize & 1) != 0) { throw new BufferDataException("fieldSize is not even for a UTF-16 string."); } int oldLimit = limit(); int end = position() + fieldSize; if (oldLimit < end) { throw new BufferUnderflowException(); } limit(end); decoder.reset(); int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1; CharBuffer out = CharBuffer.allocate(expectedLength); for (;;) { CoderResult cr; if (hasRemaining()) { cr = decoder.decode(buf(), out, true); } else { cr = decoder.flush(out); } if (cr.isUnderflow()) { break; } if (cr.isOverflow()) { CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength); out.flip(); o.put(out); out = o; continue; } cr.throwException(); } limit(oldLimit); position(end); return out.flip().toString(); } /** * {@inheritDoc} */ @Override public IoBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder) throws CharacterCodingException { return putPrefixedString(in, 2, 0, encoder); } /** * {@inheritDoc} */ @Override public IoBuffer putPrefixedString(CharSequence in, int prefixLength, CharsetEncoder encoder) throws CharacterCodingException { return putPrefixedString(in, prefixLength, 0, encoder); } /** * {@inheritDoc} */ @Override public IoBuffer putPrefixedString(CharSequence in, int prefixLength, int padding, CharsetEncoder encoder) throws CharacterCodingException { return putPrefixedString(in, prefixLength, padding, (byte) 0, encoder); } /** * {@inheritDoc} */ @Override public IoBuffer putPrefixedString(CharSequence val, int prefixLength, int padding, byte padValue, CharsetEncoder encoder) throws CharacterCodingException { int maxLength; switch (prefixLength) { case 1: maxLength = 255; break; case 2: maxLength = 65535; break; case 4: maxLength = Integer.MAX_VALUE; break; default: throw new IllegalArgumentException("prefixLength: " + prefixLength); } if (val.length() > maxLength) { throw new IllegalArgumentException("The specified string is too long."); } if (val.length() == 0) { switch (prefixLength) { case 1: put((byte) 0); break; case 2: putShort((short) 0); break; case 4: putInt(0); break; } return this; } int padMask; switch (padding) { case 0: case 1: padMask = 0; break; case 2: padMask = 1; break; case 4: padMask = 3; break; default: throw new IllegalArgumentException("padding: " + padding); } CharBuffer in = CharBuffer.wrap(val); skip(prefixLength); // make a room for the length field int oldPos = position(); encoder.reset(); int expandedState = 0; for (;;) { CoderResult cr; if (in.hasRemaining()) { cr = encoder.encode(in, buf(), true); } else { cr = encoder.flush(buf()); } if (position() - oldPos > maxLength) { throw new IllegalArgumentException("The specified string is too long."); } if (cr.isUnderflow()) { break; } if (cr.isOverflow()) { if (isAutoExpand()) { switch (expandedState) { case 0: autoExpand((int) Math.ceil(in.remaining() * encoder.averageBytesPerChar())); expandedState++; break; case 1: autoExpand((int) Math.ceil(in.remaining() * encoder.maxBytesPerChar())); expandedState++; break; default: throw new RuntimeException("Expanded by " + (int) Math.ceil(in.remaining() * encoder.maxBytesPerChar()) + " but that wasn't enough for '" + val + "'"); } continue; } } else { expandedState = 0; } cr.throwException(); } // Write the length field fill(padValue, padding - (position() - oldPos & padMask)); int length = position() - oldPos; switch (prefixLength) { case 1: put(oldPos - 1, (byte) length); break; case 2: putShort(oldPos - 2, (short) length); break; case 4: putInt(oldPos - 4, length); break; } return this; } /** * {@inheritDoc} */ @Override public Object getObject() throws ClassNotFoundException { return getObject(Thread.currentThread().getContextClassLoader()); } /** * {@inheritDoc} */ @Override public Object getObject(final ClassLoader classLoader) throws ClassNotFoundException { if (!prefixedDataAvailable(4)) { throw new BufferUnderflowException(); } int length = getInt(); if (length <= 4) { throw new BufferDataException("Object length should be greater than 4: " + length); } int oldLimit = limit(); limit(position() + length); try { ObjectInputStream in = new ObjectInputStream(asInputStream()) { @Override protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { int type = read(); if (type < 0) { throw new EOFException(); } switch (type) { case 0: // NON-Serializable class or Primitive types return super.readClassDescriptor(); case 1: // Serializable class String className = readUTF(); Class clazz = Class.forName(className, true, classLoader); return ObjectStreamClass.lookup(clazz); default: throw new StreamCorruptedException("Unexpected class descriptor type: " + type); } } @Override protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String name = desc.getName(); try { return Class.forName(name, false, classLoader); } catch (ClassNotFoundException ex) { return super.resolveClass(desc); } } }; return in.readObject(); } catch (IOException e) { throw new BufferDataException(e); } finally { limit(oldLimit); } } /** * {@inheritDoc} */ @Override public IoBuffer putObject(Object o) { int oldPos = position(); skip(4); // Make a room for the length field. try { ObjectOutputStream out = new ObjectOutputStream(asOutputStream()) { @Override protected void writeClassDescriptor(ObjectStreamClass desc) throws IOException { try { Class clz = Class.forName(desc.getName()); if (!Serializable.class.isAssignableFrom(clz)) { // NON-Serializable class write(0); super.writeClassDescriptor(desc); } else { // Serializable class write(1); writeUTF(desc.getName()); } } catch (ClassNotFoundException ex) { // Primitive types write(0); super.writeClassDescriptor(desc); } } }; out.writeObject(o); out.flush(); } catch (IOException e) { throw new BufferDataException(e); } // Fill the length field int newPos = position(); position(oldPos); putInt(newPos - oldPos - 4); position(newPos); return this; } /** * {@inheritDoc} */ @Override public boolean prefixedDataAvailable(int prefixLength) { return prefixedDataAvailable(prefixLength, Integer.MAX_VALUE); } /** * {@inheritDoc} */ @Override public boolean prefixedDataAvailable(int prefixLength, int maxDataLength) { if (remaining() < prefixLength) { return false; } int dataLength; switch (prefixLength) { case 1: dataLength = getUnsigned(position()); break; case 2: dataLength = getUnsignedShort(position()); break; case 4: dataLength = getInt(position()); break; default: throw new IllegalArgumentException("prefixLength: " + prefixLength); } if (dataLength < 0 || dataLength > maxDataLength) { throw new BufferDataException("dataLength: " + dataLength); } return remaining() - prefixLength >= dataLength; } /** * {@inheritDoc} */ @Override public int indexOf(byte b) { if (hasArray()) { int arrayOffset = arrayOffset(); int beginPos = arrayOffset + position(); int limit = arrayOffset + limit(); byte[] array = array(); for (int i = beginPos; i < limit; i++) { if (array[i] == b) { return i - arrayOffset; } } } else { int beginPos = position(); int limit = limit(); for (int i = beginPos; i < limit; i++) { if (get(i) == b) { return i; } } } return -1; } /** * {@inheritDoc} */ @Override public IoBuffer skip(int size) { autoExpand(size); return position(position() + size); } /** * {@inheritDoc} */ @Override public IoBuffer fill(byte value, int size) { autoExpand(size); int q = size >>> 3; int r = size & 7; if (q > 0) { int intValue = value | value << 8 | value << 16 | value << 24; long longValue = intValue; longValue <<= 32; longValue |= intValue; for (int i = q; i > 0; i--) { putLong(longValue); } } q = r >>> 2; r = r & 3; if (q > 0) { int intValue = value | value << 8 | value << 16 | value << 24; putInt(intValue); } q = r >> 1; r = r & 1; if (q > 0) { short shortValue = (short) (value | value << 8); putShort(shortValue); } if (r > 0) { put(value); } return this; } /** * {@inheritDoc} */ @Override public IoBuffer fillAndReset(byte value, int size) { autoExpand(size); int pos = position(); try { fill(value, size); } finally { position(pos); } return this; } /** * {@inheritDoc} */ @Override public IoBuffer fill(int size) { autoExpand(size); int q = size >>> 3; int r = size & 7; for (int i = q; i > 0; i--) { putLong(0L); } q = r >>> 2; r = r & 3; if (q > 0) { putInt(0); } q = r >> 1; r = r & 1; if (q > 0) { putShort((short) 0); } if (r > 0) { put((byte) 0); } return this; } /** * {@inheritDoc} */ @Override public IoBuffer fillAndReset(int size) { autoExpand(size); int pos = position(); try { fill(size); } finally { position(pos); } return this; } /** * {@inheritDoc} */ @Override public > E getEnum(Class enumClass) { return toEnum(enumClass, getUnsigned()); } /** * {@inheritDoc} */ @Override public > E getEnum(int index, Class enumClass) { return toEnum(enumClass, getUnsigned(index)); } /** * {@inheritDoc} */ @Override public > E getEnumShort(Class enumClass) { return toEnum(enumClass, getUnsignedShort()); } /** * {@inheritDoc} */ @Override public > E getEnumShort(int index, Class enumClass) { return toEnum(enumClass, getUnsignedShort(index)); } /** * {@inheritDoc} */ @Override public > E getEnumInt(Class enumClass) { return toEnum(enumClass, getInt()); } /** * {@inheritDoc} */ public > E getEnumInt(int index, Class enumClass) { return toEnum(enumClass, getInt(index)); } /** * {@inheritDoc} */ @Override public IoBuffer putEnum(Enum e) { if (e.ordinal() > BYTE_MASK) { throw new IllegalArgumentException(enumConversionErrorMessage(e, "byte")); } return put((byte) e.ordinal()); } /** * {@inheritDoc} */ @Override public IoBuffer putEnum(int index, Enum e) { if (e.ordinal() > BYTE_MASK) { throw new IllegalArgumentException(enumConversionErrorMessage(e, "byte")); } return put(index, (byte) e.ordinal()); } /** * {@inheritDoc} */ @Override public IoBuffer putEnumShort(Enum e) { if (e.ordinal() > SHORT_MASK) { throw new IllegalArgumentException(enumConversionErrorMessage(e, "short")); } return putShort((short) e.ordinal()); } /** * {@inheritDoc} */ @Override public IoBuffer putEnumShort(int index, Enum e) { if (e.ordinal() > SHORT_MASK) { throw new IllegalArgumentException(enumConversionErrorMessage(e, "short")); } return putShort(index, (short) e.ordinal()); } /** * {@inheritDoc} */ @Override public IoBuffer putEnumInt(Enum e) { return putInt(e.ordinal()); } /** * {@inheritDoc} */ @Override public IoBuffer putEnumInt(int index, Enum e) { return putInt(index, e.ordinal()); } private E toEnum(Class enumClass, int i) { E[] enumConstants = enumClass.getEnumConstants(); if (i > enumConstants.length) { throw new IndexOutOfBoundsException(String.format( "%d is too large of an ordinal to convert to the enum %s", i, enumClass.getName())); } return enumConstants[i]; } private String enumConversionErrorMessage(Enum e, String type) { return String.format("%s.%s has an ordinal value too large for a %s", e.getClass().getName(), e.name(), type); } /** * {@inheritDoc} */ @Override public > EnumSet getEnumSet(Class enumClass) { return toEnumSet(enumClass, get() & BYTE_MASK); } /** * {@inheritDoc} */ @Override public > EnumSet getEnumSet(int index, Class enumClass) { return toEnumSet(enumClass, get(index) & BYTE_MASK); } /** * {@inheritDoc} */ @Override public > EnumSet getEnumSetShort(Class enumClass) { return toEnumSet(enumClass, getShort() & SHORT_MASK); } /** * {@inheritDoc} */ @Override public > EnumSet getEnumSetShort(int index, Class enumClass) { return toEnumSet(enumClass, getShort(index) & SHORT_MASK); } /** * {@inheritDoc} */ @Override public > EnumSet getEnumSetInt(Class enumClass) { return toEnumSet(enumClass, getInt() & INT_MASK); } /** * {@inheritDoc} */ @Override public > EnumSet getEnumSetInt(int index, Class enumClass) { return toEnumSet(enumClass, getInt(index) & INT_MASK); } /** * {@inheritDoc} */ @Override public > EnumSet getEnumSetLong(Class enumClass) { return toEnumSet(enumClass, getLong()); } /** * {@inheritDoc} */ @Override public > EnumSet getEnumSetLong(int index, Class enumClass) { return toEnumSet(enumClass, getLong(index)); } private > EnumSet toEnumSet(Class clazz, long vector) { EnumSet set = EnumSet.noneOf(clazz); long mask = 1; for (E e : clazz.getEnumConstants()) { if ((mask & vector) == mask) { set.add(e); } mask <<= 1; } return set; } /** * {@inheritDoc} */ @Override public > IoBuffer putEnumSet(Set set) { long vector = toLong(set); if ((vector & ~BYTE_MASK) != 0) { throw new IllegalArgumentException("The enum set is too large to fit in a byte: " + set); } return put((byte) vector); } /** * {@inheritDoc} */ @Override public > IoBuffer putEnumSet(int index, Set set) { long vector = toLong(set); if ((vector & ~BYTE_MASK) != 0) { throw new IllegalArgumentException("The enum set is too large to fit in a byte: " + set); } return put(index, (byte) vector); } /** * {@inheritDoc} */ @Override public > IoBuffer putEnumSetShort(Set set) { long vector = toLong(set); if ((vector & ~SHORT_MASK) != 0) { throw new IllegalArgumentException("The enum set is too large to fit in a short: " + set); } return putShort((short) vector); } /** * {@inheritDoc} */ @Override public > IoBuffer putEnumSetShort(int index, Set set) { long vector = toLong(set); if ((vector & ~SHORT_MASK) != 0) { throw new IllegalArgumentException("The enum set is too large to fit in a short: " + set); } return putShort(index, (short) vector); } /** * {@inheritDoc} */ @Override public > IoBuffer putEnumSetInt(Set set) { long vector = toLong(set); if ((vector & ~INT_MASK) != 0) { throw new IllegalArgumentException("The enum set is too large to fit in an int: " + set); } return putInt((int) vector); } /** * {@inheritDoc} */ @Override public > IoBuffer putEnumSetInt(int index, Set set) { long vector = toLong(set); if ((vector & ~INT_MASK) != 0) { throw new IllegalArgumentException("The enum set is too large to fit in an int: " + set); } return putInt(index, (int) vector); } /** * {@inheritDoc} */ @Override public > IoBuffer putEnumSetLong(Set set) { return putLong(toLong(set)); } /** * {@inheritDoc} */ @Override public > IoBuffer putEnumSetLong(int index, Set set) { return putLong(index, toLong(set)); } private > long toLong(Set set) { long vector = 0; for (E e : set) { if (e.ordinal() >= Long.SIZE) { throw new IllegalArgumentException("The enum set is too large to fit in a bit vector: " + set); } vector |= 1L << e.ordinal(); } return vector; } /** * This method forwards the call to {@link #expand(int)} only when * autoExpand property is true. */ private IoBuffer autoExpand(int expectedRemaining) { if (isAutoExpand()) { expand(expectedRemaining, true); } return this; } /** * This method forwards the call to {@link #expand(int)} only when * autoExpand property is true. */ private IoBuffer autoExpand(int pos, int expectedRemaining) { if (isAutoExpand()) { expand(pos, expectedRemaining, true); } return this; } private static void checkFieldSize(int fieldSize) { if (fieldSize < 0) { throw new IllegalArgumentException("fieldSize cannot be negative: " + fieldSize); } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/IoUtil.java0000644000175000017500000001463012032276032026047 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.concurrent.TimeUnit; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.future.IoFuture; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.session.IoSession; /** * A utility class that provides various convenience methods related with * {@link IoSession} and {@link IoFuture}. * * @author Apache MINA Project */ public class IoUtil { private static final IoSession[] EMPTY_SESSIONS = new IoSession[0]; /** * Writes the specified {@code message} to the specified {@code sessions}. * If the specified {@code message} is an {@link IoBuffer}, the buffer is * automatically duplicated using {@link IoBuffer#duplicate()}. */ public static List broadcast(Object message, Collection sessions) { List answer = new ArrayList(sessions.size()); broadcast(message, sessions.iterator(), answer); return answer; } /** * Writes the specified {@code message} to the specified {@code sessions}. * If the specified {@code message} is an {@link IoBuffer}, the buffer is * automatically duplicated using {@link IoBuffer#duplicate()}. */ public static List broadcast(Object message, Iterable sessions) { List answer = new ArrayList(); broadcast(message, sessions.iterator(), answer); return answer; } /** * Writes the specified {@code message} to the specified {@code sessions}. * If the specified {@code message} is an {@link IoBuffer}, the buffer is * automatically duplicated using {@link IoBuffer#duplicate()}. */ public static List broadcast(Object message, Iterator sessions) { List answer = new ArrayList(); broadcast(message, sessions, answer); return answer; } /** * Writes the specified {@code message} to the specified {@code sessions}. * If the specified {@code message} is an {@link IoBuffer}, the buffer is * automatically duplicated using {@link IoBuffer#duplicate()}. */ public static List broadcast(Object message, IoSession... sessions) { if (sessions == null) { sessions = EMPTY_SESSIONS; } List answer = new ArrayList(sessions.length); if (message instanceof IoBuffer) { for (IoSession s : sessions) { answer.add(s.write(((IoBuffer) message).duplicate())); } } else { for (IoSession s : sessions) { answer.add(s.write(message)); } } return answer; } private static void broadcast(Object message, Iterator sessions, Collection answer) { if (message instanceof IoBuffer) { while (sessions.hasNext()) { IoSession s = sessions.next(); answer.add(s.write(((IoBuffer) message).duplicate())); } } else { while (sessions.hasNext()) { IoSession s = sessions.next(); answer.add(s.write(message)); } } } public static void await(Iterable futures) throws InterruptedException { for (IoFuture f : futures) { f.await(); } } public static void awaitUninterruptably(Iterable futures) { for (IoFuture f : futures) { f.awaitUninterruptibly(); } } public static boolean await(Iterable futures, long timeout, TimeUnit unit) throws InterruptedException { return await(futures, unit.toMillis(timeout)); } public static boolean await(Iterable futures, long timeoutMillis) throws InterruptedException { return await0(futures, timeoutMillis, true); } public static boolean awaitUninterruptibly(Iterable futures, long timeout, TimeUnit unit) { return awaitUninterruptibly(futures, unit.toMillis(timeout)); } public static boolean awaitUninterruptibly(Iterable futures, long timeoutMillis) { try { return await0(futures, timeoutMillis, false); } catch (InterruptedException e) { throw new InternalError(); } } private static boolean await0(Iterable futures, long timeoutMillis, boolean interruptable) throws InterruptedException { long startTime = timeoutMillis <= 0 ? 0 : System.currentTimeMillis(); long waitTime = timeoutMillis; boolean lastComplete = true; Iterator i = futures.iterator(); while (i.hasNext()) { IoFuture f = i.next(); do { if (interruptable) { lastComplete = f.await(waitTime); } else { lastComplete = f.awaitUninterruptibly(waitTime); } waitTime = timeoutMillis - (System.currentTimeMillis() - startTime); if (lastComplete || waitTime <= 0) { break; } } while (!lastComplete); if (waitTime <= 0) { break; } } return lastComplete && !i.hasNext(); } private IoUtil() { // Do nothing } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/file/0000755000175000017500000000000012162575507024727 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/file/FilenameFileRegion.java0000644000175000017500000000321512032276026031245 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.file; import java.io.File; import java.io.IOException; import java.nio.channels.FileChannel; /** * TODO Add documentation * * * @author The Apache MINA Project (dev@mina.apache.org) * @version $Rev$, $Date$ */ public class FilenameFileRegion extends DefaultFileRegion { private final File file; public FilenameFileRegion(File file, FileChannel channel) throws IOException { this(file, channel, 0, file.length()); } public FilenameFileRegion(File file, FileChannel channel, long position, long remainingBytes) { super(channel, position, remainingBytes); if (file == null) { throw new IllegalArgumentException("file can not be null"); } this.file = file; } public String getFilename() { return file.getAbsolutePath(); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/file/FileRegion.java0000644000175000017500000000457312032276026027614 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.file; import java.nio.channels.FileChannel; /** * Indicates the region of a file to be sent to the remote host. * * @author Apache MINA Project */ public interface FileRegion { /** * The open FileChannel from which data will be read to send to * remote host. * * @return An open FileChannel. */ FileChannel getFileChannel(); /** * The current file position from which data will be read. * * @return The current file position. */ long getPosition(); /** * Updates the current file position based on the specified amount. This * increases the value returned by {@link #getPosition()} and * {@link getWrittenBytes} by the given amount and decreases the value * returned by {@link #getCount()} by the given {@code amount}. * * @param amount The new value for the file position. */ void update(long amount); /** * The number of bytes remaining to be written from the file to the remote * host. * * @return The number of bytes remaining to be written. */ long getRemainingBytes(); /** * The total number of bytes already written. * * @return The total number of bytes already written. */ long getWrittenBytes(); /** * Provides an absolute filename for the underlying FileChannel. * * @return the absolute filename, or null if the FileRegion * does not know the filename */ String getFilename(); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/file/DefaultFileRegion.java0000644000175000017500000000461512032276026031116 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.file; import java.io.IOException; import java.nio.channels.FileChannel; /** * TODO Add documentation * * * @author Apache MINA Project */ public class DefaultFileRegion implements FileRegion { private final FileChannel channel; private final long originalPosition; private long position; private long remainingBytes; public DefaultFileRegion(FileChannel channel) throws IOException { this(channel, 0, channel.size()); } public DefaultFileRegion(FileChannel channel, long position, long remainingBytes) { if (channel == null) { throw new IllegalArgumentException("channel can not be null"); } if (position < 0) { throw new IllegalArgumentException("position may not be less than 0"); } if (remainingBytes < 0) { throw new IllegalArgumentException("remainingBytes may not be less than 0"); } this.channel = channel; this.originalPosition = position; this.position = position; this.remainingBytes = remainingBytes; } public long getWrittenBytes() { return position - originalPosition; } public long getRemainingBytes() { return remainingBytes; } public FileChannel getFileChannel() { return channel; } public long getPosition() { return position; } public void update(long value) { position += value; remainingBytes -= value; } public String getFilename() { return null; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/RuntimeIoException.java0000644000175000017500000000316412032276032030434 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core; import java.io.IOException; /** * A unchecked version of {@link IOException}. *

* Please note that {@link RuntimeIoException} is different from * {@link IOException} in that doesn't trigger force session close, * while {@link IOException} forces disconnection. * * @author Apache MINA Project */ public class RuntimeIoException extends RuntimeException { private static final long serialVersionUID = 9029092241311939548L; public RuntimeIoException() { super(); } public RuntimeIoException(String message) { super(message); } public RuntimeIoException(String message, Throwable cause) { super(message, cause); } public RuntimeIoException(Throwable cause) { super(cause); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/0000755000175000017500000000000012162575507025473 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/SessionState.java0000644000175000017500000000233012032276030030741 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; /** * The session state. A session can be in three different state : *

    *
  • OPENING : The session has not been fully created
  • *
  • OPENED : The session is opened
  • *
  • CLOSING : The session is closing
  • *
* * @author Apache MINA Project */ public enum SessionState { OPENING, OPENED, CLOSING }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/AttributeKey.java0000644000175000017500000000531712032276030030741 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; import java.io.Serializable; /** * Creates a Key from a class name and an attribute name. The resulting Key will * be stored in the session Map.
* For instance, we can create a 'processor' AttributeKey this way : * *
 * private static final AttributeKey PROCESSOR = new AttributeKey(
 * 	SimpleIoProcessorPool.class, "processor");
 * 
* * This will create the SimpleIoProcessorPool.processor@7DE45C99 key * which will be stored in the session map.
* Such an attributeKey is mainly useful for debug purposes. * * @author Apache MINA Project */ public final class AttributeKey implements Serializable { /** The serial version UID */ private static final long serialVersionUID = -583377473376683096L; /** The attribute's name */ private final String name; /** * Creates a new instance. It's built from : *
    *
  • the class' name
  • *
  • the attribute's name
  • *
  • this attribute hashCode
  • *
* * @param source The class this AttributeKey will be attached to * @param name The Attribute name */ public AttributeKey(Class source, String name) { this.name = source.getName() + '.' + name + '@' + Integer.toHexString(this.hashCode()); } /** * The String representation of this object. */ @Override public String toString() { return name; } @Override public int hashCode() { int h = 17 * 37 + ((name == null) ? 0 : name.hashCode()); return h; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof AttributeKey)) { return false; } AttributeKey other = (AttributeKey) obj; return name.equals(other.name); } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/IoSessionInitializationException.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/IoSessionInitializationExc0000644000175000017500000000304012032276030032657 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; /** * A {@link RuntimeException} that is thrown when the initialization of * an {@link IoSession} fails. * * @author Apache MINA Project */ public class IoSessionInitializationException extends RuntimeException { private static final long serialVersionUID = -1205810145763696189L; public IoSessionInitializationException() { super(); } public IoSessionInitializationException(String message, Throwable cause) { super(message, cause); } public IoSessionInitializationException(String message) { super(message); } public IoSessionInitializationException(Throwable cause) { super(cause); } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/DefaultIoSessionDataStructureFactory.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/DefaultIoSessionDataStruct0000644000175000017500000001465712032276030032633 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; import java.util.HashMap; import java.util.HashSet; import java.util.Queue; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.core.write.WriteRequestQueue; /** * The default {@link IoSessionDataStructureFactory} implementation * that creates a new {@link HashMap}-based {@link IoSessionAttributeMap} * instance and a new synchronized {@link ConcurrentLinkedQueue} instance per * {@link IoSession}. * * @author Apache MINA Project */ public class DefaultIoSessionDataStructureFactory implements IoSessionDataStructureFactory { public IoSessionAttributeMap getAttributeMap(IoSession session) throws Exception { return new DefaultIoSessionAttributeMap(); } public WriteRequestQueue getWriteRequestQueue(IoSession session) throws Exception { return new DefaultWriteRequestQueue(); } private static class DefaultIoSessionAttributeMap implements IoSessionAttributeMap { private final ConcurrentHashMap attributes = new ConcurrentHashMap(4); /** * Default constructor */ public DefaultIoSessionAttributeMap() { super(); } /** * {@inheritDoc} */ public Object getAttribute(IoSession session, Object key, Object defaultValue) { if (key == null) { throw new IllegalArgumentException("key"); } if (defaultValue == null) { return attributes.get(key); } Object object = attributes.putIfAbsent(key, defaultValue); if (object == null) { return defaultValue; } else { return object; } } /** * {@inheritDoc} */ public Object setAttribute(IoSession session, Object key, Object value) { if (key == null) { throw new IllegalArgumentException("key"); } if (value == null) { return attributes.remove(key); } return attributes.put(key, value); } /** * {@inheritDoc} */ public Object setAttributeIfAbsent(IoSession session, Object key, Object value) { if (key == null) { throw new IllegalArgumentException("key"); } if (value == null) { return null; } return attributes.putIfAbsent(key, value); } /** * {@inheritDoc} */ public Object removeAttribute(IoSession session, Object key) { if (key == null) { throw new IllegalArgumentException("key"); } return attributes.remove(key); } /** * {@inheritDoc} */ public boolean removeAttribute(IoSession session, Object key, Object value) { if (key == null) { throw new IllegalArgumentException("key"); } if (value == null) { return false; } try { return attributes.remove(key, value); } catch (NullPointerException e) { return false; } } /** * {@inheritDoc} */ public boolean replaceAttribute(IoSession session, Object key, Object oldValue, Object newValue) { try { return attributes.replace(key, oldValue, newValue); } catch (NullPointerException e) { } return false; } /** * {@inheritDoc} */ public boolean containsAttribute(IoSession session, Object key) { return attributes.containsKey(key); } /** * {@inheritDoc} */ public Set getAttributeKeys(IoSession session) { synchronized (attributes) { return new HashSet(attributes.keySet()); } } /** * {@inheritDoc} */ public void dispose(IoSession session) throws Exception { // Do nothing } } private static class DefaultWriteRequestQueue implements WriteRequestQueue { /** A queue to store incoming write requests */ private final Queue q = new ConcurrentLinkedQueue(); /** * Default constructor */ public DefaultWriteRequestQueue() { super(); } /** * {@inheritDoc} */ public void dispose(IoSession session) { // Do nothing } /** * {@inheritDoc} */ public void clear(IoSession session) { q.clear(); } /** * {@inheritDoc} */ public synchronized boolean isEmpty(IoSession session) { return q.isEmpty(); } /** * {@inheritDoc} */ public synchronized void offer(IoSession session, WriteRequest writeRequest) { q.offer(writeRequest); } /** * {@inheritDoc} */ public synchronized WriteRequest poll(IoSession session) { return q.poll(); } @Override public String toString() { return q.toString(); } /** * {@inheritDoc} */ public int size() { return q.size(); } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/IdleStatus.java0000644000175000017500000000474412032276030030411 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; /** * Represents the type of idleness of {@link IoSession} or * {@link IoSession}. There are three types of idleness: *
    *
  • {@link #READER_IDLE} - No data is coming from the remote peer.
  • *
  • {@link #WRITER_IDLE} - Session is not writing any data.
  • *
  • {@link #BOTH_IDLE} - Both {@link #READER_IDLE} and {@link #WRITER_IDLE}.
  • *
*

* Idle time settings are all disabled by default. You can enable them * using {@link IoSessionConfig#setIdleTime(IdleStatus,int)}. * * @author Apache MINA Project */ public class IdleStatus { /** * Represents the session status that no data is coming from the remote * peer. */ public static final IdleStatus READER_IDLE = new IdleStatus("reader idle"); /** * Represents the session status that the session is not writing any data. */ public static final IdleStatus WRITER_IDLE = new IdleStatus("writer idle"); /** * Represents both {@link #READER_IDLE} and {@link #WRITER_IDLE}. */ public static final IdleStatus BOTH_IDLE = new IdleStatus("both idle"); private final String strValue; /** * Creates a new instance. */ private IdleStatus(String strValue) { this.strValue = strValue; } /** * Returns the string representation of this status. *

    *
  • {@link #READER_IDLE} - "reader idle"
  • *
  • {@link #WRITER_IDLE} - "writer idle"
  • *
  • {@link #BOTH_IDLE} - "both idle"
  • *
*/ @Override public String toString() { return strValue; } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/IoSessionRecycler.java0000644000175000017500000000473012032276030031727 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; import java.net.SocketAddress; import org.apache.mina.core.service.IoService; /** * A connectionless transport can recycle existing sessions by assigning an * {@link IoSessionRecycler} to an {@link IoService}. * * @author Apache MINA Project * TODO More documentation */ public interface IoSessionRecycler { /** * A dummy recycler that doesn't recycle any sessions. Using this recycler will * make all session lifecycle events to be fired for every I/O for all connectionless * sessions. */ static IoSessionRecycler NOOP = new IoSessionRecycler() { public void put(IoSession session) { // Do nothing } public IoSession recycle(SocketAddress remoteAddress) { return null; } public void remove(IoSession session) { // Do nothing } }; /** * Called when the underlying transport creates or writes a new {@link IoSession}. * * @param session * the new {@link IoSession}. */ void put(IoSession session); /** * Attempts to retrieve a recycled {@link IoSession}. * * @param remoteAddress * the remote socket address of the {@link IoSession} the * transport wants to recycle. * @return a recycled {@link IoSession}, or null if one cannot be found. */ IoSession recycle(SocketAddress remoteAddress); /** * Called when an {@link IoSession} is explicitly closed. * * @param session * the new {@link IoSession}. */ void remove(IoSession session); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/IdleStatusChecker.java0000644000175000017500000001151112032276030031664 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; import java.util.Iterator; import java.util.Set; import org.apache.mina.core.future.CloseFuture; import org.apache.mina.core.future.IoFuture; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.service.IoService; import org.apache.mina.util.ConcurrentHashSet; /** * Detects idle sessions and fires sessionIdle events to them. * To be used for service unable to trigger idle events alone, like VmPipe * or SerialTransport. Polling base transport are advised to trigger idle * events alone, using the poll/select timeout. * * @author Apache MINA Project */ public class IdleStatusChecker { // the list of session to check private final Set sessions = new ConcurrentHashSet(); /* create a task you can execute in the transport code, * if the transport is like NIO or APR you don't need to call it, * you just need to call the needed static sessions on select()/poll() * timeout. */ private final NotifyingTask notifyingTask = new NotifyingTask(); private final IoFutureListener sessionCloseListener = new SessionCloseListener(); public IdleStatusChecker() { // Do nothing } /** * Add the session for being checked for idle. * @param session the session to check */ public void addSession(AbstractIoSession session) { sessions.add(session); CloseFuture closeFuture = session.getCloseFuture(); // isn't service reponsability to remove the session nicely ? closeFuture.addListener(sessionCloseListener); } /** * remove a session from the list of session being checked. * @param session */ private void removeSession(AbstractIoSession session) { sessions.remove(session); } /** * get a runnable task able to be scheduled in the {@link IoService} executor. * @return */ public NotifyingTask getNotifyingTask() { return notifyingTask; } /** * The class to place in the transport executor for checking the sessions idle */ public class NotifyingTask implements Runnable { private volatile boolean cancelled; private volatile Thread thread; // we forbid instantiation of this class outside /** No qualifier */ NotifyingTask() { // Do nothing } public void run() { thread = Thread.currentThread(); try { while (!cancelled) { // Check idleness with fixed delay (1 second). long currentTime = System.currentTimeMillis(); notifySessions(currentTime); try { Thread.sleep(1000); } catch (InterruptedException e) { // will exit the loop if interrupted from interrupt() } } } finally { thread = null; } } /** * stop execution of the task */ public void cancel() { cancelled = true; Thread thread = this.thread; if (thread != null) { thread.interrupt(); } } private void notifySessions(long currentTime) { Iterator it = sessions.iterator(); while (it.hasNext()) { AbstractIoSession session = it.next(); if (session.isConnected()) { AbstractIoSession.notifyIdleSession(session, currentTime); } } } } private class SessionCloseListener implements IoFutureListener { /** * Default constructor */ public SessionCloseListener() { super(); } public void operationComplete(IoFuture future) { removeSession((AbstractIoSession) future.getSession()); } } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/IoEventType.java0000644000175000017500000000240512032276030030533 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; /** * An {@link Enum} that represents the type of I/O events and requests. * Most users won't need to use this class. It is usually used by internal * components to store I/O events. * * @author Apache MINA Project */ public enum IoEventType { SESSION_CREATED, SESSION_OPENED, SESSION_CLOSED, MESSAGE_RECEIVED, MESSAGE_SENT, SESSION_IDLE, EXCEPTION_CAUGHT, WRITE, CLOSE, } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/UnknownMessageTypeException.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/UnknownMessageTypeExceptio0000644000175000017500000000276412032276030032717 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; /** * An exception that is thrown when the type of the message cannot be determined. * * @author Apache MINA Project */ public class UnknownMessageTypeException extends RuntimeException { private static final long serialVersionUID = 3257290227428047158L; public UnknownMessageTypeException() { // Do nothing } public UnknownMessageTypeException(String message, Throwable cause) { super(message, cause); } public UnknownMessageTypeException(String message) { super(message); } public UnknownMessageTypeException(Throwable cause) { super(cause); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/IoSessionInitializer.java0000644000175000017500000000226012032276030032436 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; import org.apache.mina.core.future.IoFuture; /** * Defines a callback for obtaining the {@link IoSession} during * session initialization. * * @author Apache MINA Project */ public interface IoSessionInitializer { void initializeSession(IoSession session, T future); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/DummySession.java0000644000175000017500000002473312032276030030767 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; import java.io.IOException; import java.net.SocketAddress; import java.util.List; import java.util.Set; import java.util.concurrent.Executor; import org.apache.mina.core.file.FileRegion; import org.apache.mina.core.filterchain.DefaultIoFilterChain; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.service.AbstractIoAcceptor; import org.apache.mina.core.service.DefaultTransportMetadata; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.IoService; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.core.write.WriteRequestQueue; /** * A dummy {@link IoSession} for unit-testing or non-network-use of * the classes that depends on {@link IoSession}. * *

Overriding I/O request methods

* All I/O request methods (i.e. {@link #close()}, {@link #write(Object)} and * {@link #setTrafficMask(TrafficMask)}) are final and therefore cannot be * overridden, but you can always add your custom {@link IoFilter} to the * {@link IoFilterChain} to intercept any I/O events and requests. * * @author Apache MINA Project */ public class DummySession extends AbstractIoSession { private static final TransportMetadata TRANSPORT_METADATA = new DefaultTransportMetadata("mina", "dummy", false, false, SocketAddress.class, IoSessionConfig.class, Object.class); private static final SocketAddress ANONYMOUS_ADDRESS = new SocketAddress() { private static final long serialVersionUID = -496112902353454179L; @Override public String toString() { return "?"; } }; private volatile IoService service; private volatile IoSessionConfig config = new AbstractIoSessionConfig() { @Override protected void doSetAll(IoSessionConfig config) { // Do nothing } }; private final IoFilterChain filterChain = new DefaultIoFilterChain(this); private final IoProcessor processor; private volatile IoHandler handler = new IoHandlerAdapter(); private volatile SocketAddress localAddress = ANONYMOUS_ADDRESS; private volatile SocketAddress remoteAddress = ANONYMOUS_ADDRESS; private volatile TransportMetadata transportMetadata = TRANSPORT_METADATA; /** * Creates a new instance. */ public DummySession() { super( // Initialize dummy service. new AbstractIoAcceptor(new AbstractIoSessionConfig() { @Override protected void doSetAll(IoSessionConfig config) { // Do nothing } }, new Executor() { public void execute(Runnable command) { // Do nothing } }) { @Override protected Set bindInternal(List localAddresses) throws Exception { throw new UnsupportedOperationException(); } @Override protected void unbind0(List localAddresses) throws Exception { throw new UnsupportedOperationException(); } public IoSession newSession(SocketAddress remoteAddress, SocketAddress localAddress) { throw new UnsupportedOperationException(); } public TransportMetadata getTransportMetadata() { return TRANSPORT_METADATA; } @Override protected void dispose0() throws Exception { } }); processor = new IoProcessor() { public void add(AbstractIoSession session) { // Do nothing } public void flush(AbstractIoSession session) { DummySession s = (DummySession) session; WriteRequest req = s.getWriteRequestQueue().poll(session); // Chek that the request is not null. If the session has been closed, // we may not have any pending requests. if (req != null) { Object m = req.getMessage(); if (m instanceof FileRegion) { FileRegion file = (FileRegion) m; try { file.getFileChannel().position(file.getPosition() + file.getRemainingBytes()); file.update(file.getRemainingBytes()); } catch (IOException e) { s.getFilterChain().fireExceptionCaught(e); } } getFilterChain().fireMessageSent(req); } } /** * {@inheritDoc} */ public void write(AbstractIoSession session, WriteRequest writeRequest) { WriteRequestQueue writeRequestQueue = session.getWriteRequestQueue(); writeRequestQueue.offer(session, writeRequest); if (!session.isWriteSuspended()) { this.flush(session); } } public void remove(AbstractIoSession session) { if (!session.getCloseFuture().isClosed()) { session.getFilterChain().fireSessionClosed(); } } public void updateTrafficControl(AbstractIoSession session) { // Do nothing } public void dispose() { // Do nothing } public boolean isDisposed() { return false; } public boolean isDisposing() { return false; } }; this.service = super.getService(); try { IoSessionDataStructureFactory factory = new DefaultIoSessionDataStructureFactory(); setAttributeMap(factory.getAttributeMap(this)); setWriteRequestQueue(factory.getWriteRequestQueue(this)); } catch (Exception e) { throw new InternalError(); } } public IoSessionConfig getConfig() { return config; } /** * Sets the configuration of this session. */ public void setConfig(IoSessionConfig config) { if (config == null) { throw new IllegalArgumentException("config"); } this.config = config; } public IoFilterChain getFilterChain() { return filterChain; } public IoHandler getHandler() { return handler; } /** * Sets the {@link IoHandler} which handles this session. */ public void setHandler(IoHandler handler) { if (handler == null) { throw new IllegalArgumentException("handler"); } this.handler = handler; } public SocketAddress getLocalAddress() { return localAddress; } public SocketAddress getRemoteAddress() { return remoteAddress; } /** * Sets the socket address of local machine which is associated with * this session. */ public void setLocalAddress(SocketAddress localAddress) { if (localAddress == null) { throw new IllegalArgumentException("localAddress"); } this.localAddress = localAddress; } /** * Sets the socket address of remote peer. */ public void setRemoteAddress(SocketAddress remoteAddress) { if (remoteAddress == null) { throw new IllegalArgumentException("remoteAddress"); } this.remoteAddress = remoteAddress; } public IoService getService() { return service; } /** * Sets the {@link IoService} which provides I/O service to this session. */ public void setService(IoService service) { if (service == null) { throw new IllegalArgumentException("service"); } this.service = service; } @Override public final IoProcessor getProcessor() { return processor; } public TransportMetadata getTransportMetadata() { return transportMetadata; } /** * Sets the {@link TransportMetadata} that this session runs on. */ public void setTransportMetadata(TransportMetadata transportMetadata) { if (transportMetadata == null) { throw new IllegalArgumentException("transportMetadata"); } this.transportMetadata = transportMetadata; } @Override public void setScheduledWriteBytes(int byteCount) { super.setScheduledWriteBytes(byteCount); } @Override public void setScheduledWriteMessages(int messages) { super.setScheduledWriteMessages(messages); } /** * Update all statistical properties related with throughput. By default * this method returns silently without updating the throughput properties * if they were calculated already within last * {@link IoSessionConfig#getThroughputCalculationInterval() calculation interval}. * If, however, force is specified as true, this method * updates the throughput properties immediately. */ public void updateThroughput(boolean force) { super.updateThroughput(System.currentTimeMillis(), force); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/AbstractIoSessionConfig.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/AbstractIoSessionConfig.ja0000644000175000017500000002016612032276030032522 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; /** * A base implementation of {@link IoSessionConfig}. * * @author Apache MINA Project */ public abstract class AbstractIoSessionConfig implements IoSessionConfig { private int minReadBufferSize = 64; private int readBufferSize = 2048; private int maxReadBufferSize = 65536; private int idleTimeForRead; private int idleTimeForWrite; private int idleTimeForBoth; private int writeTimeout = 60; private boolean useReadOperation; private int throughputCalculationInterval = 3; protected AbstractIoSessionConfig() { // Do nothing } /** * {@inheritDoc} */ public final void setAll(IoSessionConfig config) { if (config == null) { throw new IllegalArgumentException("config"); } setReadBufferSize(config.getReadBufferSize()); setMinReadBufferSize(config.getMinReadBufferSize()); setMaxReadBufferSize(config.getMaxReadBufferSize()); setIdleTime(IdleStatus.BOTH_IDLE, config.getIdleTime(IdleStatus.BOTH_IDLE)); setIdleTime(IdleStatus.READER_IDLE, config.getIdleTime(IdleStatus.READER_IDLE)); setIdleTime(IdleStatus.WRITER_IDLE, config.getIdleTime(IdleStatus.WRITER_IDLE)); setWriteTimeout(config.getWriteTimeout()); setUseReadOperation(config.isUseReadOperation()); setThroughputCalculationInterval(config.getThroughputCalculationInterval()); doSetAll(config); } /** * Implement this method to set all transport-specific configuration * properties retrieved from the specified config. */ protected abstract void doSetAll(IoSessionConfig config); /** * {@inheritDoc} */ public int getReadBufferSize() { return readBufferSize; } /** * {@inheritDoc} */ public void setReadBufferSize(int readBufferSize) { if (readBufferSize <= 0) { throw new IllegalArgumentException("readBufferSize: " + readBufferSize + " (expected: 1+)"); } this.readBufferSize = readBufferSize; } /** * {@inheritDoc} */ public int getMinReadBufferSize() { return minReadBufferSize; } /** * {@inheritDoc} */ public void setMinReadBufferSize(int minReadBufferSize) { if (minReadBufferSize <= 0) { throw new IllegalArgumentException("minReadBufferSize: " + minReadBufferSize + " (expected: 1+)"); } if (minReadBufferSize > maxReadBufferSize) { throw new IllegalArgumentException("minReadBufferSize: " + minReadBufferSize + " (expected: smaller than " + maxReadBufferSize + ')'); } this.minReadBufferSize = minReadBufferSize; } /** * {@inheritDoc} */ public int getMaxReadBufferSize() { return maxReadBufferSize; } /** * {@inheritDoc} */ public void setMaxReadBufferSize(int maxReadBufferSize) { if (maxReadBufferSize <= 0) { throw new IllegalArgumentException("maxReadBufferSize: " + maxReadBufferSize + " (expected: 1+)"); } if (maxReadBufferSize < minReadBufferSize) { throw new IllegalArgumentException("maxReadBufferSize: " + maxReadBufferSize + " (expected: greater than " + minReadBufferSize + ')'); } this.maxReadBufferSize = maxReadBufferSize; } /** * {@inheritDoc} */ public int getIdleTime(IdleStatus status) { if (status == IdleStatus.BOTH_IDLE) { return idleTimeForBoth; } if (status == IdleStatus.READER_IDLE) { return idleTimeForRead; } if (status == IdleStatus.WRITER_IDLE) { return idleTimeForWrite; } throw new IllegalArgumentException("Unknown idle status: " + status); } /** * {@inheritDoc} */ public long getIdleTimeInMillis(IdleStatus status) { return getIdleTime(status) * 1000L; } /** * {@inheritDoc} */ public void setIdleTime(IdleStatus status, int idleTime) { if (idleTime < 0) { throw new IllegalArgumentException("Illegal idle time: " + idleTime); } if (status == IdleStatus.BOTH_IDLE) { idleTimeForBoth = idleTime; } else if (status == IdleStatus.READER_IDLE) { idleTimeForRead = idleTime; } else if (status == IdleStatus.WRITER_IDLE) { idleTimeForWrite = idleTime; } else { throw new IllegalArgumentException("Unknown idle status: " + status); } } /** * {@inheritDoc} */ public final int getBothIdleTime() { return getIdleTime(IdleStatus.BOTH_IDLE); } /** * {@inheritDoc} */ public final long getBothIdleTimeInMillis() { return getIdleTimeInMillis(IdleStatus.BOTH_IDLE); } /** * {@inheritDoc} */ public final int getReaderIdleTime() { return getIdleTime(IdleStatus.READER_IDLE); } /** * {@inheritDoc} */ public final long getReaderIdleTimeInMillis() { return getIdleTimeInMillis(IdleStatus.READER_IDLE); } /** * {@inheritDoc} */ public final int getWriterIdleTime() { return getIdleTime(IdleStatus.WRITER_IDLE); } /** * {@inheritDoc} */ public final long getWriterIdleTimeInMillis() { return getIdleTimeInMillis(IdleStatus.WRITER_IDLE); } /** * {@inheritDoc} */ public void setBothIdleTime(int idleTime) { setIdleTime(IdleStatus.BOTH_IDLE, idleTime); } /** * {@inheritDoc} */ public void setReaderIdleTime(int idleTime) { setIdleTime(IdleStatus.READER_IDLE, idleTime); } /** * {@inheritDoc} */ public void setWriterIdleTime(int idleTime) { setIdleTime(IdleStatus.WRITER_IDLE, idleTime); } /** * {@inheritDoc} */ public int getWriteTimeout() { return writeTimeout; } /** * {@inheritDoc} */ public long getWriteTimeoutInMillis() { return writeTimeout * 1000L; } /** * {@inheritDoc} */ public void setWriteTimeout(int writeTimeout) { if (writeTimeout < 0) { throw new IllegalArgumentException("Illegal write timeout: " + writeTimeout); } this.writeTimeout = writeTimeout; } /** * {@inheritDoc} */ public boolean isUseReadOperation() { return useReadOperation; } /** * {@inheritDoc} */ public void setUseReadOperation(boolean useReadOperation) { this.useReadOperation = useReadOperation; } /** * {@inheritDoc} */ public int getThroughputCalculationInterval() { return throughputCalculationInterval; } /** * {@inheritDoc} */ public void setThroughputCalculationInterval(int throughputCalculationInterval) { if (throughputCalculationInterval < 0) { throw new IllegalArgumentException("throughputCalculationInterval: " + throughputCalculationInterval); } this.throughputCalculationInterval = throughputCalculationInterval; } /** * {@inheritDoc} */ public long getThroughputCalculationIntervalInMillis() { return throughputCalculationInterval * 1000L; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/IoSessionConfig.java0000644000175000017500000001404112032276030031360 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; import java.util.concurrent.BlockingQueue; /** * The configuration of {@link IoSession}. * * @author Apache MINA Project */ public interface IoSessionConfig { /** * Returns the size of the read buffer that I/O processor allocates * per each read. It's unusual to adjust this property because * it's often adjusted automatically by the I/O processor. */ int getReadBufferSize(); /** * Sets the size of the read buffer that I/O processor allocates * per each read. It's unusual to adjust this property because * it's often adjusted automatically by the I/O processor. */ void setReadBufferSize(int readBufferSize); /** * Returns the minimum size of the read buffer that I/O processor * allocates per each read. I/O processor will not decrease the * read buffer size to the smaller value than this property value. */ int getMinReadBufferSize(); /** * Sets the minimum size of the read buffer that I/O processor * allocates per each read. I/O processor will not decrease the * read buffer size to the smaller value than this property value. */ void setMinReadBufferSize(int minReadBufferSize); /** * Returns the maximum size of the read buffer that I/O processor * allocates per each read. I/O processor will not increase the * read buffer size to the greater value than this property value. */ int getMaxReadBufferSize(); /** * Sets the maximum size of the read buffer that I/O processor * allocates per each read. I/O processor will not increase the * read buffer size to the greater value than this property value. */ void setMaxReadBufferSize(int maxReadBufferSize); /** * Returns the interval (seconds) between each throughput calculation. * The default value is 3 seconds. */ int getThroughputCalculationInterval(); /** * Returns the interval (milliseconds) between each throughput calculation. * The default value is 3 seconds. */ long getThroughputCalculationIntervalInMillis(); /** * Sets the interval (seconds) between each throughput calculation. The * default value is 3 seconds. */ void setThroughputCalculationInterval(int throughputCalculationInterval); /** * Returns idle time for the specified type of idleness in seconds. */ int getIdleTime(IdleStatus status); /** * Returns idle time for the specified type of idleness in milliseconds. */ long getIdleTimeInMillis(IdleStatus status); /** * Sets idle time for the specified type of idleness in seconds. */ void setIdleTime(IdleStatus status, int idleTime); /** * Returns idle time for {@link IdleStatus#READER_IDLE} in seconds. */ int getReaderIdleTime(); /** * Returns idle time for {@link IdleStatus#READER_IDLE} in milliseconds. */ long getReaderIdleTimeInMillis(); /** * Sets idle time for {@link IdleStatus#READER_IDLE} in seconds. */ void setReaderIdleTime(int idleTime); /** * Returns idle time for {@link IdleStatus#WRITER_IDLE} in seconds. */ int getWriterIdleTime(); /** * Returns idle time for {@link IdleStatus#WRITER_IDLE} in milliseconds. */ long getWriterIdleTimeInMillis(); /** * Sets idle time for {@link IdleStatus#WRITER_IDLE} in seconds. */ void setWriterIdleTime(int idleTime); /** * Returns idle time for {@link IdleStatus#BOTH_IDLE} in seconds. */ int getBothIdleTime(); /** * Returns idle time for {@link IdleStatus#BOTH_IDLE} in milliseconds. */ long getBothIdleTimeInMillis(); /** * Sets idle time for {@link IdleStatus#WRITER_IDLE} in seconds. */ void setBothIdleTime(int idleTime); /** * Returns write timeout in seconds. */ int getWriteTimeout(); /** * Returns write timeout in milliseconds. */ long getWriteTimeoutInMillis(); /** * Sets write timeout in seconds. */ void setWriteTimeout(int writeTimeout); /** * Returns true if and only if {@link IoSession#read()} operation * is enabled. If enabled, all received messages are stored in an internal * {@link BlockingQueue} so you can read received messages in more * convenient way for client applications. Enabling this option is not * useful to server applications and can cause unintended memory leak, and * therefore it's disabled by default. */ boolean isUseReadOperation(); /** * Enables or disabled {@link IoSession#read()} operation. If enabled, all * received messages are stored in an internal {@link BlockingQueue} so you * can read received messages in more convenient way for client * applications. Enabling this option is not useful to server applications * and can cause unintended memory leak, and therefore it's disabled by * default. */ void setUseReadOperation(boolean useReadOperation); /** * Sets all configuration properties retrieved from the specified * config. */ void setAll(IoSessionConfig config); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/IoSessionAttributeMap.java0000644000175000017500000001056612032276030032564 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; import java.util.Set; /** * Stores the user-defined attributes which is provided per {@link IoSession}. * All user-defined attribute accesses in {@link IoSession} are forwarded to * the instance of {@link IoSessionAttributeMap}. * * @author Apache MINA Project */ public interface IoSessionAttributeMap { /** * Returns the value of user defined attribute associated with the * specified key. If there's no such attribute, the specified default * value is associated with the specified key, and the default value is * returned. This method is same with the following code except that the * operation is performed atomically. *
     * if (containsAttribute(key)) {
     *     return getAttribute(key);
     * } else {
     *     setAttribute(key, defaultValue);
     *     return defaultValue;
     * }
     * 
*/ Object getAttribute(IoSession session, Object key, Object defaultValue); /** * Sets a user-defined attribute. * * @param key the key of the attribute * @param value the value of the attribute * @return The old value of the attribute. null if it is new. */ Object setAttribute(IoSession session, Object key, Object value); /** * Sets a user defined attribute if the attribute with the specified key * is not set yet. This method is same with the following code except * that the operation is performed atomically. *
     * if (containsAttribute(key)) {
     *     return getAttribute(key);
     * } else {
     *     return setAttribute(key, value);
     * }
     * 
*/ Object setAttributeIfAbsent(IoSession session, Object key, Object value); /** * Removes a user-defined attribute with the specified key. * * @return The old value of the attribute. null if not found. */ Object removeAttribute(IoSession session, Object key); /** * Removes a user defined attribute with the specified key if the current * attribute value is equal to the specified value. This method is same * with the following code except that the operation is performed * atomically. *
     * if (containsAttribute(key) && getAttribute(key).equals(value)) {
     *     removeAttribute(key);
     *     return true;
     * } else {
     *     return false;
     * }
     * 
*/ boolean removeAttribute(IoSession session, Object key, Object value); /** * Replaces a user defined attribute with the specified key if the * value of the attribute is equals to the specified old value. * This method is same with the following code except that the operation * is performed atomically. *
     * if (containsAttribute(key) && getAttribute(key).equals(oldValue)) {
     *     setAttribute(key, newValue);
     *     return true;
     * } else {
     *     return false;
     * }
     * 
*/ boolean replaceAttribute(IoSession session, Object key, Object oldValue, Object newValue); /** * Returns true if this session contains the attribute with * the specified key. */ boolean containsAttribute(IoSession session, Object key); /** * Returns the set of keys of all user-defined attributes. */ Set getAttributeKeys(IoSession session); /** * Disposes any releases associated with the specified session. * This method is invoked on disconnection. */ void dispose(IoSession session) throws Exception; } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/IoSessionDataStructureFactory.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/IoSessionDataStructureFact0000644000175000017500000000366112032276030032631 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; import java.util.Comparator; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.core.write.WriteRequestQueue; /** * Provides data structures to a newly created session. * * @author Apache MINA Project */ public interface IoSessionDataStructureFactory { /** * Returns an {@link IoSessionAttributeMap} which is going to be associated * with the specified session. Please note that the returned * implementation must be thread-safe. */ IoSessionAttributeMap getAttributeMap(IoSession session) throws Exception; /** * Returns an {@link WriteRequest} which is going to be associated with * the specified session. Please note that the returned * implementation must be thread-safe and robust enough to deal * with various messages types (even what you didn't expect at all), * especially when you are going to implement a priority queue which * involves {@link Comparator}. */ WriteRequestQueue getWriteRequestQueue(IoSession session) throws Exception; } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/IoEvent.java0000644000175000017500000000660012032276030027672 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; import org.apache.mina.core.write.WriteRequest; /** * An I/O event or an I/O request that MINA provides. * Most users won't need to use this class. It is usually used by internal * components to store I/O events. * * @author Apache MINA Project */ public class IoEvent implements Runnable { private final IoEventType type; private final IoSession session; private final Object parameter; public IoEvent(IoEventType type, IoSession session, Object parameter) { if (type == null) { throw new IllegalArgumentException("type"); } if (session == null) { throw new IllegalArgumentException("session"); } this.type = type; this.session = session; this.parameter = parameter; } public IoEventType getType() { return type; } public IoSession getSession() { return session; } public Object getParameter() { return parameter; } public void run() { fire(); } public void fire() { switch (getType()) { case MESSAGE_RECEIVED: getSession().getFilterChain().fireMessageReceived(getParameter()); break; case MESSAGE_SENT: getSession().getFilterChain().fireMessageSent((WriteRequest) getParameter()); break; case WRITE: getSession().getFilterChain().fireFilterWrite((WriteRequest) getParameter()); break; case CLOSE: getSession().getFilterChain().fireFilterClose(); break; case EXCEPTION_CAUGHT: getSession().getFilterChain().fireExceptionCaught((Throwable) getParameter()); break; case SESSION_IDLE: getSession().getFilterChain().fireSessionIdle((IdleStatus) getParameter()); break; case SESSION_OPENED: getSession().getFilterChain().fireSessionOpened(); break; case SESSION_CREATED: getSession().getFilterChain().fireSessionCreated(); break; case SESSION_CLOSED: getSession().getFilterChain().fireSessionClosed(); break; default: throw new IllegalArgumentException("Unknown event type: " + getType()); } } @Override public String toString() { if (getParameter() == null) { return "[" + getSession() + "] " + getType().name(); } return "[" + getSession() + "] " + getType().name() + ": " + getParameter(); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/IoSession.java0000644000175000017500000004641612032276030030245 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; import java.net.SocketAddress; import java.util.Set; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.future.CloseFuture; import org.apache.mina.core.future.ReadFuture; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoService; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.core.write.WriteRequestQueue; /** * A handle which represents connection between two end-points regardless of * transport types. *

* {@link IoSession} provides user-defined attributes. User-defined attributes * are application-specific data which are associated with a session. * It often contains objects that represents the state of a higher-level protocol * and becomes a way to exchange data between filters and handlers. *

*

Adjusting Transport Type Specific Properties

*

* You can simply downcast the session to an appropriate subclass. *

*

*

Thread Safety

*

* {@link IoSession} is thread-safe. But please note that performing * more than one {@link #write(Object)} calls at the same time will * cause the {@link IoFilter#filterWrite(IoFilter.NextFilter,IoSession,WriteRequest)} * to be executed simultaneously, and therefore you have to make sure the * {@link IoFilter} implementations you're using are thread-safe, too. *

*

*

Equality of Sessions

* TODO : The getId() method is totally wrong. We can't base * a method which is designed to create a unique ID on the hashCode method. * {@link #equals(Object)} and {@link #hashCode()} shall not be overriden * to the default behavior that is defined in {@link Object}. * * @author Apache MINA Project */ public interface IoSession { /** * @return a unique identifier for this session. Every session has its own * ID which is different from each other. * * TODO : The way it's implemented does not guarantee that the contract is * respected. It uses the HashCode() method which don't guarantee the key * unicity. */ long getId(); /** * @return the {@link IoService} which provides I/O service to this session. */ IoService getService(); /** * @return the {@link IoHandler} which handles this session. */ IoHandler getHandler(); /** * @return the configuration of this session. */ IoSessionConfig getConfig(); /** * @return the filter chain that only affects this session. */ IoFilterChain getFilterChain(); /** * TODO Add method documentation */ WriteRequestQueue getWriteRequestQueue(); /** * @return the {@link TransportMetadata} that this session runs on. */ TransportMetadata getTransportMetadata(); /** * TODO This javadoc is wrong. The return tag should be short. * * @return a {@link ReadFuture} which is notified when a new message is * received, the connection is closed or an exception is caught. This * operation is especially useful when you implement a client application. * TODO : Describe here how we enable this feature. * However, please note that this operation is disabled by default and * throw {@link IllegalStateException} because all received events must be * queued somewhere to support this operation, possibly leading to memory * leak. This means you have to keep calling {@link #read()} once you * enabled this operation. To enable this operation, please call * {@link IoSessionConfig#setUseReadOperation(boolean)} with true. * * @throws IllegalStateException if * {@link IoSessionConfig#setUseReadOperation(boolean) useReadOperation} * option has not been enabled. */ ReadFuture read(); /** * Writes the specified message to remote peer. This * operation is asynchronous; {@link IoHandler#messageSent(IoSession,Object)} * will be invoked when the message is actually sent to remote peer. * You can also wait for the returned {@link WriteFuture} if you want * to wait for the message actually written. */ WriteFuture write(Object message); /** * (Optional) Writes the specified message to the specified destination. * This operation is asynchronous; {@link IoHandler#messageSent(IoSession, Object)} * will be invoked when the message is actually sent to remote peer. You can * also wait for the returned {@link WriteFuture} if you want to wait for * the message actually written. *

* When you implement a client that receives a broadcast message from a server * such as DHCP server, the client might need to send a response message for the * broadcast message the server sent. Because the remote address of the session * is not the address of the server in case of broadcasting, there should be a * way to specify the destination when you write the response message. * This interface provides {@link #write(Object, SocketAddress)} method so you * can specify the destination. * * @param destination null if you want the message sent to the * default remote address * * @throws UnsupportedOperationException if this operation is not supported */ WriteFuture write(Object message, SocketAddress destination); /** * Closes this session immediately or after all queued write requests * are flushed. This operation is asynchronous. Wait for the returned * {@link CloseFuture} if you want to wait for the session actually closed. * * @param immediately {@code true} to close this session immediately * (i.e. {@link #close()}). The pending write requests * will simply be discarded. * {@code false} to close this session after all queued * write requests are flushed (i.e. {@link #closeOnFlush()}). */ CloseFuture close(boolean immediately); /** * Closes this session after all queued write requests * are flushed. This operation is asynchronous. Wait for the returned * {@link CloseFuture} if you want to wait for the session actually closed. * @deprecated use {@link IoSession#close(boolean)} */ @Deprecated CloseFuture close(); /** * Returns an attachment of this session. * This method is identical with getAttribute( "" ). * * @deprecated Use {@link #getAttribute(Object)} instead. */ @Deprecated Object getAttachment(); /** * Sets an attachment of this session. * This method is identical with setAttribute( "", attachment ). * * @return Old attachment. null if it is new. * @deprecated Use {@link #setAttribute(Object, Object)} instead. */ @Deprecated Object setAttachment(Object attachment); /** * Returns the value of the user-defined attribute of this session. * * @param key the key of the attribute * @return null if there is no attribute with the specified key */ Object getAttribute(Object key); /** * Returns the value of user defined attribute associated with the * specified key. If there's no such attribute, the specified default * value is associated with the specified key, and the default value is * returned. This method is same with the following code except that the * operation is performed atomically. *

     * if (containsAttribute(key)) {
     *     return getAttribute(key);
     * } else {
     *     setAttribute(key, defaultValue);
     *     return defaultValue;
     * }
     * 
*/ Object getAttribute(Object key, Object defaultValue); /** * Sets a user-defined attribute. * * @param key the key of the attribute * @param value the value of the attribute * @return The old value of the attribute. null if it is new. */ Object setAttribute(Object key, Object value); /** * Sets a user defined attribute without a value. This is useful when * you just want to put a 'mark' attribute. Its value is set to * {@link Boolean#TRUE}. * * @param key the key of the attribute * @return The old value of the attribute. null if it is new. */ Object setAttribute(Object key); /** * Sets a user defined attribute if the attribute with the specified key * is not set yet. This method is same with the following code except * that the operation is performed atomically. *
     * if (containsAttribute(key)) {
     *     return getAttribute(key);
     * } else {
     *     return setAttribute(key, value);
     * }
     * 
*/ Object setAttributeIfAbsent(Object key, Object value); /** * Sets a user defined attribute without a value if the attribute with * the specified key is not set yet. This is useful when you just want to * put a 'mark' attribute. Its value is set to {@link Boolean#TRUE}. * This method is same with the following code except that the operation * is performed atomically. *
     * if (containsAttribute(key)) {
     *     return getAttribute(key);  // might not always be Boolean.TRUE.
     * } else {
     *     return setAttribute(key);
     * }
     * 
*/ Object setAttributeIfAbsent(Object key); /** * Removes a user-defined attribute with the specified key. * * @return The old value of the attribute. null if not found. */ Object removeAttribute(Object key); /** * Removes a user defined attribute with the specified key if the current * attribute value is equal to the specified value. This method is same * with the following code except that the operation is performed * atomically. *
     * if (containsAttribute(key) && getAttribute(key).equals(value)) {
     *     removeAttribute(key);
     *     return true;
     * } else {
     *     return false;
     * }
     * 
*/ boolean removeAttribute(Object key, Object value); /** * Replaces a user defined attribute with the specified key if the * value of the attribute is equals to the specified old value. * This method is same with the following code except that the operation * is performed atomically. *
     * if (containsAttribute(key) && getAttribute(key).equals(oldValue)) {
     *     setAttribute(key, newValue);
     *     return true;
     * } else {
     *     return false;
     * }
     * 
*/ boolean replaceAttribute(Object key, Object oldValue, Object newValue); /** * Returns true if this session contains the attribute with * the specified key. */ boolean containsAttribute(Object key); /** * Returns the set of keys of all user-defined attributes. */ Set getAttributeKeys(); /** * Returns true if this session is connected with remote peer. */ boolean isConnected(); /** * Returns true if and only if this session is being closed * (but not disconnected yet) or is closed. */ boolean isClosing(); /** * Returns the {@link CloseFuture} of this session. This method returns * the same instance whenever user calls it. */ CloseFuture getCloseFuture(); /** * Returns the socket address of remote peer. */ SocketAddress getRemoteAddress(); /** * Returns the socket address of local machine which is associated with this * session. */ SocketAddress getLocalAddress(); /** * Returns the socket address of the {@link IoService} listens to to manage * this session. If this session is managed by {@link IoAcceptor}, it * returns the {@link SocketAddress} which is specified as a parameter of * {@link IoAcceptor#bind()}. If this session is managed by * {@link IoConnector}, this method returns the same address with * that of {@link #getRemoteAddress()}. */ SocketAddress getServiceAddress(); /** * * TODO setWriteRequestQueue. * * @param writeRequestQueue */ void setCurrentWriteRequest(WriteRequest currentWriteRequest); /** * Suspends read operations for this session. */ void suspendRead(); /** * Suspends write operations for this session. */ void suspendWrite(); /** * Resumes read operations for this session. */ void resumeRead(); /** * Resumes write operations for this session. */ void resumeWrite(); /** * Is read operation is suspended for this session. * @return true if suspended */ boolean isReadSuspended(); /** * Is write operation is suspended for this session. * @return true if suspended */ boolean isWriteSuspended(); /** * Update all statistical properties related with throughput assuming * the specified time is the current time. By default this method returns * silently without updating the throughput properties if they were * calculated already within last * {@link IoSessionConfig#getThroughputCalculationInterval() calculation interval}. * If, however, force is specified as true, this method * updates the throughput properties immediately. * @param currentTime the current time in milliseconds */ void updateThroughput(long currentTime, boolean force); /** * Returns the total number of bytes which were read from this session. */ long getReadBytes(); /** * Returns the total number of bytes which were written to this session. */ long getWrittenBytes(); /** * Returns the total number of messages which were read and decoded from this session. */ long getReadMessages(); /** * Returns the total number of messages which were written and encoded by this session. */ long getWrittenMessages(); /** * Returns the number of read bytes per second. */ double getReadBytesThroughput(); /** * Returns the number of written bytes per second. */ double getWrittenBytesThroughput(); /** * Returns the number of read messages per second. */ double getReadMessagesThroughput(); /** * Returns the number of written messages per second. */ double getWrittenMessagesThroughput(); /** * Returns the number of messages which are scheduled to be written to this session. */ int getScheduledWriteMessages(); /** * Returns the number of bytes which are scheduled to be written to this * session. */ long getScheduledWriteBytes(); /** * Returns the message which is being written by {@link IoService}. * @return null if and if only no message is being written */ Object getCurrentWriteMessage(); /** * Returns the {@link WriteRequest} which is being processed by * {@link IoService}. * * @return null if and if only no message is being written */ WriteRequest getCurrentWriteRequest(); /** * @return the session's creation time in milliseconds */ long getCreationTime(); /** * Returns the time in millis when I/O occurred lastly. */ long getLastIoTime(); /** * Returns the time in millis when read operation occurred lastly. */ long getLastReadTime(); /** * Returns the time in millis when write operation occurred lastly. */ long getLastWriteTime(); /** * Returns true if this session is idle for the specified * {@link IdleStatus}. */ boolean isIdle(IdleStatus status); /** * Returns true if this session is {@link IdleStatus#READER_IDLE}. * @see #isIdle(IdleStatus) */ boolean isReaderIdle(); /** * Returns true if this session is {@link IdleStatus#WRITER_IDLE}. * @see #isIdle(IdleStatus) */ boolean isWriterIdle(); /** * Returns true if this session is {@link IdleStatus#BOTH_IDLE}. * @see #isIdle(IdleStatus) */ boolean isBothIdle(); /** * Returns the number of the fired continuous sessionIdle events * for the specified {@link IdleStatus}. *

* If sessionIdle event is fired first after some time after I/O, * idleCount becomes 1. idleCount resets to * 0 if any I/O occurs again, otherwise it increases to * 2 and so on if sessionIdle event is fired again without * any I/O between two (or more) sessionIdle events. */ int getIdleCount(IdleStatus status); /** * Returns the number of the fired continuous sessionIdle events * for {@link IdleStatus#READER_IDLE}. * @see #getIdleCount(IdleStatus) */ int getReaderIdleCount(); /** * Returns the number of the fired continuous sessionIdle events * for {@link IdleStatus#WRITER_IDLE}. * @see #getIdleCount(IdleStatus) */ int getWriterIdleCount(); /** * Returns the number of the fired continuous sessionIdle events * for {@link IdleStatus#BOTH_IDLE}. * @see #getIdleCount(IdleStatus) */ int getBothIdleCount(); /** * Returns the time in milliseconds when the last sessionIdle event * is fired for the specified {@link IdleStatus}. */ long getLastIdleTime(IdleStatus status); /** * Returns the time in milliseconds when the last sessionIdle event * is fired for {@link IdleStatus#READER_IDLE}. * @see #getLastIdleTime(IdleStatus) */ long getLastReaderIdleTime(); /** * Returns the time in milliseconds when the last sessionIdle event * is fired for {@link IdleStatus#WRITER_IDLE}. * @see #getLastIdleTime(IdleStatus) */ long getLastWriterIdleTime(); /** * Returns the time in milliseconds when the last sessionIdle event * is fired for {@link IdleStatus#BOTH_IDLE}. * @see #getLastIdleTime(IdleStatus) */ long getLastBothIdleTime(); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/AbstractIoSession.java0000644000175000017500000011514612032276030031726 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.SocketAddress; import java.nio.channels.FileChannel; import java.util.Iterator; import java.util.Queue; import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.file.DefaultFileRegion; import org.apache.mina.core.file.FilenameFileRegion; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.future.CloseFuture; import org.apache.mina.core.future.DefaultCloseFuture; import org.apache.mina.core.future.DefaultReadFuture; import org.apache.mina.core.future.DefaultWriteFuture; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.future.ReadFuture; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.service.AbstractIoService; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.IoService; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.core.write.DefaultWriteRequest; import org.apache.mina.core.write.WriteException; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.core.write.WriteRequestQueue; import org.apache.mina.core.write.WriteTimeoutException; import org.apache.mina.core.write.WriteToClosedSessionException; import org.apache.mina.util.ExceptionMonitor; /** * Base implementation of {@link IoSession}. * * @author Apache MINA Project */ public abstract class AbstractIoSession implements IoSession { /** The associated handler */ private final IoHandler handler; /** The session config */ protected IoSessionConfig config; /** The service which will manage this session */ private final IoService service; private static final AttributeKey READY_READ_FUTURES_KEY = new AttributeKey(AbstractIoSession.class, "readyReadFutures"); private static final AttributeKey WAITING_READ_FUTURES_KEY = new AttributeKey(AbstractIoSession.class, "waitingReadFutures"); private static final IoFutureListener SCHEDULED_COUNTER_RESETTER = new IoFutureListener() { public void operationComplete(CloseFuture future) { AbstractIoSession session = (AbstractIoSession) future.getSession(); session.scheduledWriteBytes.set(0); session.scheduledWriteMessages.set(0); session.readBytesThroughput = 0; session.readMessagesThroughput = 0; session.writtenBytesThroughput = 0; session.writtenMessagesThroughput = 0; } }; /** * An internal write request object that triggers session close. * * @see #writeRequestQueue */ private static final WriteRequest CLOSE_REQUEST = new DefaultWriteRequest(new Object()); private final Object lock = new Object(); private IoSessionAttributeMap attributes; private WriteRequestQueue writeRequestQueue; private WriteRequest currentWriteRequest; /** The Session creation's time */ private final long creationTime; /** An id generator guaranteed to generate unique IDs for the session */ private static AtomicLong idGenerator = new AtomicLong(0); /** The session ID */ private long sessionId; /** * A future that will be set 'closed' when the connection is closed. */ private final CloseFuture closeFuture = new DefaultCloseFuture(this); private volatile boolean closing; // traffic control private boolean readSuspended = false; private boolean writeSuspended = false; // Status variables private final AtomicBoolean scheduledForFlush = new AtomicBoolean(); private final AtomicInteger scheduledWriteBytes = new AtomicInteger(); private final AtomicInteger scheduledWriteMessages = new AtomicInteger(); private long readBytes; private long writtenBytes; private long readMessages; private long writtenMessages; private long lastReadTime; private long lastWriteTime; private long lastThroughputCalculationTime; private long lastReadBytes; private long lastWrittenBytes; private long lastReadMessages; private long lastWrittenMessages; private double readBytesThroughput; private double writtenBytesThroughput; private double readMessagesThroughput; private double writtenMessagesThroughput; private AtomicInteger idleCountForBoth = new AtomicInteger(); private AtomicInteger idleCountForRead = new AtomicInteger(); private AtomicInteger idleCountForWrite = new AtomicInteger(); private long lastIdleTimeForBoth; private long lastIdleTimeForRead; private long lastIdleTimeForWrite; private boolean deferDecreaseReadBuffer = true; /** * TODO Add method documentation */ protected AbstractIoSession(IoService service) { this.service = service; this.handler = service.getHandler(); // Initialize all the Session counters to the current time long currentTime = System.currentTimeMillis(); creationTime = currentTime; lastThroughputCalculationTime = currentTime; lastReadTime = currentTime; lastWriteTime = currentTime; lastIdleTimeForBoth = currentTime; lastIdleTimeForRead = currentTime; lastIdleTimeForWrite = currentTime; // TODO add documentation closeFuture.addListener(SCHEDULED_COUNTER_RESETTER); // Set a new ID for this session sessionId = idGenerator.incrementAndGet(); } /** * {@inheritDoc} * * We use an AtomicLong to guarantee that the session ID are unique. */ public final long getId() { return sessionId; } /** * @return The associated IoProcessor for this session */ public abstract IoProcessor getProcessor(); /** * {@inheritDoc} */ public final boolean isConnected() { return !closeFuture.isClosed(); } /** * {@inheritDoc} */ public final boolean isClosing() { return closing || closeFuture.isClosed(); } /** * {@inheritDoc} */ public final CloseFuture getCloseFuture() { return closeFuture; } /** * Tells if the session is scheduled for flushed * * @param true if the session is scheduled for flush */ public final boolean isScheduledForFlush() { return scheduledForFlush.get(); } /** * Schedule the session for flushed */ public final void scheduledForFlush() { scheduledForFlush.set(true); } /** * Change the session's status : it's not anymore scheduled for flush */ public final void unscheduledForFlush() { scheduledForFlush.set(false); } /** * Set the scheduledForFLush flag. As we may have concurrent access to this * flag, we compare and set it in one call. * * @param schedule * the new value to set if not already set. * @return true if the session flag has been set, and if it wasn't set * already. */ public final boolean setScheduledForFlush(boolean schedule) { if (schedule) { // If the current tag is set to false, switch it to true, // otherwise, we do nothing but return false : the session // is already scheduled for flush return scheduledForFlush.compareAndSet(false, schedule); } scheduledForFlush.set(schedule); return true; } /** * {@inheritDoc} */ public final CloseFuture close(boolean rightNow) { if (!isClosing()) { if (rightNow) { return close(); } return closeOnFlush(); } else { return closeFuture; } } /** * {@inheritDoc} */ public final CloseFuture close() { synchronized (lock) { if (isClosing()) { return closeFuture; } closing = true; } getFilterChain().fireFilterClose(); return closeFuture; } private final CloseFuture closeOnFlush() { getWriteRequestQueue().offer(this, CLOSE_REQUEST); getProcessor().flush(this); return closeFuture; } /** * {@inheritDoc} */ public IoHandler getHandler() { return handler; } /** * {@inheritDoc} */ public IoSessionConfig getConfig() { return config; } /** * {@inheritDoc} */ public final ReadFuture read() { if (!getConfig().isUseReadOperation()) { throw new IllegalStateException("useReadOperation is not enabled."); } Queue readyReadFutures = getReadyReadFutures(); ReadFuture future; synchronized (readyReadFutures) { future = readyReadFutures.poll(); if (future != null) { if (future.isClosed()) { // Let other readers get notified. readyReadFutures.offer(future); } } else { future = new DefaultReadFuture(this); getWaitingReadFutures().offer(future); } } return future; } /** * TODO Add method documentation */ public final void offerReadFuture(Object message) { newReadFuture().setRead(message); } /** * TODO Add method documentation */ public final void offerFailedReadFuture(Throwable exception) { newReadFuture().setException(exception); } /** * TODO Add method documentation */ public final void offerClosedReadFuture() { Queue readyReadFutures = getReadyReadFutures(); synchronized (readyReadFutures) { newReadFuture().setClosed(); } } /** * TODO Add method documentation */ private ReadFuture newReadFuture() { Queue readyReadFutures = getReadyReadFutures(); Queue waitingReadFutures = getWaitingReadFutures(); ReadFuture future; synchronized (readyReadFutures) { future = waitingReadFutures.poll(); if (future == null) { future = new DefaultReadFuture(this); readyReadFutures.offer(future); } } return future; } /** * TODO Add method documentation */ private Queue getReadyReadFutures() { Queue readyReadFutures = (Queue) getAttribute(READY_READ_FUTURES_KEY); if (readyReadFutures == null) { readyReadFutures = new ConcurrentLinkedQueue(); Queue oldReadyReadFutures = (Queue) setAttributeIfAbsent(READY_READ_FUTURES_KEY, readyReadFutures); if (oldReadyReadFutures != null) { readyReadFutures = oldReadyReadFutures; } } return readyReadFutures; } /** * TODO Add method documentation */ private Queue getWaitingReadFutures() { Queue waitingReadyReadFutures = (Queue) getAttribute(WAITING_READ_FUTURES_KEY); if (waitingReadyReadFutures == null) { waitingReadyReadFutures = new ConcurrentLinkedQueue(); Queue oldWaitingReadyReadFutures = (Queue) setAttributeIfAbsent( WAITING_READ_FUTURES_KEY, waitingReadyReadFutures); if (oldWaitingReadyReadFutures != null) { waitingReadyReadFutures = oldWaitingReadyReadFutures; } } return waitingReadyReadFutures; } /** * {@inheritDoc} */ public WriteFuture write(Object message) { return write(message, null); } /** * {@inheritDoc} */ public WriteFuture write(Object message, SocketAddress remoteAddress) { if (message == null) { throw new IllegalArgumentException("Trying to write a null message : not allowed"); } // We can't send a message to a connected session if we don't have // the remote address if (!getTransportMetadata().isConnectionless() && (remoteAddress != null)) { throw new UnsupportedOperationException(); } // If the session has been closed or is closing, we can't either // send a message to the remote side. We generate a future // containing an exception. if (isClosing() || !isConnected()) { WriteFuture future = new DefaultWriteFuture(this); WriteRequest request = new DefaultWriteRequest(message, future, remoteAddress); WriteException writeException = new WriteToClosedSessionException(request); future.setException(writeException); return future; } FileChannel openedFileChannel = null; // TODO: remove this code as soon as we use InputStream // instead of Object for the message. try { if ((message instanceof IoBuffer) && !((IoBuffer) message).hasRemaining()) { // Nothing to write : probably an error in the user code throw new IllegalArgumentException("message is empty. Forgot to call flip()?"); } else if (message instanceof FileChannel) { FileChannel fileChannel = (FileChannel) message; message = new DefaultFileRegion(fileChannel, 0, fileChannel.size()); } else if (message instanceof File) { File file = (File) message; openedFileChannel = new FileInputStream(file).getChannel(); message = new FilenameFileRegion(file, openedFileChannel, 0, openedFileChannel.size()); } } catch (IOException e) { ExceptionMonitor.getInstance().exceptionCaught(e); return DefaultWriteFuture.newNotWrittenFuture(this, e); } // Now, we can write the message. First, create a future WriteFuture writeFuture = new DefaultWriteFuture(this); WriteRequest writeRequest = new DefaultWriteRequest(message, writeFuture, remoteAddress); // Then, get the chain and inject the WriteRequest into it IoFilterChain filterChain = getFilterChain(); filterChain.fireFilterWrite(writeRequest); // TODO : This is not our business ! The caller has created a // FileChannel, // he has to close it ! if (openedFileChannel != null) { // If we opened a FileChannel, it needs to be closed when the write // has completed final FileChannel finalChannel = openedFileChannel; writeFuture.addListener(new IoFutureListener() { public void operationComplete(WriteFuture future) { try { finalChannel.close(); } catch (IOException e) { ExceptionMonitor.getInstance().exceptionCaught(e); } } }); } // Return the WriteFuture. return writeFuture; } /** * {@inheritDoc} */ public final Object getAttachment() { return getAttribute(""); } /** * {@inheritDoc} */ public final Object setAttachment(Object attachment) { return setAttribute("", attachment); } /** * {@inheritDoc} */ public final Object getAttribute(Object key) { return getAttribute(key, null); } /** * {@inheritDoc} */ public final Object getAttribute(Object key, Object defaultValue) { return attributes.getAttribute(this, key, defaultValue); } /** * {@inheritDoc} */ public final Object setAttribute(Object key, Object value) { return attributes.setAttribute(this, key, value); } /** * {@inheritDoc} */ public final Object setAttribute(Object key) { return setAttribute(key, Boolean.TRUE); } /** * {@inheritDoc} */ public final Object setAttributeIfAbsent(Object key, Object value) { return attributes.setAttributeIfAbsent(this, key, value); } /** * {@inheritDoc} */ public final Object setAttributeIfAbsent(Object key) { return setAttributeIfAbsent(key, Boolean.TRUE); } /** * {@inheritDoc} */ public final Object removeAttribute(Object key) { return attributes.removeAttribute(this, key); } /** * {@inheritDoc} */ public final boolean removeAttribute(Object key, Object value) { return attributes.removeAttribute(this, key, value); } /** * {@inheritDoc} */ public final boolean replaceAttribute(Object key, Object oldValue, Object newValue) { return attributes.replaceAttribute(this, key, oldValue, newValue); } /** * {@inheritDoc} */ public final boolean containsAttribute(Object key) { return attributes.containsAttribute(this, key); } /** * {@inheritDoc} */ public final Set getAttributeKeys() { return attributes.getAttributeKeys(this); } /** * TODO Add method documentation */ public final IoSessionAttributeMap getAttributeMap() { return attributes; } /** * TODO Add method documentation */ public final void setAttributeMap(IoSessionAttributeMap attributes) { this.attributes = attributes; } /** * Create a new close aware write queue, based on the given write queue. * * @param writeRequestQueue * The write request queue */ public final void setWriteRequestQueue(WriteRequestQueue writeRequestQueue) { this.writeRequestQueue = new CloseAwareWriteQueue(writeRequestQueue); } /** * {@inheritDoc} */ public final void suspendRead() { readSuspended = true; if (isClosing() || !isConnected()) { return; } getProcessor().updateTrafficControl(this); } /** * {@inheritDoc} */ public final void suspendWrite() { writeSuspended = true; if (isClosing() || !isConnected()) { return; } getProcessor().updateTrafficControl(this); } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") public final void resumeRead() { readSuspended = false; if (isClosing() || !isConnected()) { return; } getProcessor().updateTrafficControl(this); } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") public final void resumeWrite() { writeSuspended = false; if (isClosing() || !isConnected()) { return; } getProcessor().updateTrafficControl(this); } /** * {@inheritDoc} */ public boolean isReadSuspended() { return readSuspended; } /** * {@inheritDoc} */ public boolean isWriteSuspended() { return writeSuspended; } /** * {@inheritDoc} */ public final long getReadBytes() { return readBytes; } /** * {@inheritDoc} */ public final long getWrittenBytes() { return writtenBytes; } /** * {@inheritDoc} */ public final long getReadMessages() { return readMessages; } /** * {@inheritDoc} */ public final long getWrittenMessages() { return writtenMessages; } /** * {@inheritDoc} */ public final double getReadBytesThroughput() { return readBytesThroughput; } /** * {@inheritDoc} */ public final double getWrittenBytesThroughput() { return writtenBytesThroughput; } /** * {@inheritDoc} */ public final double getReadMessagesThroughput() { return readMessagesThroughput; } /** * {@inheritDoc} */ public final double getWrittenMessagesThroughput() { return writtenMessagesThroughput; } /** * {@inheritDoc} */ public final void updateThroughput(long currentTime, boolean force) { int interval = (int) (currentTime - lastThroughputCalculationTime); long minInterval = getConfig().getThroughputCalculationIntervalInMillis(); if ((minInterval == 0) || (interval < minInterval)) { if (!force) { return; } } readBytesThroughput = (readBytes - lastReadBytes) * 1000.0 / interval; writtenBytesThroughput = (writtenBytes - lastWrittenBytes) * 1000.0 / interval; readMessagesThroughput = (readMessages - lastReadMessages) * 1000.0 / interval; writtenMessagesThroughput = (writtenMessages - lastWrittenMessages) * 1000.0 / interval; lastReadBytes = readBytes; lastWrittenBytes = writtenBytes; lastReadMessages = readMessages; lastWrittenMessages = writtenMessages; lastThroughputCalculationTime = currentTime; } /** * {@inheritDoc} */ public final long getScheduledWriteBytes() { return scheduledWriteBytes.get(); } /** * {@inheritDoc} */ public final int getScheduledWriteMessages() { return scheduledWriteMessages.get(); } /** * TODO Add method documentation */ protected void setScheduledWriteBytes(int byteCount) { scheduledWriteBytes.set(byteCount); } /** * TODO Add method documentation */ protected void setScheduledWriteMessages(int messages) { scheduledWriteMessages.set(messages); } /** * TODO Add method documentation */ public final void increaseReadBytes(long increment, long currentTime) { if (increment <= 0) { return; } readBytes += increment; lastReadTime = currentTime; idleCountForBoth.set(0); idleCountForRead.set(0); if (getService() instanceof AbstractIoService) { ((AbstractIoService) getService()).getStatistics().increaseReadBytes(increment, currentTime); } } /** * TODO Add method documentation */ public final void increaseReadMessages(long currentTime) { readMessages++; lastReadTime = currentTime; idleCountForBoth.set(0); idleCountForRead.set(0); if (getService() instanceof AbstractIoService) { ((AbstractIoService) getService()).getStatistics().increaseReadMessages(currentTime); } } /** * TODO Add method documentation */ public final void increaseWrittenBytes(int increment, long currentTime) { if (increment <= 0) { return; } writtenBytes += increment; lastWriteTime = currentTime; idleCountForBoth.set(0); idleCountForWrite.set(0); if (getService() instanceof AbstractIoService) { ((AbstractIoService) getService()).getStatistics().increaseWrittenBytes(increment, currentTime); } increaseScheduledWriteBytes(-increment); } /** * TODO Add method documentation */ public final void increaseWrittenMessages(WriteRequest request, long currentTime) { Object message = request.getMessage(); if (message instanceof IoBuffer) { IoBuffer b = (IoBuffer) message; if (b.hasRemaining()) { return; } } writtenMessages++; lastWriteTime = currentTime; if (getService() instanceof AbstractIoService) { ((AbstractIoService) getService()).getStatistics().increaseWrittenMessages(currentTime); } decreaseScheduledWriteMessages(); } /** * TODO Add method documentation */ public final void increaseScheduledWriteBytes(int increment) { scheduledWriteBytes.addAndGet(increment); if (getService() instanceof AbstractIoService) { ((AbstractIoService) getService()).getStatistics().increaseScheduledWriteBytes(increment); } } /** * TODO Add method documentation */ public final void increaseScheduledWriteMessages() { scheduledWriteMessages.incrementAndGet(); if (getService() instanceof AbstractIoService) { ((AbstractIoService) getService()).getStatistics().increaseScheduledWriteMessages(); } } /** * TODO Add method documentation */ private void decreaseScheduledWriteMessages() { scheduledWriteMessages.decrementAndGet(); if (getService() instanceof AbstractIoService) { ((AbstractIoService) getService()).getStatistics().decreaseScheduledWriteMessages(); } } /** * TODO Add method documentation */ public final void decreaseScheduledBytesAndMessages(WriteRequest request) { Object message = request.getMessage(); if (message instanceof IoBuffer) { IoBuffer b = (IoBuffer) message; if (b.hasRemaining()) { increaseScheduledWriteBytes(-((IoBuffer) message).remaining()); } else { decreaseScheduledWriteMessages(); } } else { decreaseScheduledWriteMessages(); } } /** * {@inheritDoc} */ public final WriteRequestQueue getWriteRequestQueue() { if (writeRequestQueue == null) { throw new IllegalStateException(); } return writeRequestQueue; } /** * {@inheritDoc} */ public final WriteRequest getCurrentWriteRequest() { return currentWriteRequest; } /** * {@inheritDoc} */ public final Object getCurrentWriteMessage() { WriteRequest req = getCurrentWriteRequest(); if (req == null) { return null; } return req.getMessage(); } /** * {@inheritDoc} */ public final void setCurrentWriteRequest(WriteRequest currentWriteRequest) { this.currentWriteRequest = currentWriteRequest; } /** * TODO Add method documentation */ public final void increaseReadBufferSize() { int newReadBufferSize = getConfig().getReadBufferSize() << 1; if (newReadBufferSize <= getConfig().getMaxReadBufferSize()) { getConfig().setReadBufferSize(newReadBufferSize); } else { getConfig().setReadBufferSize(getConfig().getMaxReadBufferSize()); } deferDecreaseReadBuffer = true; } /** * TODO Add method documentation */ public final void decreaseReadBufferSize() { if (deferDecreaseReadBuffer) { deferDecreaseReadBuffer = false; return; } if (getConfig().getReadBufferSize() > getConfig().getMinReadBufferSize()) { getConfig().setReadBufferSize(getConfig().getReadBufferSize() >>> 1); } deferDecreaseReadBuffer = true; } /** * {@inheritDoc} */ public final long getCreationTime() { return creationTime; } /** * {@inheritDoc} */ public final long getLastIoTime() { return Math.max(lastReadTime, lastWriteTime); } /** * {@inheritDoc} */ public final long getLastReadTime() { return lastReadTime; } /** * {@inheritDoc} */ public final long getLastWriteTime() { return lastWriteTime; } /** * {@inheritDoc} */ public final boolean isIdle(IdleStatus status) { if (status == IdleStatus.BOTH_IDLE) { return idleCountForBoth.get() > 0; } if (status == IdleStatus.READER_IDLE) { return idleCountForRead.get() > 0; } if (status == IdleStatus.WRITER_IDLE) { return idleCountForWrite.get() > 0; } throw new IllegalArgumentException("Unknown idle status: " + status); } /** * {@inheritDoc} */ public final boolean isBothIdle() { return isIdle(IdleStatus.BOTH_IDLE); } /** * {@inheritDoc} */ public final boolean isReaderIdle() { return isIdle(IdleStatus.READER_IDLE); } /** * {@inheritDoc} */ public final boolean isWriterIdle() { return isIdle(IdleStatus.WRITER_IDLE); } /** * {@inheritDoc} */ public final int getIdleCount(IdleStatus status) { if (getConfig().getIdleTime(status) == 0) { if (status == IdleStatus.BOTH_IDLE) { idleCountForBoth.set(0); } if (status == IdleStatus.READER_IDLE) { idleCountForRead.set(0); } if (status == IdleStatus.WRITER_IDLE) { idleCountForWrite.set(0); } } if (status == IdleStatus.BOTH_IDLE) { return idleCountForBoth.get(); } if (status == IdleStatus.READER_IDLE) { return idleCountForRead.get(); } if (status == IdleStatus.WRITER_IDLE) { return idleCountForWrite.get(); } throw new IllegalArgumentException("Unknown idle status: " + status); } /** * {@inheritDoc} */ public final long getLastIdleTime(IdleStatus status) { if (status == IdleStatus.BOTH_IDLE) { return lastIdleTimeForBoth; } if (status == IdleStatus.READER_IDLE) { return lastIdleTimeForRead; } if (status == IdleStatus.WRITER_IDLE) { return lastIdleTimeForWrite; } throw new IllegalArgumentException("Unknown idle status: " + status); } /** * TODO Add method documentation */ public final void increaseIdleCount(IdleStatus status, long currentTime) { if (status == IdleStatus.BOTH_IDLE) { idleCountForBoth.incrementAndGet(); lastIdleTimeForBoth = currentTime; } else if (status == IdleStatus.READER_IDLE) { idleCountForRead.incrementAndGet(); lastIdleTimeForRead = currentTime; } else if (status == IdleStatus.WRITER_IDLE) { idleCountForWrite.incrementAndGet(); lastIdleTimeForWrite = currentTime; } else { throw new IllegalArgumentException("Unknown idle status: " + status); } } /** * {@inheritDoc} */ public final int getBothIdleCount() { return getIdleCount(IdleStatus.BOTH_IDLE); } /** * {@inheritDoc} */ public final long getLastBothIdleTime() { return getLastIdleTime(IdleStatus.BOTH_IDLE); } /** * {@inheritDoc} */ public final long getLastReaderIdleTime() { return getLastIdleTime(IdleStatus.READER_IDLE); } /** * {@inheritDoc} */ public final long getLastWriterIdleTime() { return getLastIdleTime(IdleStatus.WRITER_IDLE); } /** * {@inheritDoc} */ public final int getReaderIdleCount() { return getIdleCount(IdleStatus.READER_IDLE); } /** * {@inheritDoc} */ public final int getWriterIdleCount() { return getIdleCount(IdleStatus.WRITER_IDLE); } /** * {@inheritDoc} */ public SocketAddress getServiceAddress() { IoService service = getService(); if (service instanceof IoAcceptor) { return ((IoAcceptor) service).getLocalAddress(); } return getRemoteAddress(); } /** * {@inheritDoc} */ @Override public final int hashCode() { return super.hashCode(); } /** * {@inheritDoc} TODO This is a ridiculous implementation. Need to be * replaced. */ @Override public final boolean equals(Object o) { return super.equals(o); } /** * {@inheritDoc} */ @Override public String toString() { if (isConnected() || isClosing()) { String remote = null; String local = null; try { remote = String.valueOf(getRemoteAddress()); } catch (Throwable t) { remote = "Cannot get the remote address informations: " + t.getMessage(); } try { local = String.valueOf(getLocalAddress()); } catch (Throwable t) { local = "Cannot get the local address informations: " + t.getMessage(); } if (getService() instanceof IoAcceptor) { return "(" + getIdAsString() + ": " + getServiceName() + ", server, " + remote + " => " + local + ')'; } return "(" + getIdAsString() + ": " + getServiceName() + ", client, " + local + " => " + remote + ')'; } return "(" + getIdAsString() + ") Session disconnected ..."; } /** * TODO Add method documentation */ private String getIdAsString() { String id = Long.toHexString(getId()).toUpperCase(); // Somewhat inefficient, but it won't happen that often // because an ID is often a big integer. while (id.length() < 8) { id = '0' + id; // padding } id = "0x" + id; return id; } /** * TODO Add method documentation */ private String getServiceName() { TransportMetadata tm = getTransportMetadata(); if (tm == null) { return "null"; } return tm.getProviderName() + ' ' + tm.getName(); } /** * {@inheritDoc} */ public IoService getService() { return service; } /** * Fires a {@link IoEventType#SESSION_IDLE} event to any applicable sessions * in the specified collection. * * @param currentTime * the current time (i.e. {@link System#currentTimeMillis()}) */ public static void notifyIdleness(Iterator sessions, long currentTime) { IoSession s = null; while (sessions.hasNext()) { s = sessions.next(); notifyIdleSession(s, currentTime); } } /** * Fires a {@link IoEventType#SESSION_IDLE} event if applicable for the * specified {@code session}. * * @param currentTime * the current time (i.e. {@link System#currentTimeMillis()}) */ public static void notifyIdleSession(IoSession session, long currentTime) { notifyIdleSession0(session, currentTime, session.getConfig().getIdleTimeInMillis(IdleStatus.BOTH_IDLE), IdleStatus.BOTH_IDLE, Math.max(session.getLastIoTime(), session.getLastIdleTime(IdleStatus.BOTH_IDLE))); notifyIdleSession0(session, currentTime, session.getConfig().getIdleTimeInMillis(IdleStatus.READER_IDLE), IdleStatus.READER_IDLE, Math.max(session.getLastReadTime(), session.getLastIdleTime(IdleStatus.READER_IDLE))); notifyIdleSession0(session, currentTime, session.getConfig().getIdleTimeInMillis(IdleStatus.WRITER_IDLE), IdleStatus.WRITER_IDLE, Math.max(session.getLastWriteTime(), session.getLastIdleTime(IdleStatus.WRITER_IDLE))); notifyWriteTimeout(session, currentTime); } private static void notifyIdleSession0(IoSession session, long currentTime, long idleTime, IdleStatus status, long lastIoTime) { if ((idleTime > 0) && (lastIoTime != 0) && (currentTime - lastIoTime >= idleTime)) { session.getFilterChain().fireSessionIdle(status); } } private static void notifyWriteTimeout(IoSession session, long currentTime) { long writeTimeout = session.getConfig().getWriteTimeoutInMillis(); if ((writeTimeout > 0) && (currentTime - session.getLastWriteTime() >= writeTimeout) && !session.getWriteRequestQueue().isEmpty(session)) { WriteRequest request = session.getCurrentWriteRequest(); if (request != null) { session.setCurrentWriteRequest(null); WriteTimeoutException cause = new WriteTimeoutException(request); request.getFuture().setException(cause); session.getFilterChain().fireExceptionCaught(cause); // WriteException is an IOException, so we close the session. session.close(true); } } } /** * A queue which handles the CLOSE request. * * TODO : Check that when closing a session, all the pending requests are * correctly sent. */ private class CloseAwareWriteQueue implements WriteRequestQueue { private final WriteRequestQueue queue; /** * {@inheritDoc} */ public CloseAwareWriteQueue(WriteRequestQueue queue) { this.queue = queue; } /** * {@inheritDoc} */ public synchronized WriteRequest poll(IoSession session) { WriteRequest answer = queue.poll(session); if (answer == CLOSE_REQUEST) { AbstractIoSession.this.close(); dispose(session); answer = null; } return answer; } /** * {@inheritDoc} */ public void offer(IoSession session, WriteRequest e) { queue.offer(session, e); } /** * {@inheritDoc} */ public boolean isEmpty(IoSession session) { return queue.isEmpty(session); } /** * {@inheritDoc} */ public void clear(IoSession session) { queue.clear(session); } /** * {@inheritDoc} */ public void dispose(IoSession session) { queue.dispose(session); } /** * {@inheritDoc} */ public int size() { return queue.size(); } } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/ExpiringSessionRecycler.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/session/ExpiringSessionRecycler.ja0000644000175000017500000000600412032276030032612 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.session; import java.net.SocketAddress; import org.apache.mina.util.ExpirationListener; import org.apache.mina.util.ExpiringMap; /** * An {@link IoSessionRecycler} with sessions that time out on inactivity. * * TODO Document me. * * @author Apache MINA Project * @org.apache.xbean.XBean */ public class ExpiringSessionRecycler implements IoSessionRecycler { private ExpiringMap sessionMap; private ExpiringMap.Expirer mapExpirer; public ExpiringSessionRecycler() { this(ExpiringMap.DEFAULT_TIME_TO_LIVE); } public ExpiringSessionRecycler(int timeToLive) { this(timeToLive, ExpiringMap.DEFAULT_EXPIRATION_INTERVAL); } public ExpiringSessionRecycler(int timeToLive, int expirationInterval) { sessionMap = new ExpiringMap(timeToLive, expirationInterval); mapExpirer = sessionMap.getExpirer(); sessionMap.addExpirationListener(new DefaultExpirationListener()); } public void put(IoSession session) { mapExpirer.startExpiringIfNotStarted(); SocketAddress key = session.getRemoteAddress(); if (!sessionMap.containsKey(key)) { sessionMap.put(key, session); } } public IoSession recycle(SocketAddress remoteAddress) { return sessionMap.get(remoteAddress); } public void remove(IoSession session) { sessionMap.remove(session.getRemoteAddress()); } public void stopExpiring() { mapExpirer.stopExpiring(); } public int getExpirationInterval() { return sessionMap.getExpirationInterval(); } public int getTimeToLive() { return sessionMap.getTimeToLive(); } public void setExpirationInterval(int expirationInterval) { sessionMap.setExpirationInterval(expirationInterval); } public void setTimeToLive(int timeToLive) { sessionMap.setTimeToLive(timeToLive); } private class DefaultExpirationListener implements ExpirationListener { public void expired(IoSession expiredSession) { expiredSession.close(true); } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/polling/0000755000175000017500000000000012162575507025454 5ustar ebourgebourg././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/polling/AbstractPollingIoAcceptor.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/polling/AbstractPollingIoAcceptor.0000644000175000017500000006036612032276030032512 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.polling; import java.net.SocketAddress; import java.nio.channels.ClosedSelectorException; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicReference; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.service.AbstractIoAcceptor; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.SimpleIoProcessorPool; import org.apache.mina.core.session.AbstractIoSession; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionConfig; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import org.apache.mina.util.ExceptionMonitor; /** * A base class for implementing transport using a polling strategy. The * underlying sockets will be checked in an active loop and woke up when an * socket needed to be processed. This class handle the logic behind binding, * accepting and disposing the server sockets. An {@link Executor} will be used * for running client accepting and an {@link AbstractPollingIoProcessor} will * be used for processing client I/O operations like reading, writing and * closing. * * All the low level methods for binding, accepting, closing need to be provided * by the subclassing implementation. * * @see NioSocketAcceptor for a example of implementation * * @author Apache MINA Project */ public abstract class AbstractPollingIoAcceptor extends AbstractIoAcceptor { /** A lock used to protect the selector to be waked up before it's created */ private final Semaphore lock = new Semaphore(1); private final IoProcessor processor; private final boolean createdProcessor; private final Queue registerQueue = new ConcurrentLinkedQueue(); private final Queue cancelQueue = new ConcurrentLinkedQueue(); private final Map boundHandles = Collections.synchronizedMap(new HashMap()); private final ServiceOperationFuture disposalFuture = new ServiceOperationFuture(); /** A flag set when the acceptor has been created and initialized */ private volatile boolean selectable; /** The thread responsible of accepting incoming requests */ private AtomicReference acceptorRef = new AtomicReference(); protected boolean reuseAddress = false; /** * Define the number of socket that can wait to be accepted. Default * to 50 (as in the SocketServer default). */ protected int backlog = 50; /** * Constructor for {@link AbstractPollingIoAcceptor}. You need to provide a default * session configuration, a class of {@link IoProcessor} which will be instantiated in a * {@link SimpleIoProcessorPool} for better scaling in multiprocessor systems. The default * pool size will be used. * * @see SimpleIoProcessorPool * * @param sessionConfig * the default configuration for the managed {@link IoSession} * @param processorClass a {@link Class} of {@link IoProcessor} for the associated {@link IoSession} * type. */ protected AbstractPollingIoAcceptor(IoSessionConfig sessionConfig, Class> processorClass) { this(sessionConfig, null, new SimpleIoProcessorPool(processorClass), true); } /** * Constructor for {@link AbstractPollingIoAcceptor}. You need to provide a default * session configuration, a class of {@link IoProcessor} which will be instantiated in a * {@link SimpleIoProcessorPool} for using multiple thread for better scaling in multiprocessor * systems. * * @see SimpleIoProcessorPool * * @param sessionConfig * the default configuration for the managed {@link IoSession} * @param processorClass a {@link Class} of {@link IoProcessor} for the associated {@link IoSession} * type. * @param processorCount the amount of processor to instantiate for the pool */ protected AbstractPollingIoAcceptor(IoSessionConfig sessionConfig, Class> processorClass, int processorCount) { this(sessionConfig, null, new SimpleIoProcessorPool(processorClass, processorCount), true); } /** * Constructor for {@link AbstractPollingIoAcceptor}. You need to provide a default * session configuration, a default {@link Executor} will be created using * {@link Executors#newCachedThreadPool()}. * * {@see AbstractIoService#AbstractIoService(IoSessionConfig, Executor)} * * @param sessionConfig * the default configuration for the managed {@link IoSession} * @param processor the {@link IoProcessor} for processing the {@link IoSession} of this transport, triggering * events to the bound {@link IoHandler} and processing the chains of {@link IoFilter} */ protected AbstractPollingIoAcceptor(IoSessionConfig sessionConfig, IoProcessor processor) { this(sessionConfig, null, processor, false); } /** * Constructor for {@link AbstractPollingIoAcceptor}. You need to provide a default * session configuration and an {@link Executor} for handling I/O events. If a * null {@link Executor} is provided, a default one will be created using * {@link Executors#newCachedThreadPool()}. * * {@see AbstractIoService#AbstractIoService(IoSessionConfig, Executor)} * * @param sessionConfig * the default configuration for the managed {@link IoSession} * @param executor * the {@link Executor} used for handling asynchronous execution of I/O * events. Can be null. * @param processor the {@link IoProcessor} for processing the {@link IoSession} of this transport, triggering * events to the bound {@link IoHandler} and processing the chains of {@link IoFilter} */ protected AbstractPollingIoAcceptor(IoSessionConfig sessionConfig, Executor executor, IoProcessor processor) { this(sessionConfig, executor, processor, false); } /** * Constructor for {@link AbstractPollingIoAcceptor}. You need to provide a default * session configuration and an {@link Executor} for handling I/O events. If a * null {@link Executor} is provided, a default one will be created using * {@link Executors#newCachedThreadPool()}. * * {@see AbstractIoService#AbstractIoService(IoSessionConfig, Executor)} * * @param sessionConfig * the default configuration for the managed {@link IoSession} * @param executor * the {@link Executor} used for handling asynchronous execution of I/O * events. Can be null. * @param processor the {@link IoProcessor} for processing the {@link IoSession} of * this transport, triggering events to the bound {@link IoHandler} and processing * the chains of {@link IoFilter} * @param createdProcessor tagging the processor as automatically created, so it * will be automatically disposed */ private AbstractPollingIoAcceptor(IoSessionConfig sessionConfig, Executor executor, IoProcessor processor, boolean createdProcessor) { super(sessionConfig, executor); if (processor == null) { throw new IllegalArgumentException("processor"); } this.processor = processor; this.createdProcessor = createdProcessor; try { // Initialize the selector init(); // The selector is now ready, we can switch the // flag to true so that incoming connection can be accepted selectable = true; } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeIoException("Failed to initialize.", e); } finally { if (!selectable) { try { destroy(); } catch (Exception e) { ExceptionMonitor.getInstance().exceptionCaught(e); } } } } /** * Initialize the polling system, will be called at construction time. * @throws Exception any exception thrown by the underlying system calls */ protected abstract void init() throws Exception; /** * Destroy the polling system, will be called when this {@link IoAcceptor} * implementation will be disposed. * @throws Exception any exception thrown by the underlying systems calls */ protected abstract void destroy() throws Exception; /** * Check for acceptable connections, interrupt when at least a server is ready for accepting. * All the ready server socket descriptors need to be returned by {@link #selectedHandles()} * @return The number of sockets having got incoming client * @throws Exception any exception thrown by the underlying systems calls */ protected abstract int select() throws Exception; /** * Interrupt the {@link #select()} method. Used when the poll set need to be modified. */ protected abstract void wakeup(); /** * {@link Iterator} for the set of server sockets found with acceptable incoming connections * during the last {@link #select()} call. * @return the list of server handles ready */ protected abstract Iterator selectedHandles(); /** * Open a server socket for a given local address. * @param localAddress the associated local address * @return the opened server socket * @throws Exception any exception thrown by the underlying systems calls */ protected abstract H open(SocketAddress localAddress) throws Exception; /** * Get the local address associated with a given server socket * @param handle the server socket * @return the local {@link SocketAddress} associated with this handle * @throws Exception any exception thrown by the underlying systems calls */ protected abstract SocketAddress localAddress(H handle) throws Exception; /** * Accept a client connection for a server socket and return a new {@link IoSession} * associated with the given {@link IoProcessor} * @param processor the {@link IoProcessor} to associate with the {@link IoSession} * @param handle the server handle * @return the created {@link IoSession} * @throws Exception any exception thrown by the underlying systems calls */ protected abstract S accept(IoProcessor processor, H handle) throws Exception; /** * Close a server socket. * @param handle the server socket * @throws Exception any exception thrown by the underlying systems calls */ protected abstract void close(H handle) throws Exception; /** * {@inheritDoc} */ @Override protected void dispose0() throws Exception { unbind(); startupAcceptor(); wakeup(); } /** * {@inheritDoc} */ @Override protected final Set bindInternal(List localAddresses) throws Exception { // Create a bind request as a Future operation. When the selector // have handled the registration, it will signal this future. AcceptorOperationFuture request = new AcceptorOperationFuture(localAddresses); // adds the Registration request to the queue for the Workers // to handle registerQueue.add(request); // creates the Acceptor instance and has the local // executor kick it off. startupAcceptor(); // As we just started the acceptor, we have to unblock the select() // in order to process the bind request we just have added to the // registerQueue. try { lock.acquire(); // Wait a bit to give a chance to the Acceptor thread to do the select() Thread.sleep(10); wakeup(); } finally { lock.release(); } // Now, we wait until this request is completed. request.awaitUninterruptibly(); if (request.getException() != null) { throw request.getException(); } // Update the local addresses. // setLocalAddresses() shouldn't be called from the worker thread // because of deadlock. Set newLocalAddresses = new HashSet(); for (H handle : boundHandles.values()) { newLocalAddresses.add(localAddress(handle)); } return newLocalAddresses; } /** * This method is called by the doBind() and doUnbind() * methods. If the acceptor is null, the acceptor object will * be created and kicked off by the executor. If the acceptor * object is null, probably already created and this class * is now working, then nothing will happen and the method * will just return. */ private void startupAcceptor() throws InterruptedException { // If the acceptor is not ready, clear the queues // TODO : they should already be clean : do we have to do that ? if (!selectable) { registerQueue.clear(); cancelQueue.clear(); } // start the acceptor if not already started Acceptor acceptor = acceptorRef.get(); if (acceptor == null) { lock.acquire(); acceptor = new Acceptor(); if (acceptorRef.compareAndSet(null, acceptor)) { executeWorker(acceptor); } else { lock.release(); } } } /** * {@inheritDoc} */ @Override protected final void unbind0(List localAddresses) throws Exception { AcceptorOperationFuture future = new AcceptorOperationFuture(localAddresses); cancelQueue.add(future); startupAcceptor(); wakeup(); future.awaitUninterruptibly(); if (future.getException() != null) { throw future.getException(); } } /** * This class is called by the startupAcceptor() method and is * placed into a NamePreservingRunnable class. * It's a thread accepting incoming connections from clients. * The loop is stopped when all the bound handlers are unbound. */ private class Acceptor implements Runnable { public void run() { assert (acceptorRef.get() == this); int nHandles = 0; // Release the lock lock.release(); while (selectable) { try { // Detect if we have some keys ready to be processed // The select() will be woke up if some new connection // have occurred, or if the selector has been explicitly // woke up int selected = select(); // this actually sets the selector to OP_ACCEPT, // and binds to the port on which this class will // listen on nHandles += registerHandles(); // Now, if the number of registred handles is 0, we can // quit the loop: we don't have any socket listening // for incoming connection. if (nHandles == 0) { acceptorRef.set(null); if (registerQueue.isEmpty() && cancelQueue.isEmpty()) { assert (acceptorRef.get() != this); break; } if (!acceptorRef.compareAndSet(null, this)) { assert (acceptorRef.get() != this); break; } assert (acceptorRef.get() == this); } if (selected > 0) { // We have some connection request, let's process // them here. processHandles(selectedHandles()); } // check to see if any cancellation request has been made. nHandles -= unregisterHandles(); } catch (ClosedSelectorException cse) { // If the selector has been closed, we can exit the loop break; } catch (Throwable e) { ExceptionMonitor.getInstance().exceptionCaught(e); try { Thread.sleep(1000); } catch (InterruptedException e1) { ExceptionMonitor.getInstance().exceptionCaught(e1); } } } // Cleanup all the processors, and shutdown the acceptor. if (selectable && isDisposing()) { selectable = false; try { if (createdProcessor) { processor.dispose(); } } finally { try { synchronized (disposalLock) { if (isDisposing()) { destroy(); } } } catch (Exception e) { ExceptionMonitor.getInstance().exceptionCaught(e); } finally { disposalFuture.setDone(); } } } } /** * This method will process new sessions for the Worker class. All * keys that have had their status updates as per the Selector.selectedKeys() * method will be processed here. Only keys that are ready to accept * connections are handled here. *

* Session objects are created by making new instances of SocketSessionImpl * and passing the session object to the SocketIoProcessor class. */ @SuppressWarnings("unchecked") private void processHandles(Iterator handles) throws Exception { while (handles.hasNext()) { H handle = handles.next(); handles.remove(); // Associates a new created connection to a processor, // and get back a session S session = accept(processor, handle); if (session == null) { continue; } initSession(session, null, null); // add the session to the SocketIoProcessor session.getProcessor().add(session); } } } /** * Sets up the socket communications. Sets items such as: *

* Blocking * Reuse address * Receive buffer size * Bind to listen port * Registers OP_ACCEPT for selector */ private int registerHandles() { for (;;) { // The register queue contains the list of services to manage // in this acceptor. AcceptorOperationFuture future = registerQueue.poll(); if (future == null) { return 0; } // We create a temporary map to store the bound handles, // as we may have to remove them all if there is an exception // during the sockets opening. Map newHandles = new ConcurrentHashMap(); List localAddresses = future.getLocalAddresses(); try { // Process all the addresses for (SocketAddress a : localAddresses) { H handle = open(a); newHandles.put(localAddress(handle), handle); } // Everything went ok, we can now update the map storing // all the bound sockets. boundHandles.putAll(newHandles); // and notify. future.setDone(); return newHandles.size(); } catch (Exception e) { // We store the exception in the future future.setException(e); } finally { // Roll back if failed to bind all addresses. if (future.getException() != null) { for (H handle : newHandles.values()) { try { close(handle); } catch (Exception e) { ExceptionMonitor.getInstance().exceptionCaught(e); } } // TODO : add some comment : what is the wakeup() waking up ? wakeup(); } } } } /** * This method just checks to see if anything has been placed into the * cancellation queue. The only thing that should be in the cancelQueue * is CancellationRequest objects and the only place this happens is in * the doUnbind() method. */ private int unregisterHandles() { int cancelledHandles = 0; for (;;) { AcceptorOperationFuture future = cancelQueue.poll(); if (future == null) { break; } // close the channels for (SocketAddress a : future.getLocalAddresses()) { H handle = boundHandles.remove(a); if (handle == null) { continue; } try { close(handle); wakeup(); // wake up again to trigger thread death } catch (Throwable e) { ExceptionMonitor.getInstance().exceptionCaught(e); } finally { cancelledHandles++; } } future.setDone(); } return cancelledHandles; } /** * {@inheritDoc} */ public final IoSession newSession(SocketAddress remoteAddress, SocketAddress localAddress) { throw new UnsupportedOperationException(); } /** * {@inheritDoc} */ public int getBacklog() { return backlog; } /** * {@inheritDoc} */ public void setBacklog(int backlog) { synchronized (bindLock) { if (isActive()) { throw new IllegalStateException("backlog can't be set while the acceptor is bound."); } this.backlog = backlog; } } /** * {@inheritDoc} */ public boolean isReuseAddress() { return reuseAddress; } /** * {@inheritDoc} */ public void setReuseAddress(boolean reuseAddress) { synchronized (bindLock) { if (isActive()) { throw new IllegalStateException("backlog can't be set while the acceptor is bound."); } this.reuseAddress = reuseAddress; } } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/polling/AbstractPollingIoConnector.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/polling/AbstractPollingIoConnector0000644000175000017500000005367612032276030032634 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.polling; import java.net.ConnectException; import java.net.SocketAddress; import java.nio.channels.ClosedSelectorException; import java.util.Iterator; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicReference; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.DefaultConnectFuture; import org.apache.mina.core.service.AbstractIoConnector; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.SimpleIoProcessorPool; import org.apache.mina.core.session.AbstractIoSession; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionConfig; import org.apache.mina.core.session.IoSessionInitializer; import org.apache.mina.transport.socket.nio.NioSocketConnector; import org.apache.mina.util.ExceptionMonitor; /** * A base class for implementing client transport using a polling strategy. The * underlying sockets will be checked in an active loop and woke up when an * socket needed to be processed. This class handle the logic behind binding, * connecting and disposing the client sockets. A {@link Executor} will be used * for running client connection, and an {@link AbstractPollingIoProcessor} will * be used for processing connected client I/O operations like reading, writing * and closing. * * All the low level methods for binding, connecting, closing need to be * provided by the subclassing implementation. * * @see NioSocketConnector for a example of implementation * * @author Apache MINA Project */ public abstract class AbstractPollingIoConnector extends AbstractIoConnector { private final Queue connectQueue = new ConcurrentLinkedQueue(); private final Queue cancelQueue = new ConcurrentLinkedQueue(); private final IoProcessor processor; private final boolean createdProcessor; private final ServiceOperationFuture disposalFuture = new ServiceOperationFuture(); private volatile boolean selectable; /** The connector thread */ private final AtomicReference connectorRef = new AtomicReference(); /** * Constructor for {@link AbstractPollingIoConnector}. You need to provide a default * session configuration, a class of {@link IoProcessor} which will be instantiated in a * {@link SimpleIoProcessorPool} for better scaling in multiprocessor systems. The default * pool size will be used. * * @see SimpleIoProcessorPool * * @param sessionConfig * the default configuration for the managed {@link IoSession} * @param processorClass a {@link Class} of {@link IoProcessor} for the associated {@link IoSession} * type. */ protected AbstractPollingIoConnector(IoSessionConfig sessionConfig, Class> processorClass) { this(sessionConfig, null, new SimpleIoProcessorPool(processorClass), true); } /** * Constructor for {@link AbstractPollingIoConnector}. You need to provide a default * session configuration, a class of {@link IoProcessor} which will be instantiated in a * {@link SimpleIoProcessorPool} for using multiple thread for better scaling in multiprocessor * systems. * * @see SimpleIoProcessorPool * * @param sessionConfig * the default configuration for the managed {@link IoSession} * @param processorClass a {@link Class} of {@link IoProcessor} for the associated {@link IoSession} * type. * @param processorCount the amount of processor to instantiate for the pool */ protected AbstractPollingIoConnector(IoSessionConfig sessionConfig, Class> processorClass, int processorCount) { this(sessionConfig, null, new SimpleIoProcessorPool(processorClass, processorCount), true); } /** * Constructor for {@link AbstractPollingIoConnector}. You need to provide a default * session configuration, a default {@link Executor} will be created using * {@link Executors#newCachedThreadPool()}. * * {@see AbstractIoService#AbstractIoService(IoSessionConfig, Executor)} * * @param sessionConfig * the default configuration for the managed {@link IoSession} * @param processor the {@link IoProcessor} for processing the {@link IoSession} of this transport, triggering * events to the bound {@link IoHandler} and processing the chains of {@link IoFilter} */ protected AbstractPollingIoConnector(IoSessionConfig sessionConfig, IoProcessor processor) { this(sessionConfig, null, processor, false); } /** * Constructor for {@link AbstractPollingIoConnector}. You need to provide a default * session configuration and an {@link Executor} for handling I/O events. If * null {@link Executor} is provided, a default one will be created using * {@link Executors#newCachedThreadPool()}. * * {@see AbstractIoService#AbstractIoService(IoSessionConfig, Executor)} * * @param sessionConfig * the default configuration for the managed {@link IoSession} * @param executor * the {@link Executor} used for handling asynchronous execution of I/O * events. Can be null. * @param processor the {@link IoProcessor} for processing the {@link IoSession} of this transport, triggering * events to the bound {@link IoHandler} and processing the chains of {@link IoFilter} */ protected AbstractPollingIoConnector(IoSessionConfig sessionConfig, Executor executor, IoProcessor processor) { this(sessionConfig, executor, processor, false); } /** * Constructor for {@link AbstractPollingIoAcceptor}. You need to provide a default * session configuration and an {@link Executor} for handling I/O events. If * null {@link Executor} is provided, a default one will be created using * {@link Executors#newCachedThreadPool()}. * * {@see AbstractIoService#AbstractIoService(IoSessionConfig, Executor)} * * @param sessionConfig * the default configuration for the managed {@link IoSession} * @param executor * the {@link Executor} used for handling asynchronous execution of I/O * events. Can be null. * @param processor the {@link IoProcessor} for processing the {@link IoSession} of this transport, triggering * events to the bound {@link IoHandler} and processing the chains of {@link IoFilter} * @param createdProcessor tagging the processor as automatically created, so it will be automatically disposed */ private AbstractPollingIoConnector(IoSessionConfig sessionConfig, Executor executor, IoProcessor processor, boolean createdProcessor) { super(sessionConfig, executor); if (processor == null) { throw new IllegalArgumentException("processor"); } this.processor = processor; this.createdProcessor = createdProcessor; try { init(); selectable = true; } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeIoException("Failed to initialize.", e); } finally { if (!selectable) { try { destroy(); } catch (Exception e) { ExceptionMonitor.getInstance().exceptionCaught(e); } } } } /** * Initialize the polling system, will be called at construction time. * @throws Exception any exception thrown by the underlying system calls */ protected abstract void init() throws Exception; /** * Destroy the polling system, will be called when this {@link IoConnector} * implementation will be disposed. * @throws Exception any exception thrown by the underlying systems calls */ protected abstract void destroy() throws Exception; /** * Create a new client socket handle from a local {@link SocketAddress} * @param localAddress the socket address for binding the new client socket * @return a new client socket handle * @throws Exception any exception thrown by the underlying systems calls */ protected abstract H newHandle(SocketAddress localAddress) throws Exception; /** * Connect a newly created client socket handle to a remote {@link SocketAddress}. * This operation is non-blocking, so at end of the call the socket can be still in connection * process. * @param handle the client socket handle * @param remoteAddress the remote address where to connect * @return true if a connection was established, false if this client socket * is in non-blocking mode and the connection operation is in progress * @throws Exception */ protected abstract boolean connect(H handle, SocketAddress remoteAddress) throws Exception; /** * Finish the connection process of a client socket after it was marked as ready to process * by the {@link #select(int)} call. The socket will be connected or reported as connection * failed. * @param handle the client socket handle to finsh to connect * @return true if the socket is connected * @throws Exception any exception thrown by the underlying systems calls */ protected abstract boolean finishConnect(H handle) throws Exception; /** * Create a new {@link IoSession} from a connected socket client handle. * Will assign the created {@link IoSession} to the given {@link IoProcessor} for * managing future I/O events. * @param processor the processor in charge of this session * @param handle the newly connected client socket handle * @return a new {@link IoSession} * @throws Exception any exception thrown by the underlying systems calls */ protected abstract T newSession(IoProcessor processor, H handle) throws Exception; /** * Close a client socket. * @param handle the client socket * @throws Exception any exception thrown by the underlying systems calls */ protected abstract void close(H handle) throws Exception; /** * Interrupt the {@link #select()} method. Used when the poll set need to be modified. */ protected abstract void wakeup(); /** * Check for connected sockets, interrupt when at least a connection is processed (connected or * failed to connect). All the client socket descriptors processed need to be returned by * {@link #selectedHandles()} * @return The number of socket having received some data * @throws Exception any exception thrown by the underlying systems calls */ protected abstract int select(int timeout) throws Exception; /** * {@link Iterator} for the set of client sockets found connected or * failed to connect during the last {@link #select()} call. * @return the list of client socket handles to process */ protected abstract Iterator selectedHandles(); /** * {@link Iterator} for all the client sockets polled for connection. * @return the list of client sockets currently polled for connection */ protected abstract Iterator allHandles(); /** * Register a new client socket for connection, add it to connection polling * @param handle client socket handle * @param request the associated {@link ConnectionRequest} * @throws Exception any exception thrown by the underlying systems calls */ protected abstract void register(H handle, ConnectionRequest request) throws Exception; /** * get the {@link ConnectionRequest} for a given client socket handle * @param handle the socket client handle * @return the connection request if the socket is connecting otherwise null */ protected abstract ConnectionRequest getConnectionRequest(H handle); /** * {@inheritDoc} */ @Override protected final void dispose0() throws Exception { startupWorker(); wakeup(); } /** * {@inheritDoc} */ @Override @SuppressWarnings("unchecked") protected final ConnectFuture connect0(SocketAddress remoteAddress, SocketAddress localAddress, IoSessionInitializer sessionInitializer) { H handle = null; boolean success = false; try { handle = newHandle(localAddress); if (connect(handle, remoteAddress)) { ConnectFuture future = new DefaultConnectFuture(); T session = newSession(processor, handle); initSession(session, future, sessionInitializer); // Forward the remaining process to the IoProcessor. session.getProcessor().add(session); success = true; return future; } success = true; } catch (Exception e) { return DefaultConnectFuture.newFailedFuture(e); } finally { if (!success && handle != null) { try { close(handle); } catch (Exception e) { ExceptionMonitor.getInstance().exceptionCaught(e); } } } ConnectionRequest request = new ConnectionRequest(handle, sessionInitializer); connectQueue.add(request); startupWorker(); wakeup(); return request; } private void startupWorker() { if (!selectable) { connectQueue.clear(); cancelQueue.clear(); } Connector connector = connectorRef.get(); if (connector == null) { connector = new Connector(); if (connectorRef.compareAndSet(null, connector)) { executeWorker(connector); } } } private int registerNew() { int nHandles = 0; for (;;) { ConnectionRequest req = connectQueue.poll(); if (req == null) { break; } H handle = req.handle; try { register(handle, req); nHandles++; } catch (Exception e) { req.setException(e); try { close(handle); } catch (Exception e2) { ExceptionMonitor.getInstance().exceptionCaught(e2); } } } return nHandles; } private int cancelKeys() { int nHandles = 0; for (;;) { ConnectionRequest req = cancelQueue.poll(); if (req == null) { break; } H handle = req.handle; try { close(handle); } catch (Exception e) { ExceptionMonitor.getInstance().exceptionCaught(e); } finally { nHandles++; } } if (nHandles > 0) { wakeup(); } return nHandles; } /** * Process the incoming connections, creating a new session for each * valid connection. */ private int processConnections(Iterator handlers) { int nHandles = 0; // Loop on each connection request while (handlers.hasNext()) { H handle = handlers.next(); handlers.remove(); ConnectionRequest connectionRequest = getConnectionRequest(handle); if (connectionRequest == null) { continue; } boolean success = false; try { if (finishConnect(handle)) { T session = newSession(processor, handle); initSession(session, connectionRequest, connectionRequest.getSessionInitializer()); // Forward the remaining process to the IoProcessor. session.getProcessor().add(session); nHandles++; } success = true; } catch (Throwable e) { connectionRequest.setException(e); } finally { if (!success) { // The connection failed, we have to cancel it. cancelQueue.offer(connectionRequest); } } } return nHandles; } private void processTimedOutSessions(Iterator handles) { long currentTime = System.currentTimeMillis(); while (handles.hasNext()) { H handle = handles.next(); ConnectionRequest connectionRequest = getConnectionRequest(handle); if ((connectionRequest != null) && (currentTime >= connectionRequest.deadline)) { connectionRequest.setException(new ConnectException("Connection timed out.")); cancelQueue.offer(connectionRequest); } } } private class Connector implements Runnable { public void run() { assert (connectorRef.get() == this); int nHandles = 0; while (selectable) { try { // the timeout for select shall be smaller of the connect // timeout or 1 second... int timeout = (int) Math.min(getConnectTimeoutMillis(), 1000L); int selected = select(timeout); nHandles += registerNew(); // get a chance to get out of the connector loop, if we don't have any more handles if (nHandles == 0) { connectorRef.set(null); if (connectQueue.isEmpty()) { assert (connectorRef.get() != this); break; } if (!connectorRef.compareAndSet(null, this)) { assert (connectorRef.get() != this); break; } assert (connectorRef.get() == this); } if (selected > 0) { nHandles -= processConnections(selectedHandles()); } processTimedOutSessions(allHandles()); nHandles -= cancelKeys(); } catch (ClosedSelectorException cse) { // If the selector has been closed, we can exit the loop break; } catch (Throwable e) { ExceptionMonitor.getInstance().exceptionCaught(e); try { Thread.sleep(1000); } catch (InterruptedException e1) { ExceptionMonitor.getInstance().exceptionCaught(e1); } } } if (selectable && isDisposing()) { selectable = false; try { if (createdProcessor) { processor.dispose(); } } finally { try { synchronized (disposalLock) { if (isDisposing()) { destroy(); } } } catch (Exception e) { ExceptionMonitor.getInstance().exceptionCaught(e); } finally { disposalFuture.setDone(); } } } } } public final class ConnectionRequest extends DefaultConnectFuture { private final H handle; private final long deadline; private final IoSessionInitializer sessionInitializer; public ConnectionRequest(H handle, IoSessionInitializer callback) { this.handle = handle; long timeout = getConnectTimeoutMillis(); if (timeout <= 0L) { this.deadline = Long.MAX_VALUE; } else { this.deadline = System.currentTimeMillis() + timeout; } this.sessionInitializer = callback; } public H getHandle() { return handle; } public long getDeadline() { return deadline; } public IoSessionInitializer getSessionInitializer() { return sessionInitializer; } @Override public void cancel() { if (!isDone()) { super.cancel(); cancelQueue.add(this); startupWorker(); wakeup(); } } } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/polling/AbstractPollingConnectionlessIoAcceptor.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/polling/AbstractPollingConnectionl0000644000175000017500000006231412033571630032657 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.polling; import java.net.SocketAddress; import java.nio.channels.ClosedSelectorException; import java.nio.channels.SelectionKey; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; import java.util.concurrent.Semaphore; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.service.AbstractIoAcceptor; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.session.AbstractIoSession; import org.apache.mina.core.session.ExpiringSessionRecycler; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionConfig; import org.apache.mina.core.session.IoSessionRecycler; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.core.write.WriteRequestQueue; import org.apache.mina.util.ExceptionMonitor; /** * {@link IoAcceptor} for datagram transport (UDP/IP). * * @author Apache MINA Project * @org.apache.xbean.XBean * * @param the type of the {@link IoSession} this processor can handle */ public abstract class AbstractPollingConnectionlessIoAcceptor extends AbstractIoAcceptor implements IoProcessor { private static final IoSessionRecycler DEFAULT_RECYCLER = new ExpiringSessionRecycler(); /** * A timeout used for the select, as we need to get out to deal with idle * sessions */ private static final long SELECT_TIMEOUT = 1000L; /** A lock used to protect the selector to be waked up before it's created */ private final Semaphore lock = new Semaphore( 1 ); private final Queue registerQueue = new ConcurrentLinkedQueue(); private final Queue cancelQueue = new ConcurrentLinkedQueue(); private final Queue flushingSessions = new ConcurrentLinkedQueue(); private final Map boundHandles = Collections.synchronizedMap( new HashMap() ); private IoSessionRecycler sessionRecycler = DEFAULT_RECYCLER; private final ServiceOperationFuture disposalFuture = new ServiceOperationFuture(); private volatile boolean selectable; /** The thread responsible of accepting incoming requests */ private Acceptor acceptor; private long lastIdleCheckTime; /** * Creates a new instance. */ protected AbstractPollingConnectionlessIoAcceptor( IoSessionConfig sessionConfig ) { this( sessionConfig, null ); } /** * Creates a new instance. */ protected AbstractPollingConnectionlessIoAcceptor( IoSessionConfig sessionConfig, Executor executor ) { super( sessionConfig, executor ); try { init(); selectable = true; } catch ( RuntimeException e ) { throw e; } catch ( Exception e ) { throw new RuntimeIoException( "Failed to initialize.", e ); } finally { if ( !selectable ) { try { destroy(); } catch ( Exception e ) { ExceptionMonitor.getInstance().exceptionCaught( e ); } } } } protected abstract void init() throws Exception; protected abstract void destroy() throws Exception; protected abstract int select() throws Exception; protected abstract int select( long timeout ) throws Exception; protected abstract void wakeup(); protected abstract Set selectedHandles(); protected abstract H open( SocketAddress localAddress ) throws Exception; protected abstract void close( H handle ) throws Exception; protected abstract SocketAddress localAddress( H handle ) throws Exception; protected abstract boolean isReadable( H handle ); protected abstract boolean isWritable( H handle ); protected abstract SocketAddress receive( H handle, IoBuffer buffer ) throws Exception; protected abstract int send( S session, IoBuffer buffer, SocketAddress remoteAddress ) throws Exception; protected abstract S newSession( IoProcessor processor, H handle, SocketAddress remoteAddress ) throws Exception; protected abstract void setInterestedInWrite( S session, boolean interested ) throws Exception; /** * {@inheritDoc} */ @Override protected void dispose0() throws Exception { unbind(); startupAcceptor(); wakeup(); } /** * {@inheritDoc} */ @Override protected final Set bindInternal( List localAddresses ) throws Exception { // Create a bind request as a Future operation. When the selector // have handled the registration, it will signal this future. AcceptorOperationFuture request = new AcceptorOperationFuture( localAddresses ); // adds the Registration request to the queue for the Workers // to handle registerQueue.add( request ); // creates the Acceptor instance and has the local // executor kick it off. startupAcceptor(); // As we just started the acceptor, we have to unblock the select() // in order to process the bind request we just have added to the // registerQueue. try { lock.acquire(); // Wait a bit to give a chance to the Acceptor thread to do the select() Thread.sleep( 10 ); wakeup(); } finally { lock.release(); } // Now, we wait until this request is completed. request.awaitUninterruptibly(); if ( request.getException() != null ) { throw request.getException(); } // Update the local addresses. // setLocalAddresses() shouldn't be called from the worker thread // because of deadlock. Set newLocalAddresses = new HashSet(); for ( H handle : boundHandles.values() ) { newLocalAddresses.add( localAddress( handle ) ); } return newLocalAddresses; } /** * {@inheritDoc} */ @Override protected final void unbind0( List localAddresses ) throws Exception { AcceptorOperationFuture request = new AcceptorOperationFuture( localAddresses ); cancelQueue.add( request ); startupAcceptor(); wakeup(); request.awaitUninterruptibly(); if ( request.getException() != null ) { throw request.getException(); } } /** * {@inheritDoc} */ public final IoSession newSession( SocketAddress remoteAddress, SocketAddress localAddress ) { if ( isDisposing() ) { throw new IllegalStateException( "Already disposed." ); } if ( remoteAddress == null ) { throw new IllegalArgumentException( "remoteAddress" ); } synchronized ( bindLock ) { if ( !isActive() ) { throw new IllegalStateException( "Can't create a session from a unbound service." ); } try { return newSessionWithoutLock( remoteAddress, localAddress ); } catch ( RuntimeException e ) { throw e; } catch ( Error e ) { throw e; } catch ( Exception e ) { throw new RuntimeIoException( "Failed to create a session.", e ); } } } private IoSession newSessionWithoutLock( SocketAddress remoteAddress, SocketAddress localAddress ) throws Exception { H handle = boundHandles.get( localAddress ); if ( handle == null ) { throw new IllegalArgumentException( "Unknown local address: " + localAddress ); } IoSession session; synchronized ( sessionRecycler ) { session = sessionRecycler.recycle( remoteAddress ); if ( session != null ) { return session; } // If a new session needs to be created. S newSession = newSession( this, handle, remoteAddress ); getSessionRecycler().put( newSession ); session = newSession; } initSession( session, null, null ); try { this.getFilterChainBuilder().buildFilterChain( session.getFilterChain() ); getListeners().fireSessionCreated( session ); } catch ( Throwable t ) { ExceptionMonitor.getInstance().exceptionCaught( t ); } return session; } public final IoSessionRecycler getSessionRecycler() { return sessionRecycler; } public final void setSessionRecycler( IoSessionRecycler sessionRecycler ) { synchronized ( bindLock ) { if ( isActive() ) { throw new IllegalStateException( "sessionRecycler can't be set while the acceptor is bound." ); } if ( sessionRecycler == null ) { sessionRecycler = DEFAULT_RECYCLER; } this.sessionRecycler = sessionRecycler; } } /** * {@inheritDoc} */ public void add( S session ) { // Nothing to do for UDP } /** * {@inheritDoc} */ public void flush( S session ) { if ( scheduleFlush( session ) ) { wakeup(); } } /** * {@inheritDoc} */ public void write( S session, WriteRequest writeRequest ) { // We will try to write the message directly long currentTime = System.currentTimeMillis(); final WriteRequestQueue writeRequestQueue = session.getWriteRequestQueue(); final int maxWrittenBytes = session.getConfig().getMaxReadBufferSize() + ( session.getConfig().getMaxReadBufferSize() >>> 1 ); int writtenBytes = 0; // Deal with the special case of a Message marker (no bytes in the request) // We just have to return after having calle dthe messageSent event IoBuffer buf = ( IoBuffer ) writeRequest.getMessage(); if ( buf.remaining() == 0 ) { // Clear and fire event session.setCurrentWriteRequest( null ); buf.reset(); session.getFilterChain().fireMessageSent( writeRequest ); return; } // Now, write the data try { for ( ;; ) { if ( writeRequest == null ) { writeRequest = writeRequestQueue.poll( session ); if ( writeRequest == null ) { setInterestedInWrite( session, false ); break; } session.setCurrentWriteRequest( writeRequest ); } buf = ( IoBuffer ) writeRequest.getMessage(); if ( buf.remaining() == 0 ) { // Clear and fire event session.setCurrentWriteRequest( null ); buf.reset(); session.getFilterChain().fireMessageSent( writeRequest ); continue; } SocketAddress destination = writeRequest.getDestination(); if ( destination == null ) { destination = session.getRemoteAddress(); } int localWrittenBytes = send( session, buf, destination ); if ( ( localWrittenBytes == 0 ) || ( writtenBytes >= maxWrittenBytes ) ) { // Kernel buffer is full or wrote too much setInterestedInWrite( session, true ); session.getWriteRequestQueue().offer( session, writeRequest ); scheduleFlush( session ); } else { setInterestedInWrite( session, false ); // Clear and fire event session.setCurrentWriteRequest( null ); writtenBytes += localWrittenBytes; buf.reset(); session.getFilterChain().fireMessageSent( writeRequest ); break; } } } catch ( Exception e ) { session.getFilterChain().fireExceptionCaught( e ); } finally { session.increaseWrittenBytes( writtenBytes, currentTime ); } } /** * {@inheritDoc} */ public void remove( S session ) { getSessionRecycler().remove( session ); getListeners().fireSessionDestroyed( session ); } /** * {@inheritDoc} */ public void updateTrafficControl( S session ) { throw new UnsupportedOperationException(); } /** * Starts the inner Acceptor thread. */ private void startupAcceptor() throws InterruptedException { if ( !selectable ) { registerQueue.clear(); cancelQueue.clear(); flushingSessions.clear(); } lock.acquire(); if ( acceptor == null ) { acceptor = new Acceptor(); executeWorker( acceptor ); } else { lock.release(); } } private boolean scheduleFlush( S session ) { // Set the schedule for flush flag if the session // has not already be added to the flushingSessions // queue if ( session.setScheduledForFlush( true ) ) { flushingSessions.add( session ); return true; } else { return false; } } /** * This private class is used to accept incoming connection from * clients. It's an infinite loop, which can be stopped when all * the registered handles have been removed (unbound). */ private class Acceptor implements Runnable { public void run() { int nHandles = 0; lastIdleCheckTime = System.currentTimeMillis(); // Release the lock lock.release(); while ( selectable ) { try { int selected = select( SELECT_TIMEOUT ); nHandles += registerHandles(); if ( nHandles == 0 ) { try { lock.acquire(); if ( registerQueue.isEmpty() && cancelQueue.isEmpty() ) { acceptor = null; break; } } finally { lock.release(); } } if ( selected > 0 ) { processReadySessions( selectedHandles() ); } long currentTime = System.currentTimeMillis(); flushSessions( currentTime ); nHandles -= unregisterHandles(); notifyIdleSessions( currentTime ); } catch ( ClosedSelectorException cse ) { // If the selector has been closed, we can exit the loop break; } catch ( Exception e ) { ExceptionMonitor.getInstance().exceptionCaught( e ); try { Thread.sleep( 1000 ); } catch ( InterruptedException e1 ) { } } } if ( selectable && isDisposing() ) { selectable = false; try { destroy(); } catch ( Exception e ) { ExceptionMonitor.getInstance().exceptionCaught( e ); } finally { disposalFuture.setValue( true ); } } } } @SuppressWarnings("unchecked") private void processReadySessions( Set handles ) { Iterator iterator = handles.iterator(); while ( iterator.hasNext() ) { SelectionKey key = iterator.next(); H handle = ( H ) key.channel(); iterator.remove(); try { if ( ( key != null ) && key.isValid() && key.isReadable() ) { readHandle( handle ); } if ( ( key != null ) && key.isValid() && key.isWritable() ) { for ( IoSession session : getManagedSessions().values() ) { scheduleFlush( ( S ) session ); } } } catch ( Throwable t ) { ExceptionMonitor.getInstance().exceptionCaught( t ); } } } private void readHandle( H handle ) throws Exception { IoBuffer readBuf = IoBuffer.allocate( getSessionConfig().getReadBufferSize() ); SocketAddress remoteAddress = receive( handle, readBuf ); if ( remoteAddress != null ) { IoSession session = newSessionWithoutLock( remoteAddress, localAddress( handle ) ); readBuf.flip(); session.getFilterChain().fireMessageReceived( readBuf ); } } private void flushSessions( long currentTime ) { for ( ;; ) { S session = flushingSessions.poll(); if ( session == null ) { break; } // Reset the Schedule for flush flag for this session, // as we are flushing it now session.unscheduledForFlush(); try { boolean flushedAll = flush( session, currentTime ); if ( flushedAll && !session.getWriteRequestQueue().isEmpty( session ) && !session.isScheduledForFlush() ) { scheduleFlush( session ); } } catch ( Exception e ) { session.getFilterChain().fireExceptionCaught( e ); } } } private boolean flush( S session, long currentTime ) throws Exception { final WriteRequestQueue writeRequestQueue = session.getWriteRequestQueue(); final int maxWrittenBytes = session.getConfig().getMaxReadBufferSize() + ( session.getConfig().getMaxReadBufferSize() >>> 1 ); int writtenBytes = 0; try { for ( ;; ) { WriteRequest req = session.getCurrentWriteRequest(); if ( req == null ) { req = writeRequestQueue.poll( session ); if ( req == null ) { setInterestedInWrite( session, false ); break; } session.setCurrentWriteRequest( req ); } IoBuffer buf = ( IoBuffer ) req.getMessage(); if ( buf.remaining() == 0 ) { // Clear and fire event session.setCurrentWriteRequest( null ); buf.reset(); session.getFilterChain().fireMessageSent( req ); continue; } SocketAddress destination = req.getDestination(); if ( destination == null ) { destination = session.getRemoteAddress(); } int localWrittenBytes = send( session, buf, destination ); if ( ( localWrittenBytes == 0 ) || ( writtenBytes >= maxWrittenBytes ) ) { // Kernel buffer is full or wrote too much setInterestedInWrite( session, true ); return false; } else { setInterestedInWrite( session, false ); // Clear and fire event session.setCurrentWriteRequest( null ); writtenBytes += localWrittenBytes; buf.reset(); session.getFilterChain().fireMessageSent( req ); } } } finally { session.increaseWrittenBytes( writtenBytes, currentTime ); } return true; } private int registerHandles() { for ( ;; ) { AcceptorOperationFuture req = registerQueue.poll(); if ( req == null ) { break; } Map newHandles = new HashMap(); List localAddresses = req.getLocalAddresses(); try { for ( SocketAddress socketAddress : localAddresses ) { H handle = open( socketAddress ); newHandles.put( localAddress( handle ), handle ); } boundHandles.putAll( newHandles ); getListeners().fireServiceActivated(); req.setDone(); return newHandles.size(); } catch ( Exception e ) { req.setException( e ); } finally { // Roll back if failed to bind all addresses. if ( req.getException() != null ) { for ( H handle : newHandles.values() ) { try { close( handle ); } catch ( Exception e ) { ExceptionMonitor.getInstance().exceptionCaught( e ); } } wakeup(); } } } return 0; } private int unregisterHandles() { int nHandles = 0; for ( ;; ) { AcceptorOperationFuture request = cancelQueue.poll(); if ( request == null ) { break; } // close the channels for ( SocketAddress socketAddress : request.getLocalAddresses() ) { H handle = boundHandles.remove( socketAddress ); if ( handle == null ) { continue; } try { close( handle ); wakeup(); // wake up again to trigger thread death } catch ( Throwable e ) { ExceptionMonitor.getInstance().exceptionCaught( e ); } finally { nHandles++; } } request.setDone(); } return nHandles; } private void notifyIdleSessions( long currentTime ) { // process idle sessions if ( currentTime - lastIdleCheckTime >= 1000 ) { lastIdleCheckTime = currentTime; AbstractIoSession.notifyIdleness( getListeners().getManagedSessions().values().iterator(), currentTime ); } } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/polling/AbstractPollingIoProcessor.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/polling/AbstractPollingIoProcessor0000644000175000017500000011724212032276030032647 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.polling; import java.io.IOException; import java.net.PortUnreachableException; import java.nio.channels.ClosedSelectorException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.file.FileRegion; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.filterchain.IoFilterChainBuilder; import org.apache.mina.core.future.DefaultIoFuture; import org.apache.mina.core.service.AbstractIoService; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.IoServiceListenerSupport; import org.apache.mina.core.session.AbstractIoSession; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionConfig; import org.apache.mina.core.session.SessionState; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.core.write.WriteRequestQueue; import org.apache.mina.core.write.WriteToClosedSessionException; import org.apache.mina.transport.socket.AbstractDatagramSessionConfig; import org.apache.mina.util.ExceptionMonitor; import org.apache.mina.util.NamePreservingRunnable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An abstract implementation of {@link IoProcessor} which helps transport * developers to write an {@link IoProcessor} easily. This class is in charge of * active polling a set of {@link IoSession} and trigger events when some I/O * operation is possible. * * @author Apache MINA Project * * @param the type of the {@link IoSession} this processor can handle */ public abstract class AbstractPollingIoProcessor implements IoProcessor { /** A logger for this class */ private final static Logger LOG = LoggerFactory.getLogger(IoProcessor.class); /** * The maximum loop count for a write operation until * {@link #write(AbstractIoSession, IoBuffer, int)} returns non-zero value. * It is similar to what a spin lock is for in concurrency programming. It * improves memory utilization and write throughput significantly. */ private static final int WRITE_SPIN_COUNT = 256; /** * A timeout used for the select, as we need to get out to deal with idle * sessions */ private static final long SELECT_TIMEOUT = 1000L; /** A map containing the last Thread ID for each class */ private static final ConcurrentHashMap, AtomicInteger> threadIds = new ConcurrentHashMap, AtomicInteger>(); /** This IoProcessor instance name */ private final String threadName; /** The executor to use when we need to start the inner Processor */ private final Executor executor; /** A Session queue containing the newly created sessions */ private final Queue newSessions = new ConcurrentLinkedQueue(); /** A queue used to store the sessions to be removed */ private final Queue removingSessions = new ConcurrentLinkedQueue(); /** A queue used to store the sessions to be flushed */ private final Queue flushingSessions = new ConcurrentLinkedQueue(); /** * A queue used to store the sessions which have a trafficControl to be * updated */ private final Queue trafficControllingSessions = new ConcurrentLinkedQueue(); /** The processor thread : it handles the incoming messages */ private final AtomicReference processorRef = new AtomicReference(); private long lastIdleCheckTime; private final Object disposalLock = new Object(); private volatile boolean disposing; private volatile boolean disposed; private final DefaultIoFuture disposalFuture = new DefaultIoFuture(null); protected AtomicBoolean wakeupCalled = new AtomicBoolean(false); /** * Create an {@link AbstractPollingIoProcessor} with the given * {@link Executor} for handling I/Os events. * * @param executor * the {@link Executor} for handling I/O events */ protected AbstractPollingIoProcessor(Executor executor) { if (executor == null) { throw new IllegalArgumentException("executor"); } this.threadName = nextThreadName(); this.executor = executor; } /** * Compute the thread ID for this class instance. As we may have different * classes, we store the last ID number into a Map associating the class * name to the last assigned ID. * * @return a name for the current thread, based on the class name and an * incremental value, starting at 1. */ private String nextThreadName() { Class cls = getClass(); int newThreadId; AtomicInteger threadId = threadIds.putIfAbsent(cls, new AtomicInteger(1)); if (threadId == null) { newThreadId = 1; } else { // Just increment the last ID, and get it. newThreadId = threadId.incrementAndGet(); } // Now we can compute the name for this thread return cls.getSimpleName() + '-' + newThreadId; } /** * {@inheritDoc} */ public final boolean isDisposing() { return disposing; } /** * {@inheritDoc} */ public final boolean isDisposed() { return disposed; } /** * {@inheritDoc} */ public final void dispose() { if (disposed || disposing) { return; } synchronized (disposalLock) { disposing = true; startupProcessor(); } disposalFuture.awaitUninterruptibly(); disposed = true; } /** * Dispose the resources used by this {@link IoProcessor} for polling the * client connections. The implementing class doDispose method will be called. * * @throws Exception if some low level IO error occurs */ protected abstract void doDispose() throws Exception; /** * poll those sessions for the given timeout * * @param timeout * milliseconds before the call timeout if no event appear * @return The number of session ready for read or for write * @throws Exception * if some low level IO error occurs */ protected abstract int select(long timeout) throws Exception; /** * poll those sessions forever * * @return The number of session ready for read or for write * @throws Exception * if some low level IO error occurs */ protected abstract int select() throws Exception; /** * Say if the list of {@link IoSession} polled by this {@link IoProcessor} * is empty * * @return true if at least a session is managed by this {@link IoProcessor} */ protected abstract boolean isSelectorEmpty(); /** * Interrupt the {@link AbstractPollingIoProcessor#select(int) call. */ protected abstract void wakeup(); /** * Get an {@link Iterator} for the list of {@link IoSession} polled by this * {@link IoProcessor} * * @return {@link Iterator} of {@link IoSession} */ protected abstract Iterator allSessions(); /** * Get an {@link Iterator} for the list of {@link IoSession} found selected * by the last call of {@link AbstractPollingIoProcessor#select(int) * @return {@link Iterator} of {@link IoSession} read for I/Os operation */ protected abstract Iterator selectedSessions(); /** * Get the state of a session (preparing, open, closed) * * @param session * the {@link IoSession} to inspect * @return the state of the session */ protected abstract SessionState getState(S session); /** * Is the session ready for writing * * @param session * the session queried * @return true is ready, false if not ready */ protected abstract boolean isWritable(S session); /** * Is the session ready for reading * * @param session * the session queried * @return true is ready, false if not ready */ protected abstract boolean isReadable(S session); /** * register a session for writing * * @param session * the session registered * @param isInterested * true for registering, false for removing */ protected abstract void setInterestedInWrite(S session, boolean isInterested) throws Exception; /** * register a session for reading * * @param session * the session registered * @param isInterested * true for registering, false for removing */ protected abstract void setInterestedInRead(S session, boolean isInterested) throws Exception; /** * is this session registered for reading * * @param session * the session queried * @return true is registered for reading */ protected abstract boolean isInterestedInRead(S session); /** * is this session registered for writing * * @param session * the session queried * @return true is registered for writing */ protected abstract boolean isInterestedInWrite(S session); /** * Initialize the polling of a session. Add it to the polling process. * * @param session the {@link IoSession} to add to the polling * @throws Exception any exception thrown by the underlying system calls */ protected abstract void init(S session) throws Exception; /** * Destroy the underlying client socket handle * * @param session * the {@link IoSession} * @throws Exception * any exception thrown by the underlying system calls */ protected abstract void destroy(S session) throws Exception; /** * Reads a sequence of bytes from a {@link IoSession} into the given * {@link IoBuffer}. Is called when the session was found ready for reading. * * @param session * the session to read * @param buf * the buffer to fill * @return the number of bytes read * @throws Exception * any exception thrown by the underlying system calls */ protected abstract int read(S session, IoBuffer buf) throws Exception; /** * Write a sequence of bytes to a {@link IoSession}, means to be called when * a session was found ready for writing. * * @param session * the session to write * @param buf * the buffer to write * @param length * the number of bytes to write can be superior to the number of * bytes remaining in the buffer * @return the number of byte written * @throws Exception * any exception thrown by the underlying system calls */ protected abstract int write(S session, IoBuffer buf, int length) throws Exception; /** * Write a part of a file to a {@link IoSession}, if the underlying API * isn't supporting system calls like sendfile(), you can throw a * {@link UnsupportedOperationException} so the file will be send using * usual {@link #write(AbstractIoSession, IoBuffer, int)} call. * * @param session * the session to write * @param region * the file region to write * @param length * the length of the portion to send * @return the number of written bytes * @throws Exception * any exception thrown by the underlying system calls */ protected abstract int transferFile(S session, FileRegion region, int length) throws Exception; /** * {@inheritDoc} */ public final void add(S session) { if (disposed || disposing) { throw new IllegalStateException("Already disposed."); } // Adds the session to the newSession queue and starts the worker newSessions.add(session); startupProcessor(); } /** * {@inheritDoc} */ public final void remove(S session) { scheduleRemove(session); startupProcessor(); } private void scheduleRemove(S session) { removingSessions.add(session); } /** * {@inheritDoc} */ public void write(S session, WriteRequest writeRequest) { WriteRequestQueue writeRequestQueue = session.getWriteRequestQueue(); writeRequestQueue.offer(session, writeRequest); if (!session.isWriteSuspended()) { this.flush(session); } } /** * {@inheritDoc} */ public final void flush(S session) { // add the session to the queue if it's not already // in the queue, then wake up the select() if (session.setScheduledForFlush(true)) { flushingSessions.add(session); wakeup(); } } private void scheduleFlush(S session) { // add the session to the queue if it's not already // in the queue if (session.setScheduledForFlush(true)) { flushingSessions.add(session); } } /** * {@inheritDoc} */ public final void updateTrafficMask(S session) { trafficControllingSessions.add(session); wakeup(); } /** * Starts the inner Processor, asking the executor to pick a thread in its * pool. The Runnable will be renamed */ private void startupProcessor() { Processor processor = processorRef.get(); if (processor == null) { processor = new Processor(); if (processorRef.compareAndSet(null, processor)) { executor.execute(new NamePreservingRunnable(processor, threadName)); } } // Just stop the select() and start it again, so that the processor // can be activated immediately. wakeup(); } /** * In the case we are using the java select() method, this method is used to * trash the buggy selector and create a new one, registring all the sockets * on it. * * @throws IOException * If we got an exception */ abstract protected void registerNewSelector() throws IOException; /** * Check that the select() has not exited immediately just because of a * broken connection. In this case, this is a standard case, and we just * have to loop. * * @return true if a connection has been brutally closed. * @throws IOException * If we got an exception */ abstract protected boolean isBrokenConnection() throws IOException; /** * Loops over the new sessions blocking queue and returns the number of * sessions which are effectively created * * @return The number of new sessions */ private int handleNewSessions() { int addedSessions = 0; for (S session = newSessions.poll(); session != null; session = newSessions.poll()) { if (addNow(session)) { // A new session has been created addedSessions++; } } return addedSessions; } /** * Process a new session : * - initialize it * - create its chain * - fire the CREATED listeners if any * * @param session The session to create * @return true if the session has been registered */ private boolean addNow(S session) { boolean registered = false; try { init(session); registered = true; // Build the filter chain of this session. IoFilterChainBuilder chainBuilder = session.getService().getFilterChainBuilder(); chainBuilder.buildFilterChain(session.getFilterChain()); // DefaultIoFilterChain.CONNECT_FUTURE is cleared inside here // in AbstractIoFilterChain.fireSessionOpened(). // Propagate the SESSION_CREATED event up to the chain IoServiceListenerSupport listeners = ((AbstractIoService) session.getService()).getListeners(); listeners.fireSessionCreated(session); } catch (Throwable e) { ExceptionMonitor.getInstance().exceptionCaught(e); try { destroy(session); } catch (Exception e1) { ExceptionMonitor.getInstance().exceptionCaught(e1); } finally { registered = false; } } return registered; } private int removeSessions() { int removedSessions = 0; for (S session = removingSessions.poll(); session != null; session = removingSessions.poll()) { SessionState state = getState(session); // Now deal with the removal accordingly to the session's state switch (state) { case OPENED: // Try to remove this session if (removeNow(session)) { removedSessions++; } break; case CLOSING: // Skip if channel is already closed break; case OPENING: // Remove session from the newSessions queue and // remove it newSessions.remove(session); if (removeNow(session)) { removedSessions++; } break; default: throw new IllegalStateException(String.valueOf(state)); } } return removedSessions; } private boolean removeNow(S session) { clearWriteRequestQueue(session); try { destroy(session); return true; } catch (Exception e) { IoFilterChain filterChain = session.getFilterChain(); filterChain.fireExceptionCaught(e); } finally { clearWriteRequestQueue(session); ((AbstractIoService) session.getService()).getListeners().fireSessionDestroyed(session); } return false; } private void clearWriteRequestQueue(S session) { WriteRequestQueue writeRequestQueue = session.getWriteRequestQueue(); WriteRequest req; List failedRequests = new ArrayList(); if ((req = writeRequestQueue.poll(session)) != null) { Object message = req.getMessage(); if (message instanceof IoBuffer) { IoBuffer buf = (IoBuffer) message; // The first unwritten empty buffer must be // forwarded to the filter chain. if (buf.hasRemaining()) { buf.reset(); failedRequests.add(req); } else { IoFilterChain filterChain = session.getFilterChain(); filterChain.fireMessageSent(req); } } else { failedRequests.add(req); } // Discard others. while ((req = writeRequestQueue.poll(session)) != null) { failedRequests.add(req); } } // Create an exception and notify. if (!failedRequests.isEmpty()) { WriteToClosedSessionException cause = new WriteToClosedSessionException(failedRequests); for (WriteRequest r : failedRequests) { session.decreaseScheduledBytesAndMessages(r); r.getFuture().setException(cause); } IoFilterChain filterChain = session.getFilterChain(); filterChain.fireExceptionCaught(cause); } } private void process() throws Exception { for (Iterator i = selectedSessions(); i.hasNext();) { S session = i.next(); process(session); i.remove(); } } /** * Deal with session ready for the read or write operations, or both. */ private void process(S session) { // Process Reads if (isReadable(session) && !session.isReadSuspended()) { read(session); } // Process writes if (isWritable(session) && !session.isWriteSuspended()) { // add the session to the queue, if it's not already there if (session.setScheduledForFlush(true)) { flushingSessions.add(session); } } } private void read(S session) { IoSessionConfig config = session.getConfig(); int bufferSize = config.getReadBufferSize(); IoBuffer buf = IoBuffer.allocate(bufferSize); final boolean hasFragmentation = session.getTransportMetadata().hasFragmentation(); try { int readBytes = 0; int ret; try { if (hasFragmentation) { while ((ret = read(session, buf)) > 0) { readBytes += ret; if (!buf.hasRemaining()) { break; } } } else { ret = read(session, buf); if (ret > 0) { readBytes = ret; } } } finally { buf.flip(); } if (readBytes > 0) { IoFilterChain filterChain = session.getFilterChain(); filterChain.fireMessageReceived(buf); buf = null; if (hasFragmentation) { if (readBytes << 1 < config.getReadBufferSize()) { session.decreaseReadBufferSize(); } else if (readBytes == config.getReadBufferSize()) { session.increaseReadBufferSize(); } } } if (ret < 0) { scheduleRemove(session); } } catch (Throwable e) { if (e instanceof IOException) { if (!(e instanceof PortUnreachableException) || !AbstractDatagramSessionConfig.class.isAssignableFrom(config.getClass()) || ((AbstractDatagramSessionConfig) config).isCloseOnPortUnreachable()) { scheduleRemove(session); } } IoFilterChain filterChain = session.getFilterChain(); filterChain.fireExceptionCaught(e); } } private static String byteArrayToHex(byte[] barray) { char[] c = new char[barray.length * 2]; int pos = 0; for (byte b : barray) { int bb = (b & 0x00FF) >> 4; c[pos++] = (char) (bb > 9 ? bb + 0x37 : bb + 0x30); bb = b & 0x0F; c[pos++] = (char) (bb > 9 ? bb + 0x37 : bb + 0x30); if (pos > 60) { break; } } return new String(c); } private void notifyIdleSessions(long currentTime) throws Exception { // process idle sessions if (currentTime - lastIdleCheckTime >= SELECT_TIMEOUT) { lastIdleCheckTime = currentTime; AbstractIoSession.notifyIdleness(allSessions(), currentTime); } } /** * Write all the pending messages */ private void flush(long currentTime) { if (flushingSessions.isEmpty()) { return; } do { S session = flushingSessions.poll(); // the same one with firstSession if (session == null) { // Just in case ... It should not happen. break; } // Reset the Schedule for flush flag for this session, // as we are flushing it now session.unscheduledForFlush(); SessionState state = getState(session); switch (state) { case OPENED: try { boolean flushedAll = flushNow(session, currentTime); if (flushedAll && !session.getWriteRequestQueue().isEmpty(session) && !session.isScheduledForFlush()) { scheduleFlush(session); } } catch (Exception e) { scheduleRemove(session); IoFilterChain filterChain = session.getFilterChain(); filterChain.fireExceptionCaught(e); } break; case CLOSING: // Skip if the channel is already closed. break; case OPENING: // Retry later if session is not yet fully initialized. // (In case that Session.write() is called before addSession() // is processed) scheduleFlush(session); return; default: throw new IllegalStateException(String.valueOf(state)); } } while (!flushingSessions.isEmpty()); } private boolean flushNow(S session, long currentTime) { if (!session.isConnected()) { scheduleRemove(session); return false; } final boolean hasFragmentation = session.getTransportMetadata().hasFragmentation(); final WriteRequestQueue writeRequestQueue = session.getWriteRequestQueue(); // Set limitation for the number of written bytes for read-write // fairness. I used maxReadBufferSize * 3 / 2, which yields best // performance in my experience while not breaking fairness much. final int maxWrittenBytes = session.getConfig().getMaxReadBufferSize() + (session.getConfig().getMaxReadBufferSize() >>> 1); int writtenBytes = 0; WriteRequest req = null; try { // Clear OP_WRITE setInterestedInWrite(session, false); do { // Check for pending writes. req = session.getCurrentWriteRequest(); if (req == null) { req = writeRequestQueue.poll(session); if (req == null) { break; } session.setCurrentWriteRequest(req); } int localWrittenBytes = 0; Object message = req.getMessage(); if (message instanceof IoBuffer) { localWrittenBytes = writeBuffer(session, req, hasFragmentation, maxWrittenBytes - writtenBytes, currentTime); if ((localWrittenBytes > 0) && ((IoBuffer) message).hasRemaining()) { // the buffer isn't empty, we re-interest it in writing writtenBytes += localWrittenBytes; setInterestedInWrite(session, true); return false; } } else if (message instanceof FileRegion) { localWrittenBytes = writeFile(session, req, hasFragmentation, maxWrittenBytes - writtenBytes, currentTime); // Fix for Java bug on Linux // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5103988 // If there's still data to be written in the FileRegion, // return 0 indicating that we need // to pause until writing may resume. if ((localWrittenBytes > 0) && (((FileRegion) message).getRemainingBytes() > 0)) { writtenBytes += localWrittenBytes; setInterestedInWrite(session, true); return false; } } else { throw new IllegalStateException("Don't know how to handle message of type '" + message.getClass().getName() + "'. Are you missing a protocol encoder?"); } if (localWrittenBytes == 0) { // Kernel buffer is full. setInterestedInWrite(session, true); return false; } writtenBytes += localWrittenBytes; if (writtenBytes >= maxWrittenBytes) { // Wrote too much scheduleFlush(session); return false; } } while (writtenBytes < maxWrittenBytes); } catch (Exception e) { if (req != null) { req.getFuture().setException(e); } IoFilterChain filterChain = session.getFilterChain(); filterChain.fireExceptionCaught(e); return false; } return true; } private int writeBuffer(S session, WriteRequest req, boolean hasFragmentation, int maxLength, long currentTime) throws Exception { IoBuffer buf = (IoBuffer) req.getMessage(); int localWrittenBytes = 0; if (buf.hasRemaining()) { int length; if (hasFragmentation) { length = Math.min(buf.remaining(), maxLength); } else { length = buf.remaining(); } try { localWrittenBytes = write(session, buf, length); } catch (IOException ioe) { // We have had an issue while trying to send data to the // peer : let's close the session. session.close(true); } } session.increaseWrittenBytes(localWrittenBytes, currentTime); if (!buf.hasRemaining() || (!hasFragmentation && (localWrittenBytes != 0))) { // Buffer has been sent, clear the current request. int pos = buf.position(); buf.reset(); fireMessageSent(session, req); // And set it back to its position buf.position(pos); } return localWrittenBytes; } private int writeFile(S session, WriteRequest req, boolean hasFragmentation, int maxLength, long currentTime) throws Exception { int localWrittenBytes; FileRegion region = (FileRegion) req.getMessage(); if (region.getRemainingBytes() > 0) { int length; if (hasFragmentation) { length = (int) Math.min(region.getRemainingBytes(), maxLength); } else { length = (int) Math.min(Integer.MAX_VALUE, region.getRemainingBytes()); } localWrittenBytes = transferFile(session, region, length); region.update(localWrittenBytes); } else { localWrittenBytes = 0; } session.increaseWrittenBytes(localWrittenBytes, currentTime); if ((region.getRemainingBytes() <= 0) || (!hasFragmentation && (localWrittenBytes != 0))) { fireMessageSent(session, req); } return localWrittenBytes; } private void fireMessageSent(S session, WriteRequest req) { session.setCurrentWriteRequest(null); IoFilterChain filterChain = session.getFilterChain(); filterChain.fireMessageSent(req); } /** * Update the trafficControl for all the session. */ private void updateTrafficMask() { int queueSize = trafficControllingSessions.size(); while (queueSize > 0) { S session = trafficControllingSessions.poll(); if (session == null) { // We are done with this queue. return; } SessionState state = getState(session); switch (state) { case OPENED: updateTrafficControl(session); break; case CLOSING: break; case OPENING: // Retry later if session is not yet fully initialized. // (In case that Session.suspend??() or session.resume??() is // called before addSession() is processed) // We just put back the session at the end of the queue. trafficControllingSessions.add(session); break; default: throw new IllegalStateException(String.valueOf(state)); } // As we have handled one session, decrement the number of // remaining sessions. The OPENING session will be processed // with the next select(), as the queue size has been decreased, even // if the session has been pushed at the end of the queue queueSize--; } } /** * {@inheritDoc} */ public void updateTrafficControl(S session) { // try { setInterestedInRead(session, !session.isReadSuspended()); } catch (Exception e) { IoFilterChain filterChain = session.getFilterChain(); filterChain.fireExceptionCaught(e); } try { setInterestedInWrite(session, !session.getWriteRequestQueue().isEmpty(session) && !session.isWriteSuspended()); } catch (Exception e) { IoFilterChain filterChain = session.getFilterChain(); filterChain.fireExceptionCaught(e); } } /** * The main loop. This is the place in charge to poll the Selector, and to * process the active sessions. It's done in * - handle the newly created sessions * - */ private class Processor implements Runnable { public void run() { assert (processorRef.get() == this); int nSessions = 0; lastIdleCheckTime = System.currentTimeMillis(); for (;;) { try { // This select has a timeout so that we can manage // idle session when we get out of the select every // second. (note : this is a hack to avoid creating // a dedicated thread). long t0 = System.currentTimeMillis(); int selected = select(SELECT_TIMEOUT); long t1 = System.currentTimeMillis(); long delta = (t1 - t0); if ((selected == 0) && !wakeupCalled.get() && (delta < 100)) { // Last chance : the select() may have been // interrupted because we have had an closed channel. if (isBrokenConnection()) { LOG.warn("Broken connection"); // we can reselect immediately // set back the flag to false wakeupCalled.getAndSet(false); continue; } else { LOG.warn("Create a new selector. Selected is 0, delta = " + (t1 - t0)); // Ok, we are hit by the nasty epoll // spinning. // Basically, there is a race condition // which causes a closing file descriptor not to be // considered as available as a selected channel, but // it stopped the select. The next time we will // call select(), it will exit immediately for the same // reason, and do so forever, consuming 100% // CPU. // We have to destroy the selector, and // register all the socket on a new one. registerNewSelector(); } // Set back the flag to false wakeupCalled.getAndSet(false); // and continue the loop continue; } // Manage newly created session first nSessions += handleNewSessions(); updateTrafficMask(); // Now, if we have had some incoming or outgoing events, // deal with them if (selected > 0) { //LOG.debug("Processing ..."); // This log hurts one of the MDCFilter test... process(); } // Write the pending requests long currentTime = System.currentTimeMillis(); flush(currentTime); // And manage removed sessions nSessions -= removeSessions(); // Last, not least, send Idle events to the idle sessions notifyIdleSessions(currentTime); // Get a chance to exit the infinite loop if there are no // more sessions on this Processor if (nSessions == 0) { processorRef.set(null); if (newSessions.isEmpty() && isSelectorEmpty()) { // newSessions.add() precedes startupProcessor assert (processorRef.get() != this); break; } assert (processorRef.get() != this); if (!processorRef.compareAndSet(null, this)) { // startupProcessor won race, so must exit processor assert (processorRef.get() != this); break; } assert (processorRef.get() == this); } // Disconnect all sessions immediately if disposal has been // requested so that we exit this loop eventually. if (isDisposing()) { for (Iterator i = allSessions(); i.hasNext();) { scheduleRemove(i.next()); } wakeup(); } } catch (ClosedSelectorException cse) { // If the selector has been closed, we can exit the loop break; } catch (Throwable t) { ExceptionMonitor.getInstance().exceptionCaught(t); try { Thread.sleep(1000); } catch (InterruptedException e1) { ExceptionMonitor.getInstance().exceptionCaught(e1); } } } try { synchronized (disposalLock) { if (disposing) { doDispose(); } } } catch (Throwable t) { ExceptionMonitor.getInstance().exceptionCaught(t); } finally { disposalFuture.setValue(true); } } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/polling/package.html0000644000175000017500000000223112032276030027714 0ustar ebourgebourg Base class for implementing transport based on active polling strategies like NIO select call, or any API based on I/O polling system calls (epoll, poll, select, kqueue, etc). Know implementations are org.apache.mina.transport.socket.nio and org.apache.mina.transport.socket.apr. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/write/0000755000175000017500000000000012162575507025142 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/write/DefaultWriteRequest.java0000644000175000017500000001226412032276032031745 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.write; import java.net.SocketAddress; import java.util.concurrent.TimeUnit; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.session.IoSession; /** * The default implementation of {@link WriteRequest}. * * @author Apache MINA Project */ public class DefaultWriteRequest implements WriteRequest { private static final WriteFuture UNUSED_FUTURE = new WriteFuture() { public boolean isWritten() { return false; } public void setWritten() { // Do nothing } public IoSession getSession() { return null; } public void join() { // Do nothing } public boolean join(long timeoutInMillis) { return true; } public boolean isDone() { return true; } public WriteFuture addListener(IoFutureListener listener) { throw new IllegalStateException("You can't add a listener to a dummy future."); } public WriteFuture removeListener(IoFutureListener listener) { throw new IllegalStateException("You can't add a listener to a dummy future."); } public WriteFuture await() throws InterruptedException { return this; } public boolean await(long timeout, TimeUnit unit) throws InterruptedException { return true; } public boolean await(long timeoutMillis) throws InterruptedException { return true; } public WriteFuture awaitUninterruptibly() { return this; } public boolean awaitUninterruptibly(long timeout, TimeUnit unit) { return true; } public boolean awaitUninterruptibly(long timeoutMillis) { return true; } public Throwable getException() { return null; } public void setException(Throwable cause) { // Do nothing } }; private final Object message; private final WriteFuture future; private final SocketAddress destination; /** * Creates a new instance without {@link WriteFuture}. You'll get * an instance of {@link WriteFuture} even if you called this constructor * because {@link #getFuture()} will return a bogus future. */ public DefaultWriteRequest(Object message) { this(message, null, null); } /** * Creates a new instance with {@link WriteFuture}. */ public DefaultWriteRequest(Object message, WriteFuture future) { this(message, future, null); } /** * Creates a new instance. * * @param message a message to write * @param future a future that needs to be notified when an operation is finished * @param destination the destination of the message. This property will be * ignored unless the transport supports it. */ public DefaultWriteRequest(Object message, WriteFuture future, SocketAddress destination) { if (message == null) { throw new IllegalArgumentException("message"); } if (future == null) { future = UNUSED_FUTURE; } this.message = message; this.future = future; this.destination = destination; } public WriteFuture getFuture() { return future; } public Object getMessage() { return message; } public WriteRequest getOriginalRequest() { return this; } public SocketAddress getDestination() { return destination; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("WriteRequest: "); // Special case for the CLOSE_REQUEST writeRequest : it just // carries a native Object instance if (message.getClass().getName().equals(Object.class.getName())) { sb.append("CLOSE_REQUEST"); } else { if (getDestination() == null) { sb.append(message); } else { sb.append(message); sb.append(" => "); sb.append(getDestination()); } } return sb.toString(); } public boolean isEncoded() { return false; } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/write/WriteTimeoutException.java0000644000175000017500000000424412032276032032314 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.write; import java.util.Collection; import org.apache.mina.core.session.IoSessionConfig; /** * An exception which is thrown when write buffer is not flushed for * {@link IoSessionConfig#getWriteTimeout()} seconds. * * @author Apache MINA Project */ public class WriteTimeoutException extends WriteException { private static final long serialVersionUID = 3906931157944579121L; public WriteTimeoutException(Collection requests, String message, Throwable cause) { super(requests, message, cause); } public WriteTimeoutException(Collection requests, String s) { super(requests, s); } public WriteTimeoutException(Collection requests, Throwable cause) { super(requests, cause); } public WriteTimeoutException(Collection requests) { super(requests); } public WriteTimeoutException(WriteRequest request, String message, Throwable cause) { super(request, message, cause); } public WriteTimeoutException(WriteRequest request, String s) { super(request, s); } public WriteTimeoutException(WriteRequest request, Throwable cause) { super(request, cause); } public WriteTimeoutException(WriteRequest request) { super(request); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/write/WriteRequest.java0000644000175000017500000000364112032276032030437 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.write; import java.net.SocketAddress; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.session.IoSession; /** * Represents write request fired by {@link IoSession#write(Object)}. * * @author Apache MINA Project */ public interface WriteRequest { /** * Returns the {@link WriteRequest} which was requested originally, * which is not transformed by any {@link IoFilter}. */ WriteRequest getOriginalRequest(); /** * Returns {@link WriteFuture} that is associated with this write request. */ WriteFuture getFuture(); /** * Returns a message object to be written. */ Object getMessage(); /** * Returns the destination of this write request. * * @return null for the default destination */ SocketAddress getDestination(); /** * Tells if the current message has been encoded * * @return true if the message has already been encoded */ boolean isEncoded(); }././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/write/WriteToClosedSessionException.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/write/WriteToClosedSessionExceptio0000644000175000017500000000424612032276032032652 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.write; import java.util.Collection; /** * An exception which is thrown when one or more write operations were * attempted on a closed session. * * @author Apache MINA Project */ public class WriteToClosedSessionException extends WriteException { private static final long serialVersionUID = 5550204573739301393L; public WriteToClosedSessionException(Collection requests, String message, Throwable cause) { super(requests, message, cause); } public WriteToClosedSessionException(Collection requests, String s) { super(requests, s); } public WriteToClosedSessionException(Collection requests, Throwable cause) { super(requests, cause); } public WriteToClosedSessionException(Collection requests) { super(requests); } public WriteToClosedSessionException(WriteRequest request, String message, Throwable cause) { super(request, message, cause); } public WriteToClosedSessionException(WriteRequest request, String s) { super(request, s); } public WriteToClosedSessionException(WriteRequest request, Throwable cause) { super(request, cause); } public WriteToClosedSessionException(WriteRequest request) { super(request); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/write/NothingWrittenException.java0000644000175000017500000000416212032276032032635 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.write; import java.util.Collection; /** * An exception which is thrown when one or more write requests resulted * in no actual write operation. * * @author Apache MINA Project */ public class NothingWrittenException extends WriteException { private static final long serialVersionUID = -6331979307737691005L; public NothingWrittenException(Collection requests, String message, Throwable cause) { super(requests, message, cause); } public NothingWrittenException(Collection requests, String s) { super(requests, s); } public NothingWrittenException(Collection requests, Throwable cause) { super(requests, cause); } public NothingWrittenException(Collection requests) { super(requests); } public NothingWrittenException(WriteRequest request, String message, Throwable cause) { super(request, message, cause); } public NothingWrittenException(WriteRequest request, String s) { super(request, s); } public NothingWrittenException(WriteRequest request, Throwable cause) { super(request, cause); } public NothingWrittenException(WriteRequest request) { super(request); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/write/WriteRequestWrapper.java0000644000175000017500000000417012032276032031776 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.write; import java.net.SocketAddress; import org.apache.mina.core.future.WriteFuture; /** * A wrapper for an existing {@link WriteRequest}. * * @author Apache MINA Project */ public class WriteRequestWrapper implements WriteRequest { private final WriteRequest parentRequest; /** * Creates a new instance that wraps the specified request. */ public WriteRequestWrapper(WriteRequest parentRequest) { if (parentRequest == null) { throw new IllegalArgumentException("parentRequest"); } this.parentRequest = parentRequest; } public SocketAddress getDestination() { return parentRequest.getDestination(); } public WriteFuture getFuture() { return parentRequest.getFuture(); } public Object getMessage() { return parentRequest.getMessage(); } public WriteRequest getOriginalRequest() { return parentRequest.getOriginalRequest(); } /** * Returns the wrapped request object. */ public WriteRequest getParentRequest() { return parentRequest; } @Override public String toString() { return "WR Wrapper" + parentRequest.toString(); } public boolean isEncoded() { return false; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/write/WriteRequestQueue.java0000644000175000017500000000432012032276032031437 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.write; import org.apache.mina.core.session.IoSession; /** * Stores {@link WriteRequest}s which are queued to an {@link IoSession}. * * @author Apache MINA Project */ public interface WriteRequestQueue { /** * Get the first request available in the queue for a session. * @param session The session * @return The first available request, if any. */ WriteRequest poll(IoSession session); /** * Add a new WriteRequest to the session write's queue * @param session The session * @param writeRequest The writeRequest to add */ void offer(IoSession session, WriteRequest writeRequest); /** * Tells if the WriteRequest queue is empty or not for a session * @param session The session to check * @return true if the writeRequest is empty */ boolean isEmpty(IoSession session); /** * Removes all the requests from this session's queue. * @param session The associated session */ void clear(IoSession session); /** * Disposes any releases associated with the specified session. * This method is invoked on disconnection. * @param session The associated session */ void dispose(IoSession session); /** * Returns the number of objects currently stored in the queue. * @return */ int size(); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/write/WriteException.java0000644000175000017500000001051012032276032030736 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.write; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Set; import org.apache.mina.util.MapBackedSet; /** * An exception which is thrown when one or more write operations were failed. * * @author Apache MINA Project */ public class WriteException extends IOException { private static final long serialVersionUID = -4174407422754524197L; private final List requests; /** * Creates a new exception. */ public WriteException(WriteRequest request) { super(); this.requests = asRequestList(request); } /** * Creates a new exception. */ public WriteException(WriteRequest request, String s) { super(s); this.requests = asRequestList(request); } /** * Creates a new exception. */ public WriteException(WriteRequest request, String message, Throwable cause) { super(message); initCause(cause); this.requests = asRequestList(request); } /** * Creates a new exception. */ public WriteException(WriteRequest request, Throwable cause) { initCause(cause); this.requests = asRequestList(request); } /** * Creates a new exception. */ public WriteException(Collection requests) { super(); this.requests = asRequestList(requests); } /** * Creates a new exception. */ public WriteException(Collection requests, String s) { super(s); this.requests = asRequestList(requests); } /** * Creates a new exception. */ public WriteException(Collection requests, String message, Throwable cause) { super(message); initCause(cause); this.requests = asRequestList(requests); } /** * Creates a new exception. */ public WriteException(Collection requests, Throwable cause) { initCause(cause); this.requests = asRequestList(requests); } /** * Returns the list of the failed {@link WriteRequest}, in the order of occurrance. */ public List getRequests() { return requests; } /** * Returns the firstly failed {@link WriteRequest}. */ public WriteRequest getRequest() { return requests.get(0); } private static List asRequestList(Collection requests) { if (requests == null) { throw new IllegalArgumentException("requests"); } if (requests.isEmpty()) { throw new IllegalArgumentException("requests is empty."); } // Create a list of requests removing duplicates. Set newRequests = new MapBackedSet(new LinkedHashMap()); for (WriteRequest r : requests) { newRequests.add(r.getOriginalRequest()); } return Collections.unmodifiableList(new ArrayList(newRequests)); } private static List asRequestList(WriteRequest request) { if (request == null) { throw new IllegalArgumentException("request"); } List requests = new ArrayList(1); requests.add(request.getOriginalRequest()); return Collections.unmodifiableList(requests); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/filterchain/0000755000175000017500000000000012162575507026300 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/filterchain/IoFilterAdapter.java0000644000175000017500000000755112032276031032153 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.filterchain; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; /** * An adapter class for {@link IoFilter}. You can extend * this class and selectively override required event filter methods only. All * methods forwards events to the next filter by default. * * @author Apache MINA Project */ public class IoFilterAdapter implements IoFilter { /** * {@inheritDoc} */ public void init() throws Exception { } /** * {@inheritDoc} */ public void destroy() throws Exception { } /** * {@inheritDoc} */ public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { } /** * {@inheritDoc} */ public void onPostAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { } /** * {@inheritDoc} */ public void onPreRemove(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { } /** * {@inheritDoc} */ public void onPostRemove(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { } /** * {@inheritDoc} */ public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception { nextFilter.sessionCreated(session); } /** * {@inheritDoc} */ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception { nextFilter.sessionOpened(session); } /** * {@inheritDoc} */ public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception { nextFilter.sessionClosed(session); } /** * {@inheritDoc} */ public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception { nextFilter.sessionIdle(session, status); } /** * {@inheritDoc} */ public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) throws Exception { nextFilter.exceptionCaught(session, cause); } /** * {@inheritDoc} */ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception { nextFilter.messageReceived(session, message); } /** * {@inheritDoc} */ public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { nextFilter.messageSent(session, writeRequest); } /** * {@inheritDoc} */ public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { nextFilter.filterWrite(session, writeRequest); } /** * {@inheritDoc} */ public void filterClose(NextFilter nextFilter, IoSession session) throws Exception { nextFilter.filterClose(session); } public String toString() { return this.getClass().getSimpleName(); } }././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/filterchain/DefaultIoFilterChainBuilder.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/filterchain/DefaultIoFilterChainBu0000644000175000017500000004063512032276031032471 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.filterchain; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Random; import java.util.concurrent.CopyOnWriteArrayList; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.filterchain.IoFilterChain.Entry; import org.apache.mina.core.session.IoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The default implementation of {@link IoFilterChainBuilder} which is useful * in most cases. {@link DefaultIoFilterChainBuilder} has an identical interface * with {@link IoFilter}; it contains a list of {@link IoFilter}s that you can * modify. The {@link IoFilter}s which are added to this builder will be appended * to the {@link IoFilterChain} when {@link #buildFilterChain(IoFilterChain)} is * invoked. *

* However, the identical interface doesn't mean that it behaves in an exactly * same way with {@link IoFilterChain}. {@link DefaultIoFilterChainBuilder} * doesn't manage the life cycle of the {@link IoFilter}s at all, and the * existing {@link IoSession}s won't get affected by the changes in this builder. * {@link IoFilterChainBuilder}s affect only newly created {@link IoSession}s. * *

 * IoAcceptor acceptor = ...;
 * DefaultIoFilterChainBuilder builder = acceptor.getFilterChain();
 * builder.addLast( "myFilter", new MyFilter() );
 * ...
 * 
* * @author Apache MINA Project * @org.apache.xbean.XBean */ public class DefaultIoFilterChainBuilder implements IoFilterChainBuilder { private final static Logger LOGGER = LoggerFactory.getLogger(DefaultIoFilterChainBuilder.class); private final List entries; /** * Creates a new instance with an empty filter list. */ public DefaultIoFilterChainBuilder() { entries = new CopyOnWriteArrayList(); } /** * Creates a new copy of the specified {@link DefaultIoFilterChainBuilder}. */ public DefaultIoFilterChainBuilder(DefaultIoFilterChainBuilder filterChain) { if (filterChain == null) { throw new IllegalArgumentException("filterChain"); } entries = new CopyOnWriteArrayList(filterChain.entries); } /** * @see IoFilterChain#getEntry(String) */ public Entry getEntry(String name) { for (Entry e : entries) { if (e.getName().equals(name)) { return e; } } return null; } /** * @see IoFilterChain#getEntry(IoFilter) */ public Entry getEntry(IoFilter filter) { for (Entry e : entries) { if (e.getFilter() == filter) { return e; } } return null; } /** * @see IoFilterChain#getEntry(Class) */ public Entry getEntry(Class filterType) { for (Entry e : entries) { if (filterType.isAssignableFrom(e.getFilter().getClass())) { return e; } } return null; } /** * @see IoFilterChain#get(String) */ public IoFilter get(String name) { Entry e = getEntry(name); if (e == null) { return null; } return e.getFilter(); } /** * @see IoFilterChain#get(Class) */ public IoFilter get(Class filterType) { Entry e = getEntry(filterType); if (e == null) { return null; } return e.getFilter(); } /** * @see IoFilterChain#getAll() */ public List getAll() { return new ArrayList(entries); } /** * @see IoFilterChain#getAllReversed() */ public List getAllReversed() { List result = getAll(); Collections.reverse(result); return result; } /** * @see IoFilterChain#contains(String) */ public boolean contains(String name) { return getEntry(name) != null; } /** * @see IoFilterChain#contains(IoFilter) */ public boolean contains(IoFilter filter) { return getEntry(filter) != null; } /** * @see IoFilterChain#contains(Class) */ public boolean contains(Class filterType) { return getEntry(filterType) != null; } /** * @see IoFilterChain#addFirst(String, IoFilter) */ public synchronized void addFirst(String name, IoFilter filter) { register(0, new EntryImpl(name, filter)); } /** * @see IoFilterChain#addLast(String, IoFilter) */ public synchronized void addLast(String name, IoFilter filter) { register(entries.size(), new EntryImpl(name, filter)); } /** * @see IoFilterChain#addBefore(String, String, IoFilter) */ public synchronized void addBefore(String baseName, String name, IoFilter filter) { checkBaseName(baseName); for (ListIterator i = entries.listIterator(); i.hasNext();) { Entry base = i.next(); if (base.getName().equals(baseName)) { register(i.previousIndex(), new EntryImpl(name, filter)); break; } } } /** * @see IoFilterChain#addAfter(String, String, IoFilter) */ public synchronized void addAfter(String baseName, String name, IoFilter filter) { checkBaseName(baseName); for (ListIterator i = entries.listIterator(); i.hasNext();) { Entry base = i.next(); if (base.getName().equals(baseName)) { register(i.nextIndex(), new EntryImpl(name, filter)); break; } } } /** * @see IoFilterChain#remove(String) */ public synchronized IoFilter remove(String name) { if (name == null) { throw new IllegalArgumentException("name"); } for (ListIterator i = entries.listIterator(); i.hasNext();) { Entry e = i.next(); if (e.getName().equals(name)) { entries.remove(i.previousIndex()); return e.getFilter(); } } throw new IllegalArgumentException("Unknown filter name: " + name); } /** * @see IoFilterChain#remove(IoFilter) */ public synchronized IoFilter remove(IoFilter filter) { if (filter == null) { throw new IllegalArgumentException("filter"); } for (ListIterator i = entries.listIterator(); i.hasNext();) { Entry e = i.next(); if (e.getFilter() == filter) { entries.remove(i.previousIndex()); return e.getFilter(); } } throw new IllegalArgumentException("Filter not found: " + filter.getClass().getName()); } /** * @see IoFilterChain#remove(Class) */ public synchronized IoFilter remove(Class filterType) { if (filterType == null) { throw new IllegalArgumentException("filterType"); } for (ListIterator i = entries.listIterator(); i.hasNext();) { Entry e = i.next(); if (filterType.isAssignableFrom(e.getFilter().getClass())) { entries.remove(i.previousIndex()); return e.getFilter(); } } throw new IllegalArgumentException("Filter not found: " + filterType.getName()); } public synchronized IoFilter replace(String name, IoFilter newFilter) { checkBaseName(name); EntryImpl e = (EntryImpl) getEntry(name); IoFilter oldFilter = e.getFilter(); e.setFilter(newFilter); return oldFilter; } public synchronized void replace(IoFilter oldFilter, IoFilter newFilter) { for (Entry e : entries) { if (e.getFilter() == oldFilter) { ((EntryImpl) e).setFilter(newFilter); return; } } throw new IllegalArgumentException("Filter not found: " + oldFilter.getClass().getName()); } public synchronized void replace(Class oldFilterType, IoFilter newFilter) { for (Entry e : entries) { if (oldFilterType.isAssignableFrom(e.getFilter().getClass())) { ((EntryImpl) e).setFilter(newFilter); return; } } throw new IllegalArgumentException("Filter not found: " + oldFilterType.getName()); } /** * @see IoFilterChain#clear() */ public synchronized void clear() { entries.clear(); } /** * Clears the current list of filters and adds the specified * filter mapping to this builder. Please note that you must specify * a {@link Map} implementation that iterates the filter mapping in the * order of insertion such as {@link LinkedHashMap}. Otherwise, it will * throw an {@link IllegalArgumentException}. */ public void setFilters(Map filters) { if (filters == null) { throw new IllegalArgumentException("filters"); } if (!isOrderedMap(filters)) { throw new IllegalArgumentException("filters is not an ordered map. Please try " + LinkedHashMap.class.getName() + "."); } filters = new LinkedHashMap(filters); for (Map.Entry e : filters.entrySet()) { if (e.getKey() == null) { throw new IllegalArgumentException("filters contains a null key."); } if (e.getValue() == null) { throw new IllegalArgumentException("filters contains a null value."); } } synchronized (this) { clear(); for (Map.Entry e : filters.entrySet()) { addLast(e.getKey(), e.getValue()); } } } @SuppressWarnings("unchecked") private boolean isOrderedMap(Map map) { Class mapType = map.getClass(); if (LinkedHashMap.class.isAssignableFrom(mapType)) { if (LOGGER.isDebugEnabled()) { LOGGER.debug(mapType.getSimpleName() + " is an ordered map."); } return true; } if (LOGGER.isDebugEnabled()) { LOGGER.debug(mapType.getName() + " is not a " + LinkedHashMap.class.getSimpleName()); } // Detect Jakarta Commons Collections OrderedMap implementations. Class type = mapType; while (type != null) { for (Class i : type.getInterfaces()) { if (i.getName().endsWith("OrderedMap")) { if (LOGGER.isDebugEnabled()) { LOGGER.debug(mapType.getSimpleName() + " is an ordered map (guessed from that it " + " implements OrderedMap interface.)"); } return true; } } type = type.getSuperclass(); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(mapType.getName() + " doesn't implement OrderedMap interface."); } // Last resort: try to create a new instance and test if it maintains // the insertion order. LOGGER.debug("Last resort; trying to create a new map instance with a " + "default constructor and test if insertion order is " + "maintained."); Map newMap; try { newMap = (Map) mapType.newInstance(); } catch (Exception e) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Failed to create a new map instance of '" + mapType.getName() + "'.", e); } return false; } Random rand = new Random(); List expectedNames = new ArrayList(); IoFilter dummyFilter = new IoFilterAdapter(); for (int i = 0; i < 65536; i++) { String filterName; do { filterName = String.valueOf(rand.nextInt()); } while (newMap.containsKey(filterName)); newMap.put(filterName, dummyFilter); expectedNames.add(filterName); Iterator it = expectedNames.iterator(); for (Object key : newMap.keySet()) { if (!it.next().equals(key)) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("The specified map didn't pass the insertion " + "order test after " + (i + 1) + " tries."); } return false; } } } if (LOGGER.isDebugEnabled()) { LOGGER.debug("The specified map passed the insertion order test."); } return true; } public void buildFilterChain(IoFilterChain chain) throws Exception { for (Entry e : entries) { chain.addLast(e.getName(), e.getFilter()); } } @Override public String toString() { StringBuilder buf = new StringBuilder(); buf.append("{ "); boolean empty = true; for (Entry e : entries) { if (!empty) { buf.append(", "); } else { empty = false; } buf.append('('); buf.append(e.getName()); buf.append(':'); buf.append(e.getFilter()); buf.append(')'); } if (empty) { buf.append("empty"); } buf.append(" }"); return buf.toString(); } private void checkBaseName(String baseName) { if (baseName == null) { throw new IllegalArgumentException("baseName"); } if (!contains(baseName)) { throw new IllegalArgumentException("Unknown filter name: " + baseName); } } private void register(int index, Entry e) { if (contains(e.getName())) { throw new IllegalArgumentException("Other filter is using the same name: " + e.getName()); } entries.add(index, e); } private class EntryImpl implements Entry { private final String name; private volatile IoFilter filter; private EntryImpl(String name, IoFilter filter) { if (name == null) { throw new IllegalArgumentException("name"); } if (filter == null) { throw new IllegalArgumentException("filter"); } this.name = name; this.filter = filter; } public String getName() { return name; } public IoFilter getFilter() { return filter; } private void setFilter(IoFilter filter) { this.filter = filter; } public NextFilter getNextFilter() { throw new IllegalStateException(); } @Override public String toString() { return "(" + getName() + ':' + filter + ')'; } public void addAfter(String name, IoFilter filter) { DefaultIoFilterChainBuilder.this.addAfter(getName(), name, filter); } public void addBefore(String name, IoFilter filter) { DefaultIoFilterChainBuilder.this.addBefore(getName(), name, filter); } public void remove() { DefaultIoFilterChainBuilder.this.remove(getName()); } public void replace(IoFilter newFilter) { DefaultIoFilterChainBuilder.this.replace(getName(), newFilter); } } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/filterchain/IoFilterLifeCycleException.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/filterchain/IoFilterLifeCycleExcep0000644000175000017500000000312112032276031032464 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.filterchain; /** * A {@link RuntimeException} which is thrown when {@link IoFilter#init()} * or {@link IoFilter#onPostAdd(IoFilterChain, String, org.apache.mina.core.filterchain.IoFilter.NextFilter)} * failed. * * @author Apache MINA Project */ public class IoFilterLifeCycleException extends RuntimeException { private static final long serialVersionUID = -5542098881633506449L; public IoFilterLifeCycleException() { } public IoFilterLifeCycleException(String message) { super(message); } public IoFilterLifeCycleException(String message, Throwable cause) { super(message, cause); } public IoFilterLifeCycleException(Throwable cause) { super(cause); } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/filterchain/DefaultIoFilterChain.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/filterchain/DefaultIoFilterChain.j0000644000175000017500000006767312032276031032445 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.filterchain; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.IoFuture; import org.apache.mina.core.session.AbstractIoSession; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.core.write.WriteRequestQueue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A default implementation of {@link IoFilterChain} that provides * all operations for developers who want to implement their own * transport layer once used with {@link AbstractIoSession}. * * @author Apache MINA Project */ public class DefaultIoFilterChain implements IoFilterChain { /** * A session attribute that stores an {@link IoFuture} related with * the {@link IoSession}. {@link DefaultIoFilterChain} clears this * attribute and notifies the future when {@link #fireSessionCreated()} * or {@link #fireExceptionCaught(Throwable)} is invoked. */ public static final AttributeKey SESSION_CREATED_FUTURE = new AttributeKey(DefaultIoFilterChain.class, "connectFuture"); /** The associated session */ private final AbstractIoSession session; private final Map name2entry = new ConcurrentHashMap(); /** The chain head */ private final EntryImpl head; /** The chain tail */ private final EntryImpl tail; /** The logger for this class */ private final static Logger LOGGER = LoggerFactory.getLogger(DefaultIoFilterChain.class); /** * Create a new default chain, associated with a session. It will only contain a * HeadFilter and a TailFilter. * * @param session The session associated with the created filter chain */ public DefaultIoFilterChain(AbstractIoSession session) { if (session == null) { throw new IllegalArgumentException("session"); } this.session = session; head = new EntryImpl(null, null, "head", new HeadFilter()); tail = new EntryImpl(head, null, "tail", new TailFilter()); head.nextEntry = tail; } public IoSession getSession() { return session; } public Entry getEntry(String name) { Entry e = name2entry.get(name); if (e == null) { return null; } return e; } public Entry getEntry(IoFilter filter) { EntryImpl e = head.nextEntry; while (e != tail) { if (e.getFilter() == filter) { return e; } e = e.nextEntry; } return null; } public Entry getEntry(Class filterType) { EntryImpl e = head.nextEntry; while (e != tail) { if (filterType.isAssignableFrom(e.getFilter().getClass())) { return e; } e = e.nextEntry; } return null; } public IoFilter get(String name) { Entry e = getEntry(name); if (e == null) { return null; } return e.getFilter(); } public IoFilter get(Class filterType) { Entry e = getEntry(filterType); if (e == null) { return null; } return e.getFilter(); } public NextFilter getNextFilter(String name) { Entry e = getEntry(name); if (e == null) { return null; } return e.getNextFilter(); } public NextFilter getNextFilter(IoFilter filter) { Entry e = getEntry(filter); if (e == null) { return null; } return e.getNextFilter(); } public NextFilter getNextFilter(Class filterType) { Entry e = getEntry(filterType); if (e == null) { return null; } return e.getNextFilter(); } public synchronized void addFirst(String name, IoFilter filter) { checkAddable(name); register(head, name, filter); } public synchronized void addLast(String name, IoFilter filter) { checkAddable(name); register(tail.prevEntry, name, filter); } public synchronized void addBefore(String baseName, String name, IoFilter filter) { EntryImpl baseEntry = checkOldName(baseName); checkAddable(name); register(baseEntry.prevEntry, name, filter); } public synchronized void addAfter(String baseName, String name, IoFilter filter) { EntryImpl baseEntry = checkOldName(baseName); checkAddable(name); register(baseEntry, name, filter); } public synchronized IoFilter remove(String name) { EntryImpl entry = checkOldName(name); deregister(entry); return entry.getFilter(); } public synchronized void remove(IoFilter filter) { EntryImpl e = head.nextEntry; while (e != tail) { if (e.getFilter() == filter) { deregister(e); return; } e = e.nextEntry; } throw new IllegalArgumentException("Filter not found: " + filter.getClass().getName()); } public synchronized IoFilter remove(Class filterType) { EntryImpl e = head.nextEntry; while (e != tail) { if (filterType.isAssignableFrom(e.getFilter().getClass())) { IoFilter oldFilter = e.getFilter(); deregister(e); return oldFilter; } e = e.nextEntry; } throw new IllegalArgumentException("Filter not found: " + filterType.getName()); } public synchronized IoFilter replace(String name, IoFilter newFilter) { EntryImpl entry = checkOldName(name); IoFilter oldFilter = entry.getFilter(); entry.setFilter(newFilter); return oldFilter; } public synchronized void replace(IoFilter oldFilter, IoFilter newFilter) { EntryImpl e = head.nextEntry; while (e != tail) { if (e.getFilter() == oldFilter) { e.setFilter(newFilter); return; } e = e.nextEntry; } throw new IllegalArgumentException("Filter not found: " + oldFilter.getClass().getName()); } public synchronized IoFilter replace(Class oldFilterType, IoFilter newFilter) { EntryImpl e = head.nextEntry; while (e != tail) { if (oldFilterType.isAssignableFrom(e.getFilter().getClass())) { IoFilter oldFilter = e.getFilter(); e.setFilter(newFilter); return oldFilter; } e = e.nextEntry; } throw new IllegalArgumentException("Filter not found: " + oldFilterType.getName()); } public synchronized void clear() throws Exception { List l = new ArrayList(name2entry.values()); for (IoFilterChain.Entry entry : l) { try { deregister((EntryImpl) entry); } catch (Exception e) { throw new IoFilterLifeCycleException("clear(): " + entry.getName() + " in " + getSession(), e); } } } private void register(EntryImpl prevEntry, String name, IoFilter filter) { EntryImpl newEntry = new EntryImpl(prevEntry, prevEntry.nextEntry, name, filter); try { filter.onPreAdd(this, name, newEntry.getNextFilter()); } catch (Exception e) { throw new IoFilterLifeCycleException("onPreAdd(): " + name + ':' + filter + " in " + getSession(), e); } prevEntry.nextEntry.prevEntry = newEntry; prevEntry.nextEntry = newEntry; name2entry.put(name, newEntry); try { filter.onPostAdd(this, name, newEntry.getNextFilter()); } catch (Exception e) { deregister0(newEntry); throw new IoFilterLifeCycleException("onPostAdd(): " + name + ':' + filter + " in " + getSession(), e); } } private void deregister(EntryImpl entry) { IoFilter filter = entry.getFilter(); try { filter.onPreRemove(this, entry.getName(), entry.getNextFilter()); } catch (Exception e) { throw new IoFilterLifeCycleException("onPreRemove(): " + entry.getName() + ':' + filter + " in " + getSession(), e); } deregister0(entry); try { filter.onPostRemove(this, entry.getName(), entry.getNextFilter()); } catch (Exception e) { throw new IoFilterLifeCycleException("onPostRemove(): " + entry.getName() + ':' + filter + " in " + getSession(), e); } } private void deregister0(EntryImpl entry) { EntryImpl prevEntry = entry.prevEntry; EntryImpl nextEntry = entry.nextEntry; prevEntry.nextEntry = nextEntry; nextEntry.prevEntry = prevEntry; name2entry.remove(entry.name); } /** * Throws an exception when the specified filter name is not registered in this chain. * * @return An filter entry with the specified name. */ private EntryImpl checkOldName(String baseName) { EntryImpl e = (EntryImpl) name2entry.get(baseName); if (e == null) { throw new IllegalArgumentException("Filter not found:" + baseName); } return e; } /** * Checks the specified filter name is already taken and throws an exception if already taken. */ private void checkAddable(String name) { if (name2entry.containsKey(name)) { throw new IllegalArgumentException("Other filter is using the same name '" + name + "'"); } } public void fireSessionCreated() { Entry head = this.head; callNextSessionCreated(head, session); } private void callNextSessionCreated(Entry entry, IoSession session) { try { IoFilter filter = entry.getFilter(); NextFilter nextFilter = entry.getNextFilter(); filter.sessionCreated(nextFilter, session); } catch (Throwable e) { fireExceptionCaught(e); } } public void fireSessionOpened() { Entry head = this.head; callNextSessionOpened(head, session); } private void callNextSessionOpened(Entry entry, IoSession session) { try { IoFilter filter = entry.getFilter(); NextFilter nextFilter = entry.getNextFilter(); filter.sessionOpened(nextFilter, session); } catch (Throwable e) { fireExceptionCaught(e); } } public void fireSessionClosed() { // Update future. try { session.getCloseFuture().setClosed(); } catch (Throwable t) { fireExceptionCaught(t); } // And start the chain. Entry head = this.head; callNextSessionClosed(head, session); } private void callNextSessionClosed(Entry entry, IoSession session) { try { IoFilter filter = entry.getFilter(); NextFilter nextFilter = entry.getNextFilter(); filter.sessionClosed(nextFilter, session); } catch (Throwable e) { fireExceptionCaught(e); } } public void fireSessionIdle(IdleStatus status) { session.increaseIdleCount(status, System.currentTimeMillis()); Entry head = this.head; callNextSessionIdle(head, session, status); } private void callNextSessionIdle(Entry entry, IoSession session, IdleStatus status) { try { IoFilter filter = entry.getFilter(); NextFilter nextFilter = entry.getNextFilter(); filter.sessionIdle(nextFilter, session, status); } catch (Throwable e) { fireExceptionCaught(e); } } public void fireMessageReceived(Object message) { if (message instanceof IoBuffer) { session.increaseReadBytes(((IoBuffer) message).remaining(), System.currentTimeMillis()); } Entry head = this.head; callNextMessageReceived(head, session, message); } private void callNextMessageReceived(Entry entry, IoSession session, Object message) { try { IoFilter filter = entry.getFilter(); NextFilter nextFilter = entry.getNextFilter(); filter.messageReceived(nextFilter, session, message); } catch (Throwable e) { fireExceptionCaught(e); } } public void fireMessageSent(WriteRequest request) { session.increaseWrittenMessages(request, System.currentTimeMillis()); try { request.getFuture().setWritten(); } catch (Throwable t) { fireExceptionCaught(t); } Entry head = this.head; if (!request.isEncoded()) { callNextMessageSent(head, session, request); } } private void callNextMessageSent(Entry entry, IoSession session, WriteRequest writeRequest) { try { IoFilter filter = entry.getFilter(); NextFilter nextFilter = entry.getNextFilter(); filter.messageSent(nextFilter, session, writeRequest); } catch (Throwable e) { fireExceptionCaught(e); } } public void fireExceptionCaught(Throwable cause) { Entry head = this.head; callNextExceptionCaught(head, session, cause); } private void callNextExceptionCaught(Entry entry, IoSession session, Throwable cause) { // Notify the related future. ConnectFuture future = (ConnectFuture) session.removeAttribute(SESSION_CREATED_FUTURE); if (future == null) { try { IoFilter filter = entry.getFilter(); NextFilter nextFilter = entry.getNextFilter(); filter.exceptionCaught(nextFilter, session, cause); } catch (Throwable e) { LOGGER.warn("Unexpected exception from exceptionCaught handler.", e); } } else { // Please note that this place is not the only place that // calls ConnectFuture.setException(). session.close(true); future.setException(cause); } } public void fireFilterWrite(WriteRequest writeRequest) { Entry tail = this.tail; callPreviousFilterWrite(tail, session, writeRequest); } private void callPreviousFilterWrite(Entry entry, IoSession session, WriteRequest writeRequest) { try { IoFilter filter = entry.getFilter(); NextFilter nextFilter = entry.getNextFilter(); filter.filterWrite(nextFilter, session, writeRequest); } catch (Throwable e) { writeRequest.getFuture().setException(e); fireExceptionCaught(e); } } public void fireFilterClose() { Entry tail = this.tail; callPreviousFilterClose(tail, session); } private void callPreviousFilterClose(Entry entry, IoSession session) { try { IoFilter filter = entry.getFilter(); NextFilter nextFilter = entry.getNextFilter(); filter.filterClose(nextFilter, session); } catch (Throwable e) { fireExceptionCaught(e); } } public List getAll() { List list = new ArrayList(); EntryImpl e = head.nextEntry; while (e != tail) { list.add(e); e = e.nextEntry; } return list; } public List getAllReversed() { List list = new ArrayList(); EntryImpl e = tail.prevEntry; while (e != head) { list.add(e); e = e.prevEntry; } return list; } public boolean contains(String name) { return getEntry(name) != null; } public boolean contains(IoFilter filter) { return getEntry(filter) != null; } public boolean contains(Class filterType) { return getEntry(filterType) != null; } @Override public String toString() { StringBuilder buf = new StringBuilder(); buf.append("{ "); boolean empty = true; EntryImpl e = head.nextEntry; while (e != tail) { if (!empty) { buf.append(", "); } else { empty = false; } buf.append('('); buf.append(e.getName()); buf.append(':'); buf.append(e.getFilter()); buf.append(')'); e = e.nextEntry; } if (empty) { buf.append("empty"); } buf.append(" }"); return buf.toString(); } private class HeadFilter extends IoFilterAdapter { @SuppressWarnings("unchecked") @Override public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { AbstractIoSession s = (AbstractIoSession) session; // Maintain counters. if (writeRequest.getMessage() instanceof IoBuffer) { IoBuffer buffer = (IoBuffer) writeRequest.getMessage(); // I/O processor implementation will call buffer.reset() // it after the write operation is finished, because // the buffer will be specified with messageSent event. buffer.mark(); int remaining = buffer.remaining(); if (remaining == 0) { // Zero-sized buffer means the internal message // delimiter. s.increaseScheduledWriteMessages(); } else { s.increaseScheduledWriteBytes(remaining); } } else { s.increaseScheduledWriteMessages(); } WriteRequestQueue writeRequestQueue = s.getWriteRequestQueue(); if (!s.isWriteSuspended()) { if (writeRequestQueue.size() == 0) { // We can write directly the message s.getProcessor().write(s, writeRequest); } else { s.getWriteRequestQueue().offer(s, writeRequest); s.getProcessor().flush(s); } } else { s.getWriteRequestQueue().offer(s, writeRequest); } } @SuppressWarnings("unchecked") @Override public void filterClose(NextFilter nextFilter, IoSession session) throws Exception { ((AbstractIoSession) session).getProcessor().remove(session); } } private static class TailFilter extends IoFilterAdapter { @Override public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception { try { session.getHandler().sessionCreated(session); } finally { // Notify the related future. ConnectFuture future = (ConnectFuture) session.removeAttribute(SESSION_CREATED_FUTURE); if (future != null) { future.setSession(session); } } } @Override public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception { session.getHandler().sessionOpened(session); } @Override public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception { AbstractIoSession s = (AbstractIoSession) session; try { s.getHandler().sessionClosed(session); } finally { try { s.getWriteRequestQueue().dispose(session); } finally { try { s.getAttributeMap().dispose(session); } finally { try { // Remove all filters. session.getFilterChain().clear(); } finally { if (s.getConfig().isUseReadOperation()) { s.offerClosedReadFuture(); } } } } } } @Override public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception { session.getHandler().sessionIdle(session, status); } @Override public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) throws Exception { AbstractIoSession s = (AbstractIoSession) session; try { s.getHandler().exceptionCaught(s, cause); } finally { if (s.getConfig().isUseReadOperation()) { s.offerFailedReadFuture(cause); } } } @Override public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception { AbstractIoSession s = (AbstractIoSession) session; if (!(message instanceof IoBuffer)) { s.increaseReadMessages(System.currentTimeMillis()); } else if (!((IoBuffer) message).hasRemaining()) { s.increaseReadMessages(System.currentTimeMillis()); } try { session.getHandler().messageReceived(s, message); } finally { if (s.getConfig().isUseReadOperation()) { s.offerReadFuture(message); } } } @Override public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { session.getHandler().messageSent(session, writeRequest.getMessage()); } @Override public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { nextFilter.filterWrite(session, writeRequest); } @Override public void filterClose(NextFilter nextFilter, IoSession session) throws Exception { nextFilter.filterClose(session); } } private class EntryImpl implements Entry { private EntryImpl prevEntry; private EntryImpl nextEntry; private final String name; private IoFilter filter; private final NextFilter nextFilter; private EntryImpl(EntryImpl prevEntry, EntryImpl nextEntry, String name, IoFilter filter) { if (filter == null) { throw new IllegalArgumentException("filter"); } if (name == null) { throw new IllegalArgumentException("name"); } this.prevEntry = prevEntry; this.nextEntry = nextEntry; this.name = name; this.filter = filter; this.nextFilter = new NextFilter() { public void sessionCreated(IoSession session) { Entry nextEntry = EntryImpl.this.nextEntry; callNextSessionCreated(nextEntry, session); } public void sessionOpened(IoSession session) { Entry nextEntry = EntryImpl.this.nextEntry; callNextSessionOpened(nextEntry, session); } public void sessionClosed(IoSession session) { Entry nextEntry = EntryImpl.this.nextEntry; callNextSessionClosed(nextEntry, session); } public void sessionIdle(IoSession session, IdleStatus status) { Entry nextEntry = EntryImpl.this.nextEntry; callNextSessionIdle(nextEntry, session, status); } public void exceptionCaught(IoSession session, Throwable cause) { Entry nextEntry = EntryImpl.this.nextEntry; callNextExceptionCaught(nextEntry, session, cause); } public void messageReceived(IoSession session, Object message) { Entry nextEntry = EntryImpl.this.nextEntry; callNextMessageReceived(nextEntry, session, message); } public void messageSent(IoSession session, WriteRequest writeRequest) { Entry nextEntry = EntryImpl.this.nextEntry; callNextMessageSent(nextEntry, session, writeRequest); } public void filterWrite(IoSession session, WriteRequest writeRequest) { Entry nextEntry = EntryImpl.this.prevEntry; callPreviousFilterWrite(nextEntry, session, writeRequest); } public void filterClose(IoSession session) { Entry nextEntry = EntryImpl.this.prevEntry; callPreviousFilterClose(nextEntry, session); } public String toString() { return EntryImpl.this.nextEntry.name; } }; } public String getName() { return name; } public IoFilter getFilter() { return filter; } private void setFilter(IoFilter filter) { if (filter == null) { throw new IllegalArgumentException("filter"); } this.filter = filter; } public NextFilter getNextFilter() { return nextFilter; } @Override public String toString() { StringBuilder sb = new StringBuilder(); // Add the current filter sb.append("('").append(getName()).append('\''); // Add the previous filter sb.append(", prev: '"); if (prevEntry != null) { sb.append(prevEntry.name); sb.append(':'); sb.append(prevEntry.getFilter().getClass().getSimpleName()); } else { sb.append("null"); } // Add the next filter sb.append("', next: '"); if (nextEntry != null) { sb.append(nextEntry.name); sb.append(':'); sb.append(nextEntry.getFilter().getClass().getSimpleName()); } else { sb.append("null"); } sb.append("')"); return sb.toString(); } public void addAfter(String name, IoFilter filter) { DefaultIoFilterChain.this.addAfter(getName(), name, filter); } public void addBefore(String name, IoFilter filter) { DefaultIoFilterChain.this.addBefore(getName(), name, filter); } public void remove() { DefaultIoFilterChain.this.remove(getName()); } public void replace(IoFilter newFilter) { DefaultIoFilterChain.this.replace(getName(), newFilter); } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/filterchain/IoFilter.java0000644000175000017500000002343212032276031030646 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.filterchain; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.filter.util.ReferenceCountingFilter; /** * A filter which intercepts {@link IoHandler} events like Servlet * filters. Filters can be used for these purposes: *
    *
  • Event logging,
  • *
  • Performance measurement,
  • *
  • Authorization,
  • *
  • Overload control,
  • *
  • Message transformation (e.g. encryption and decryption, ...),
  • *
  • and many more.
  • *
*

* Please NEVER implement your filters to wrap * {@link IoSession}s. Users can cache the reference to the * session, which might malfunction if any filters are added or removed later. * *

The Life Cycle

* {@link IoFilter}s are activated only when they are inside {@link IoFilterChain}. *

* When you add an {@link IoFilter} to an {@link IoFilterChain}: *

    *
  1. {@link #init()} is invoked by {@link ReferenceCountingFilter} if * the filter is added at the first time.
  2. *
  3. {@link #onPreAdd(IoFilterChain, String, NextFilter)} is invoked to notify * that the filter will be added to the chain.
  4. *
  5. The filter is added to the chain, and all events and I/O requests * pass through the filter from now.
  6. *
  7. {@link #onPostAdd(IoFilterChain, String, NextFilter)} is invoked to notify * that the filter is added to the chain.
  8. *
  9. The filter is removed from the chain if {@link #onPostAdd(IoFilterChain, String, org.apache.mina.core.filterchain.IoFilter.NextFilter)} * threw an exception. {@link #destroy()} is also invoked by * {@link ReferenceCountingFilter} if the filter is the last filter which * was added to {@link IoFilterChain}s.
  10. *
*

* When you remove an {@link IoFilter} from an {@link IoFilterChain}: *

    *
  1. {@link #onPreRemove(IoFilterChain, String, NextFilter)} is invoked to * notify that the filter will be removed from the chain.
  2. *
  3. The filter is removed from the chain, and any events and I/O requests * don't pass through the filter from now.
  4. *
  5. {@link #onPostRemove(IoFilterChain, String, NextFilter)} is invoked to * notify that the filter is removed from the chain.
  6. *
  7. {@link #destroy()} is invoked by {@link ReferenceCountingFilter} if * the removed filter was the last one.
  8. *
* * @author Apache MINA Project * * @see IoFilterAdapter */ public interface IoFilter { /** * Invoked by {@link ReferenceCountingFilter} when this filter * is added to a {@link IoFilterChain} at the first time, so you can * initialize shared resources. Please note that this method is never * called if you don't wrap a filter with {@link ReferenceCountingFilter}. */ void init() throws Exception; /** * Invoked by {@link ReferenceCountingFilter} when this filter * is not used by any {@link IoFilterChain} anymore, so you can destroy * shared resources. Please note that this method is never called if * you don't wrap a filter with {@link ReferenceCountingFilter}. */ void destroy() throws Exception; /** * Invoked before this filter is added to the specified parent. * Please note that this method can be invoked more than once if * this filter is added to more than one parents. This method is not * invoked before {@link #init()} is invoked. * * @param parent the parent who called this method * @param name the name assigned to this filter * @param nextFilter the {@link NextFilter} for this filter. You can reuse * this object until this filter is removed from the chain. */ void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception; /** * Invoked after this filter is added to the specified parent. * Please note that this method can be invoked more than once if * this filter is added to more than one parents. This method is not * invoked before {@link #init()} is invoked. * * @param parent the parent who called this method * @param name the name assigned to this filter * @param nextFilter the {@link NextFilter} for this filter. You can reuse * this object until this filter is removed from the chain. */ void onPostAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception; /** * Invoked before this filter is removed from the specified parent. * Please note that this method can be invoked more than once if * this filter is removed from more than one parents. * This method is always invoked before {@link #destroy()} is invoked. * * @param parent the parent who called this method * @param name the name assigned to this filter * @param nextFilter the {@link NextFilter} for this filter. You can reuse * this object until this filter is removed from the chain. */ void onPreRemove(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception; /** * Invoked after this filter is removed from the specified parent. * Please note that this method can be invoked more than once if * this filter is removed from more than one parents. * This method is always invoked before {@link #destroy()} is invoked. * * @param parent the parent who called this method * @param name the name assigned to this filter * @param nextFilter the {@link NextFilter} for this filter. You can reuse * this object until this filter is removed from the chain. */ void onPostRemove(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception; /** * Filters {@link IoHandler#sessionCreated(IoSession)} event. */ void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception; /** * Filters {@link IoHandler#sessionOpened(IoSession)} event. */ void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception; /** * Filters {@link IoHandler#sessionClosed(IoSession)} event. */ void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception; /** * Filters {@link IoHandler#sessionIdle(IoSession,IdleStatus)} * event. */ void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception; /** * Filters {@link IoHandler#exceptionCaught(IoSession,Throwable)} * event. */ void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) throws Exception; /** * Filters {@link IoHandler#messageReceived(IoSession,Object)} * event. */ void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception; /** * Filters {@link IoHandler#messageSent(IoSession,Object)} * event. */ void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception; /** * Filters {@link IoSession#close()} method invocation. */ void filterClose(NextFilter nextFilter, IoSession session) throws Exception; /** * Filters {@link IoSession#write(Object)} method invocation. */ void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception; /** * Represents the next {@link IoFilter} in {@link IoFilterChain}. */ public interface NextFilter { /** * Forwards sessionCreated event to next filter. */ void sessionCreated(IoSession session); /** * Forwards sessionOpened event to next filter. */ void sessionOpened(IoSession session); /** * Forwards sessionClosed event to next filter. */ void sessionClosed(IoSession session); /** * Forwards sessionIdle event to next filter. */ void sessionIdle(IoSession session, IdleStatus status); /** * Forwards exceptionCaught event to next filter. */ void exceptionCaught(IoSession session, Throwable cause); /** * Forwards messageReceived event to next filter. */ void messageReceived(IoSession session, Object message); /** * Forwards messageSent event to next filter. */ void messageSent(IoSession session, WriteRequest writeRequest); /** * Forwards filterWrite event to next filter. */ void filterWrite(IoSession session, WriteRequest writeRequest); /** * Forwards filterClose event to next filter. */ void filterClose(IoSession session); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/filterchain/IoFilterEvent.java0000644000175000017500000000743312032276031031653 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.filterchain; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoEvent; import org.apache.mina.core.session.IoEventType; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An I/O event or an I/O request that MINA provides for {@link IoFilter}s. * Most users won't need to use this class. It is usually used by internal * components to store I/O events. * * @author Apache MINA Project */ public class IoFilterEvent extends IoEvent { /** A logger for this class */ static Logger LOGGER = LoggerFactory.getLogger(IoFilterEvent.class); /** A speedup for logs */ static boolean DEBUG = LOGGER.isDebugEnabled(); private final NextFilter nextFilter; public IoFilterEvent(NextFilter nextFilter, IoEventType type, IoSession session, Object parameter) { super(type, session, parameter); if (nextFilter == null) { throw new IllegalArgumentException("nextFilter must not be null"); } this.nextFilter = nextFilter; } public NextFilter getNextFilter() { return nextFilter; } @Override public void fire() { IoSession session = getSession(); NextFilter nextFilter = getNextFilter(); IoEventType type = getType(); if (DEBUG) { LOGGER.debug("Firing a {} event for session {}", type, session.getId()); } switch (type) { case MESSAGE_RECEIVED: Object parameter = getParameter(); nextFilter.messageReceived(session, parameter); break; case MESSAGE_SENT: WriteRequest writeRequest = (WriteRequest) getParameter(); nextFilter.messageSent(session, writeRequest); break; case WRITE: writeRequest = (WriteRequest) getParameter(); nextFilter.filterWrite(session, writeRequest); break; case CLOSE: nextFilter.filterClose(session); break; case EXCEPTION_CAUGHT: Throwable throwable = (Throwable) getParameter(); nextFilter.exceptionCaught(session, throwable); break; case SESSION_IDLE: nextFilter.sessionIdle(session, (IdleStatus) getParameter()); break; case SESSION_OPENED: nextFilter.sessionOpened(session); break; case SESSION_CREATED: nextFilter.sessionCreated(session); break; case SESSION_CLOSED: nextFilter.sessionClosed(session); break; default: throw new IllegalArgumentException("Unknown event type: " + type); } if (DEBUG) { LOGGER.debug("Event {} has been fired for session {}", type, session.getId()); } } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/filterchain/IoFilterChainBuilder.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/filterchain/IoFilterChainBuilder.j0000644000175000017500000000362512032276031032432 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.filterchain; import org.apache.mina.core.session.IoSession; /** * An interface that builds {@link IoFilterChain} in predefined way * when {@link IoSession} is created. You can extract common filter chain * modification logic to this interface. For example, to add a filter * to the chain, *
 * public class MyFilterChainBuilder implements IoFilterChainBuilder {
 *     public void buildFilterChain( IoFilterChain chain ) throws Exception {
 *         chain.addLast( "myFilter", new MyFilter() );
 *     }
 * }
 * 
* * @author Apache MINA Project */ public interface IoFilterChainBuilder { /** * An implementation which does nothing. */ IoFilterChainBuilder NOOP = new IoFilterChainBuilder() { public void buildFilterChain(IoFilterChain chain) throws Exception { } @Override public String toString() { return "NOOP"; } }; /** * Modifies the specified chain. */ void buildFilterChain(IoFilterChain chain) throws Exception; } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/filterchain/IoFilterChain.java0000644000175000017500000002735112032276031031615 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.core.filterchain; import java.util.List; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; /** * A container of {@link IoFilter}s that forwards {@link IoHandler} events * to the consisting filters and terminal {@link IoHandler} sequentially. * Every {@link IoSession} has its own {@link IoFilterChain} (1-to-1 relationship). * * @author Apache MINA Project */ public interface IoFilterChain { /** * Returns the parent {@link IoSession} of this chain. * * @return {@link IoSession} */ IoSession getSession(); /** * Returns the {@link Entry} with the specified name in this chain. * * @param name The filter's name we are looking for * @return null if there's no such name in this chain */ Entry getEntry(String name); /** * Returns the {@link Entry} with the specified filter in this chain. * * @param filter The Filter we are looking for * @return null if there's no such filter in this chain */ Entry getEntry(IoFilter filter); /** * Returns the {@link Entry} with the specified filterType * in this chain. If there's more than one filter with the specified * type, the first match will be chosen. * * @param filterType The filter class we are looking for * @return null if there's no such name in this chain */ Entry getEntry(Class filterType); /** * Returns the {@link IoFilter} with the specified name in this chain. * * @param name the filter's name * @return null if there's no such name in this chain */ IoFilter get(String name); /** * Returns the {@link IoFilter} with the specified filterType * in this chain. If there's more than one filter with the specified * type, the first match will be chosen. * * @param filterType The filter class * @return null if there's no such name in this chain */ IoFilter get(Class filterType); /** * Returns the {@link NextFilter} of the {@link IoFilter} with the * specified name in this chain. * * @param name The filter's name we want the next filter * @return null if there's no such name in this chain */ NextFilter getNextFilter(String name); /** * Returns the {@link NextFilter} of the specified {@link IoFilter} * in this chain. * * @param filter The filter for which we want the next filter * @return null if there's no such name in this chain */ NextFilter getNextFilter(IoFilter filter); /** * Returns the {@link NextFilter} of the specified filterType * in this chain. If there's more than one filter with the specified * type, the first match will be chosen. * * @param filterType The Filter class for which we want the next filter * @return null if there's no such name in this chain */ NextFilter getNextFilter(Class filterType); /** * @return The list of all {@link Entry}s this chain contains. */ List getAll(); /** * @return The reversed list of all {@link Entry}s this chain contains. */ List getAllReversed(); /** * @param name The filter's name we are looking for * * @return true if this chain contains an {@link IoFilter} with the * specified name. */ boolean contains(String name); /** * @param filter The filter we are looking for * * @return true if this chain contains the specified filter. */ boolean contains(IoFilter filter); /** * @param filterType The filter's class we are looking for * * @return true if this chain contains an {@link IoFilter} of the * specified filterType. */ boolean contains(Class filterType); /** * Adds the specified filter with the specified name at the beginning of this chain. * * @param name The filter's name * @param filter The filter to add */ void addFirst(String name, IoFilter filter); /** * Adds the specified filter with the specified name at the end of this chain. * * @param name The filter's name * @param filter The filter to add */ void addLast(String name, IoFilter filter); /** * Adds the specified filter with the specified name just before the filter whose name is * baseName in this chain. * * @param baseName The targeted Filter's name * @param name The filter's name * @param filter The filter to add */ void addBefore(String baseName, String name, IoFilter filter); /** * Adds the specified filter with the specified name just after the filter whose name is * baseName in this chain. * * @param baseName The targeted Filter's name * @param name The filter's name * @param filter The filter to add */ void addAfter(String baseName, String name, IoFilter filter); /** * Replace the filter with the specified name with the specified new * filter. * * @param name The name of the filter we want to replace * @param newFilter The new filter * @return the old filter */ IoFilter replace(String name, IoFilter newFilter); /** * Replace the filter with the specified name with the specified new * filter. * * @param oldFilter The filter we want to replace * @param newFilter The new filter */ void replace(IoFilter oldFilter, IoFilter newFilter); /** * Replace the filter of the specified type with the specified new * filter. If there's more than one filter with the specified type, * the first match will be replaced. * * @param oldFilterType The filter class we want to replace * @param newFilter The new filter */ IoFilter replace(Class oldFilterType, IoFilter newFilter); /** * Removes the filter with the specified name from this chain. * * @param name The name of the filter to remove * @return The removed filter */ IoFilter remove(String name); /** * Replace the filter with the specified name with the specified new * filter. * * @param name The filter to remove */ void remove(IoFilter filter); /** * Replace the filter of the specified type with the specified new * filter. If there's more than one filter with the specified type, * the first match will be replaced. * * @param name The filter class to remove * @return The removed filter */ IoFilter remove(Class filterType); /** * Removes all filters added to this chain. */ void clear() throws Exception; /** * Fires a {@link IoHandler#sessionCreated(IoSession)} event. Most users don't need to * call this method at all. Please use this method only when you implement a new transport * or fire a virtual event. */ public void fireSessionCreated(); /** * Fires a {@link IoHandler#sessionOpened(IoSession)} event. Most users don't need to call * this method at all. Please use this method only when you implement a new transport or * fire a virtual event. */ public void fireSessionOpened(); /** * Fires a {@link IoHandler#sessionClosed(IoSession)} event. Most users don't need to call * this method at all. Please use this method only when you implement a new transport or * fire a virtual event. */ public void fireSessionClosed(); /** * Fires a {@link IoHandler#sessionIdle(IoSession, IdleStatus)} event. Most users don't * need to call this method at all. Please use this method only when you implement a new * transport or fire a virtual event. * * @param status The current status to propagate */ public void fireSessionIdle(IdleStatus status); /** * Fires a {@link IoHandler#messageReceived(Object)} event. Most users don't need to * call this method at all. Please use this method only when you implement a new transport * or fire a virtual event. * * @param message The received message */ public void fireMessageReceived(Object message); /** * Fires a {@link IoHandler#messageSent(IoSession)} event. Most users don't need to call * this method at all. Please use this method only when you implement a new transport or * fire a virtual event. * * @param request The sent request */ public void fireMessageSent(WriteRequest request); /** * Fires a {@link IoHandler#exceptionCaught(IoSession, Throwable)} event. Most users don't * need to call this method at all. Please use this method only when you implement a new * transport or fire a virtual event. * * @param cause The exception cause */ public void fireExceptionCaught(Throwable cause); /** * Fires a {@link IoSession#write(Object)} event. Most users don't need to call this * method at all. Please use this method only when you implement a new transport or fire a * virtual event. * * @param writeRequest The message to write */ public void fireFilterWrite(WriteRequest writeRequest); /** * Fires a {@link IoSession#close()} event. Most users don't need to call this method at * all. Please use this method only when you implement a new transport or fire a virtual * event. */ public void fireFilterClose(); /** * Represents a name-filter pair that an {@link IoFilterChain} contains. * * @author Apache MINA Project */ public interface Entry { /** * Returns the name of the filter. */ String getName(); /** * Returns the filter. */ IoFilter getFilter(); /** * @return The {@link NextFilter} of the filter. */ NextFilter getNextFilter(); /** * Adds the specified filter with the specified name just before this entry. */ void addBefore(String name, IoFilter filter); /** * Adds the specified filter with the specified name just after this entry. */ void addAfter(String name, IoFilter filter); /** * Replace the filter of this entry with the specified new filter. */ void replace(IoFilter newFilter); /** * Removes this entry from the chain it belongs to. */ void remove(); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/core/package.html0000644000175000017500000000163312032276032026257 0ustar ebourgebourg Common types required for users to use MINA. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/0000755000175000017500000000000012162575507024035 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/Transform.java0000644000175000017500000001202012032276034026633 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import java.io.IOException; import java.io.LineNumberReader; import java.io.PrintWriter; import java.io.StringReader; import java.io.StringWriter; import java.util.ArrayList; /** * Utility class for working with xml data * * Implementation is heavily based on org.apache.log4j.helpers.Transform * * @author Apache MINA Project */ public class Transform { private static final String CDATA_START = ""; private static final String CDATA_PSEUDO_END = "]]>"; private static final String CDATA_EMBEDED_END = CDATA_END + CDATA_PSEUDO_END + CDATA_START; private static final int CDATA_END_LEN = CDATA_END.length(); /** * This method takes a string which may contain HTML tags (ie, * <b>, <table>, etc) and replaces any * '<', '>' , '&' or '"' * characters with respective predefined entity references. * * @param input The text to be converted. * @return The input string with the special characters replaced. * */ static public String escapeTags(final String input) { // Check if the string is null, zero length or devoid of special characters // if so, return what was sent in. if (input == null || input.length() == 0 || (input.indexOf('"') == -1 && input.indexOf('&') == -1 && input.indexOf('<') == -1 && input .indexOf('>') == -1)) { return input; } StringBuilder buf = new StringBuilder(input.length() + 6); char ch; int len = input.length(); for (int i = 0; i < len; i++) { ch = input.charAt(i); if (ch > '>') { buf.append(ch); } else if (ch == '<') { buf.append("<"); } else if (ch == '>') { buf.append(">"); } else if (ch == '&') { buf.append("&"); } else if (ch == '"') { buf.append("""); } else { buf.append(ch); } } return buf.toString(); } /** * Ensures that embeded CDEnd strings (]]>) are handled properly * within message, NDC and throwable tag text. * * @param buf StringBuffer holding the XML data to this point. The * initial CDStart () of the CDATA * section are the responsibility of the calling method. * @param str The String that is inserted into an existing CDATA Section within buf. * */ static public void appendEscapingCDATA(final StringBuffer buf, final String str) { if (str != null) { int end = str.indexOf(CDATA_END); if (end < 0) { buf.append(str); } else { int start = 0; while (end > -1) { buf.append(str.substring(start, end)); buf.append(CDATA_EMBEDED_END); start = end + CDATA_END_LEN; if (start < str.length()) { end = str.indexOf(CDATA_END, start); } else { return; } } buf.append(str.substring(start)); } } } /** * convert a Throwable into an array of Strings * @param throwable * @return string representation of the throwable */ public static String[] getThrowableStrRep(Throwable throwable) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); throwable.printStackTrace(pw); pw.flush(); LineNumberReader reader = new LineNumberReader(new StringReader(sw.toString())); ArrayList lines = new ArrayList(); try { String line = reader.readLine(); while (line != null) { lines.add(line); line = reader.readLine(); } } catch (IOException ex) { lines.add(ex.toString()); } String[] rep = new String[lines.size()]; lines.toArray(rep); return rep; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/CircularQueue.java0000644000175000017500000002176512032276034027451 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import java.io.Serializable; import java.util.AbstractList; import java.util.Arrays; import java.util.NoSuchElementException; import java.util.Queue; /** * A unbounded circular queue based on array. * * @author Apache MINA Project */ public class CircularQueue extends AbstractList implements Queue, Serializable { /** The serialVersionUID : mandatory for serializable classes */ private static final long serialVersionUID = 3993421269224511264L; /** Minimal size of the underlying array */ private static final int DEFAULT_CAPACITY = 4; /** The initial capacity of the list */ private final int initialCapacity; // XXX: This volatile keyword here is a workaround for SUN Java Compiler bug, // which produces buggy byte code. I don't event know why adding a volatile // fixes the problem. Eclipse Java Compiler seems to produce correct byte code. private volatile Object[] items; private int mask; private int first = 0; private int last = 0; private boolean full; private int shrinkThreshold; /** * Construct a new, empty queue. */ public CircularQueue() { this(DEFAULT_CAPACITY); } public CircularQueue(int initialCapacity) { int actualCapacity = normalizeCapacity(initialCapacity); items = new Object[actualCapacity]; mask = actualCapacity - 1; this.initialCapacity = actualCapacity; this.shrinkThreshold = 0; } /** * The capacity must be a power of 2. */ private static int normalizeCapacity(int initialCapacity) { int actualCapacity = 1; while (actualCapacity < initialCapacity) { actualCapacity <<= 1; if (actualCapacity < 0) { actualCapacity = 1 << 30; break; } } return actualCapacity; } /** * Returns the capacity of this queue. */ public int capacity() { return items.length; } @Override public void clear() { if (!isEmpty()) { Arrays.fill(items, null); first = 0; last = 0; full = false; shrinkIfNeeded(); } } @SuppressWarnings("unchecked") public E poll() { if (isEmpty()) { return null; } Object ret = items[first]; items[first] = null; decreaseSize(); if (first == last) { first = last = 0; } shrinkIfNeeded(); return (E) ret; } public boolean offer(E item) { if (item == null) { throw new IllegalArgumentException("item"); } expandIfNeeded(); items[last] = item; increaseSize(); return true; } @SuppressWarnings("unchecked") public E peek() { if (isEmpty()) { return null; } return (E) items[first]; } @SuppressWarnings("unchecked") @Override public E get(int idx) { checkIndex(idx); return (E) items[getRealIndex(idx)]; } @Override public boolean isEmpty() { return (first == last) && !full; } @Override public int size() { if (full) { return capacity(); } if (last >= first) { return last - first; } return last - first + capacity(); } @Override public String toString() { return "first=" + first + ", last=" + last + ", size=" + size() + ", mask = " + mask; } private void checkIndex(int idx) { if (idx < 0 || idx >= size()) { throw new IndexOutOfBoundsException(String.valueOf(idx)); } } private int getRealIndex(int idx) { return (first + idx) & mask; } private void increaseSize() { last = (last + 1) & mask; full = first == last; } private void decreaseSize() { first = (first + 1) & mask; full = false; } private void expandIfNeeded() { if (full) { // expand queue final int oldLen = items.length; final int newLen = oldLen << 1; Object[] tmp = new Object[newLen]; if (first < last) { System.arraycopy(items, first, tmp, 0, last - first); } else { System.arraycopy(items, first, tmp, 0, oldLen - first); System.arraycopy(items, 0, tmp, oldLen - first, last); } first = 0; last = oldLen; items = tmp; mask = tmp.length - 1; if (newLen >>> 3 > initialCapacity) { shrinkThreshold = newLen >>> 3; } } } private void shrinkIfNeeded() { int size = size(); if (size <= shrinkThreshold) { // shrink queue final int oldLen = items.length; int newLen = normalizeCapacity(size); if (size == newLen) { newLen <<= 1; } if (newLen >= oldLen) { return; } if (newLen < initialCapacity) { if (oldLen == initialCapacity) { return; } newLen = initialCapacity; } Object[] tmp = new Object[newLen]; // Copy only when there's something to copy. if (size > 0) { if (first < last) { System.arraycopy(items, first, tmp, 0, last - first); } else { System.arraycopy(items, first, tmp, 0, oldLen - first); System.arraycopy(items, 0, tmp, oldLen - first, last); } } first = 0; last = size; items = tmp; mask = tmp.length - 1; shrinkThreshold = 0; } } @Override public boolean add(E o) { return offer(o); } @SuppressWarnings("unchecked") @Override public E set(int idx, E o) { checkIndex(idx); int realIdx = getRealIndex(idx); Object old = items[realIdx]; items[realIdx] = o; return (E) old; } @Override public void add(int idx, E o) { if (idx == size()) { offer(o); return; } checkIndex(idx); expandIfNeeded(); int realIdx = getRealIndex(idx); // Make a room for a new element. if (first < last) { System.arraycopy(items, realIdx, items, realIdx + 1, last - realIdx); } else { if (realIdx >= first) { System.arraycopy(items, 0, items, 1, last); items[0] = items[items.length - 1]; System.arraycopy(items, realIdx, items, realIdx + 1, items.length - realIdx - 1); } else { System.arraycopy(items, realIdx, items, realIdx + 1, last - realIdx); } } items[realIdx] = o; increaseSize(); } @SuppressWarnings("unchecked") @Override public E remove(int idx) { if (idx == 0) { return poll(); } checkIndex(idx); int realIdx = getRealIndex(idx); Object removed = items[realIdx]; // Remove a room for the removed element. if (first < last) { System.arraycopy(items, first, items, first + 1, realIdx - first); } else { if (realIdx >= first) { System.arraycopy(items, first, items, first + 1, realIdx - first); } else { System.arraycopy(items, 0, items, 1, realIdx); items[0] = items[items.length - 1]; System.arraycopy(items, first, items, first + 1, items.length - first - 1); } } items[first] = null; decreaseSize(); shrinkIfNeeded(); return (E) removed; } public E remove() { if (isEmpty()) { throw new NoSuchElementException(); } return poll(); } public E element() { if (isEmpty()) { throw new NoSuchElementException(); } return peek(); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/AvailablePortFinder.java0000644000175000017500000001272412032533114030543 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import java.io.IOException; import java.net.DatagramSocket; import java.net.ServerSocket; import java.util.NoSuchElementException; import java.util.Set; import java.util.TreeSet; /** * Finds currently available server ports. * * @author Apache MINA Project * @see IANA.org */ public class AvailablePortFinder { /** * The minimum number of server port number. */ public static final int MIN_PORT_NUMBER = 1; /** * The maximum number of server port number. */ public static final int MAX_PORT_NUMBER = 49151; /** * Creates a new instance. */ private AvailablePortFinder() { // Do nothing } /** * Returns the {@link Set} of currently available port numbers * ({@link Integer}). This method is identical to * getAvailablePorts(MIN_PORT_NUMBER, MAX_PORT_NUMBER). * * WARNING: this can take a very long time. */ public static Set getAvailablePorts() { return getAvailablePorts(MIN_PORT_NUMBER, MAX_PORT_NUMBER); } /** * Gets an available port, selected by the system. * * @throws NoSuchElementException if there are no ports available */ public static int getNextAvailable() { ServerSocket serverSocket = null; try { // Here, we simply return an available port found by the system serverSocket = new ServerSocket(0); int port = serverSocket.getLocalPort(); // Don't forget to close the socket... serverSocket.close(); return port; } catch (IOException ioe) { throw new NoSuchElementException(ioe.getMessage()); } } /** * Gets the next available port starting at a port. * * @param fromPort the port to scan for availability * @throws NoSuchElementException if there are no ports available */ public static int getNextAvailable(int fromPort) { if (fromPort < MIN_PORT_NUMBER || fromPort > MAX_PORT_NUMBER) { throw new IllegalArgumentException("Invalid start port: " + fromPort); } for (int i = fromPort; i <= MAX_PORT_NUMBER; i++) { if (available(i)) { return i; } } throw new NoSuchElementException("Could not find an available port " + "above " + fromPort); } /** * Checks to see if a specific port is available. * * @param port the port to check for availability */ public static boolean available(int port) { if (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER) { throw new IllegalArgumentException("Invalid start port: " + port); } ServerSocket ss = null; DatagramSocket ds = null; try { ss = new ServerSocket(port); ss.setReuseAddress(true); ds = new DatagramSocket(port); ds.setReuseAddress(true); return true; } catch (IOException e) { // Do nothing } finally { if (ds != null) { ds.close(); } if (ss != null) { try { ss.close(); } catch (IOException e) { /* should not be thrown */ } } } return false; } /** * Returns the {@link Set} of currently avaliable port numbers ({@link Integer}) * between the specified port range. * * @throws IllegalArgumentException if port range is not between * {@link #MIN_PORT_NUMBER} and {@link #MAX_PORT_NUMBER} or * fromPort if greater than toPort. */ public static Set getAvailablePorts(int fromPort, int toPort) { if (fromPort < MIN_PORT_NUMBER || toPort > MAX_PORT_NUMBER || fromPort > toPort) { throw new IllegalArgumentException("Invalid port range: " + fromPort + " ~ " + toPort); } Set result = new TreeSet(); for (int i = fromPort; i <= toPort; i++) { ServerSocket s = null; try { s = new ServerSocket(i); result.add(new Integer(i)); } catch (IOException e) { // Do nothing } finally { if (s != null) { try { s.close(); } catch (IOException e) { /* should not be thrown */ } } } } return result; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/ExpirationListener.java0000644000175000017500000000212112032276034030511 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; /** * A listener for expired object events. * * @author Apache MINA Project * TODO Make this a inner interface of ExpiringMap */ public interface ExpirationListener { void expired(E expiredObject); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/ConcurrentHashSet.java0000644000175000017500000000314312032276034030270 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import java.util.Collection; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * A {@link ConcurrentHashMap}-backed {@link Set}. * * @author Apache MINA Project */ public class ConcurrentHashSet extends MapBackedSet { private static final long serialVersionUID = 8518578988740277828L; public ConcurrentHashSet() { super(new ConcurrentHashMap()); } public ConcurrentHashSet(Collection c) { super(new ConcurrentHashMap(), c); } @Override public boolean add(E o) { Boolean answer = ((ConcurrentMap) map).putIfAbsent(o, Boolean.TRUE); return answer == null; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/ExpiringMap.java0000644000175000017500000003062112032276034027112 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * A map with expiration. This class contains a worker thread that will * periodically check this class in order to determine if any objects * should be removed based on the provided time-to-live value. * * @author Apache MINA Project */ public class ExpiringMap implements Map { /** * The default value, 60 */ public static final int DEFAULT_TIME_TO_LIVE = 60; /** * The default value, 1 */ public static final int DEFAULT_EXPIRATION_INTERVAL = 1; private static volatile int expirerCount = 1; private final ConcurrentHashMap delegate; private final CopyOnWriteArrayList> expirationListeners; private final Expirer expirer; /** * Creates a new instance of ExpiringMap using the default values * DEFAULT_TIME_TO_LIVE and DEFAULT_EXPIRATION_INTERVAL * */ public ExpiringMap() { this(DEFAULT_TIME_TO_LIVE, DEFAULT_EXPIRATION_INTERVAL); } /** * Creates a new instance of ExpiringMap using the supplied * time-to-live value and the default value for DEFAULT_EXPIRATION_INTERVAL * * @param timeToLive * The time-to-live value (seconds) */ public ExpiringMap(int timeToLive) { this(timeToLive, DEFAULT_EXPIRATION_INTERVAL); } /** * Creates a new instance of ExpiringMap using the supplied values and * a {@link ConcurrentHashMap} for the internal data structure. * * @param timeToLive * The time-to-live value (seconds) * @param expirationInterval * The time between checks to see if a value should be removed (seconds) */ public ExpiringMap(int timeToLive, int expirationInterval) { this(new ConcurrentHashMap(), new CopyOnWriteArrayList>(), timeToLive, expirationInterval); } private ExpiringMap(ConcurrentHashMap delegate, CopyOnWriteArrayList> expirationListeners, int timeToLive, int expirationInterval) { this.delegate = delegate; this.expirationListeners = expirationListeners; this.expirer = new Expirer(); expirer.setTimeToLive(timeToLive); expirer.setExpirationInterval(expirationInterval); } public V put(K key, V value) { ExpiringObject answer = delegate.put(key, new ExpiringObject(key, value, System.currentTimeMillis())); if (answer == null) { return null; } return answer.getValue(); } public V get(Object key) { ExpiringObject object = delegate.get(key); if (object != null) { object.setLastAccessTime(System.currentTimeMillis()); return object.getValue(); } return null; } public V remove(Object key) { ExpiringObject answer = delegate.remove(key); if (answer == null) { return null; } return answer.getValue(); } public boolean containsKey(Object key) { return delegate.containsKey(key); } public boolean containsValue(Object value) { return delegate.containsValue(value); } public int size() { return delegate.size(); } public boolean isEmpty() { return delegate.isEmpty(); } public void clear() { delegate.clear(); } @Override public int hashCode() { return delegate.hashCode(); } public Set keySet() { return delegate.keySet(); } @Override public boolean equals(Object obj) { return delegate.equals(obj); } public void putAll(Map inMap) { for (Entry e : inMap.entrySet()) { this.put(e.getKey(), e.getValue()); } } public Collection values() { throw new UnsupportedOperationException(); } public Set> entrySet() { throw new UnsupportedOperationException(); } public void addExpirationListener(ExpirationListener listener) { expirationListeners.add(listener); } public void removeExpirationListener(ExpirationListener listener) { expirationListeners.remove(listener); } public Expirer getExpirer() { return expirer; } public int getExpirationInterval() { return expirer.getExpirationInterval(); } public int getTimeToLive() { return expirer.getTimeToLive(); } public void setExpirationInterval(int expirationInterval) { expirer.setExpirationInterval(expirationInterval); } public void setTimeToLive(int timeToLive) { expirer.setTimeToLive(timeToLive); } private class ExpiringObject { private K key; private V value; private long lastAccessTime; private final ReadWriteLock lastAccessTimeLock = new ReentrantReadWriteLock(); ExpiringObject(K key, V value, long lastAccessTime) { if (value == null) { throw new IllegalArgumentException("An expiring object cannot be null."); } this.key = key; this.value = value; this.lastAccessTime = lastAccessTime; } public long getLastAccessTime() { lastAccessTimeLock.readLock().lock(); try { return lastAccessTime; } finally { lastAccessTimeLock.readLock().unlock(); } } public void setLastAccessTime(long lastAccessTime) { lastAccessTimeLock.writeLock().lock(); try { this.lastAccessTime = lastAccessTime; } finally { lastAccessTimeLock.writeLock().unlock(); } } public K getKey() { return key; } public V getValue() { return value; } @Override public boolean equals(Object obj) { return value.equals(obj); } @Override public int hashCode() { return value.hashCode(); } } /** * A Thread that monitors an {@link ExpiringMap} and will remove * elements that have passed the threshold. * */ public class Expirer implements Runnable { private final ReadWriteLock stateLock = new ReentrantReadWriteLock(); private long timeToLiveMillis; private long expirationIntervalMillis; private boolean running = false; private final Thread expirerThread; /** * Creates a new instance of Expirer. * */ public Expirer() { expirerThread = new Thread(this, "ExpiringMapExpirer-" + expirerCount++); expirerThread.setDaemon(true); } public void run() { while (running) { processExpires(); try { Thread.sleep(expirationIntervalMillis); } catch (InterruptedException e) { // Do nothing } } } private void processExpires() { long timeNow = System.currentTimeMillis(); for (ExpiringObject o : delegate.values()) { if (timeToLiveMillis <= 0) { continue; } long timeIdle = timeNow - o.getLastAccessTime(); if (timeIdle >= timeToLiveMillis) { delegate.remove(o.getKey()); for (ExpirationListener listener : expirationListeners) { listener.expired(o.getValue()); } } } } /** * Kick off this thread which will look for old objects and remove them. * */ public void startExpiring() { stateLock.writeLock().lock(); try { if (!running) { running = true; expirerThread.start(); } } finally { stateLock.writeLock().unlock(); } } /** * If this thread has not started, then start it. * Otherwise just return; */ public void startExpiringIfNotStarted() { stateLock.readLock().lock(); try { if (running) { return; } } finally { stateLock.readLock().unlock(); } stateLock.writeLock().lock(); try { if (!running) { running = true; expirerThread.start(); } } finally { stateLock.writeLock().unlock(); } } /** * Stop the thread from monitoring the map. */ public void stopExpiring() { stateLock.writeLock().lock(); try { if (running) { running = false; expirerThread.interrupt(); } } finally { stateLock.writeLock().unlock(); } } /** * Checks to see if the thread is running * * @return * If the thread is running, true. Otherwise false. */ public boolean isRunning() { stateLock.readLock().lock(); try { return running; } finally { stateLock.readLock().unlock(); } } /** * Returns the Time-to-live value. * * @return * The time-to-live (seconds) */ public int getTimeToLive() { stateLock.readLock().lock(); try { return (int) timeToLiveMillis / 1000; } finally { stateLock.readLock().unlock(); } } /** * Update the value for the time-to-live * * @param timeToLive * The time-to-live (seconds) */ public void setTimeToLive(long timeToLive) { stateLock.writeLock().lock(); try { this.timeToLiveMillis = timeToLive * 1000; } finally { stateLock.writeLock().unlock(); } } /** * Get the interval in which an object will live in the map before * it is removed. * * @return * The time in seconds. */ public int getExpirationInterval() { stateLock.readLock().lock(); try { return (int) expirationIntervalMillis / 1000; } finally { stateLock.readLock().unlock(); } } /** * Set the interval in which an object will live in the map before * it is removed. * * @param expirationInterval * The time in seconds */ public void setExpirationInterval(long expirationInterval) { stateLock.writeLock().lock(); try { this.expirationIntervalMillis = expirationInterval * 1000; } finally { stateLock.writeLock().unlock(); } } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/LazyInitializedCacheMap.java0000644000175000017500000001335112032276034031357 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.apache.mina.core.buffer.IoBuffer; /** * This map is specially useful when reads are much more frequent than writes and * if the cost of instantiating the values is high like allocating an * {@link IoBuffer} for example. * * Based on the final implementation of Memoizer written by Brian Goetz and Tim * Peierls. This implementation will return an * {@link UnsupportedOperationException} on each method that is not intended to * be called by user code for performance reasons. * * @author Apache MINA Project * @since MINA 2.0.0-M2 */ public class LazyInitializedCacheMap implements Map { private ConcurrentMap> cache; /** * This class provides a noop {@link LazyInitializer} meaning it * will return the same object it received when instantiated. */ public class NoopInitializer extends LazyInitializer { private V value; public NoopInitializer(V value) { this.value = value; } public V init() { return value; } } /** * Default constructor. Uses the default parameters to initialize its internal * {@link ConcurrentHashMap}. */ public LazyInitializedCacheMap() { this.cache = new ConcurrentHashMap>(); } /** * This constructor allows to provide a fine tuned {@link ConcurrentHashMap} * to stick with each special case the user needs. */ public LazyInitializedCacheMap(final ConcurrentHashMap> map) { this.cache = map; } /** * {@inheritDoc} */ public V get(Object key) { LazyInitializer c = cache.get(key); if (c != null) { return c.get(); } return null; } /** * {@inheritDoc} */ public V remove(Object key) { LazyInitializer c = cache.remove(key); if (c != null) { return c.get(); } return null; } /** * If the specified key is not already associated * with a value, associate it with the given value. * This is equivalent to *
     *   if (!map.containsKey(key))
     *       return map.put(key, value);
     *   else
     *       return map.get(key);
* except that the action is performed atomically. * * @param key key with which the specified value is to be associated * @param value a lazy initialized value object. * * @return the previous value associated with the specified key, * or null if there was no mapping for the key */ public V putIfAbsent(K key, LazyInitializer value) { LazyInitializer v = cache.get(key); if (v == null) { v = cache.putIfAbsent(key, value); if (v == null) { return value.get(); } } return v.get(); } /** * {@inheritDoc} */ public V put(K key, V value) { LazyInitializer c = cache.put(key, new NoopInitializer(value)); if (c != null) { return c.get(); } return null; } /** * @throws {@link UnsupportedOperationException} as this method would imply * performance drops. */ public boolean containsValue(Object value) { throw new UnsupportedOperationException(); } /** * @throws {@link UnsupportedOperationException} as this method would imply * performance drops. */ public Collection values() { throw new UnsupportedOperationException(); } /** * @throws {@link UnsupportedOperationException} as this method would imply * performance drops. */ public Set> entrySet() { throw new UnsupportedOperationException(); } /** * {@inheritDoc} */ public void putAll(Map m) { for (Map.Entry e : m.entrySet()) { cache.put(e.getKey(), new NoopInitializer(e.getValue())); } } /** * {@inheritDoc} */ public Collection> getValues() { return cache.values(); } /** * {@inheritDoc} */ public void clear() { cache.clear(); } /** * {@inheritDoc} */ public boolean containsKey(Object key) { return cache.containsKey(key); } /** * {@inheritDoc} */ public boolean isEmpty() { return cache.isEmpty(); } /** * {@inheritDoc} */ public Set keySet() { return cache.keySet(); } /** * {@inheritDoc} */ public int size() { return cache.size(); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/Base64.java0000644000175000017500000004160712032276034025721 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import java.security.InvalidParameterException; /** * Provides Base64 encoding and decoding as defined by RFC 2045. * *

This class implements section 6.8. Base64 Content-Transfer-Encoding * from RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: * Format of Internet Message Bodies by Freed and Borenstein.

* * @see RFC 2045 * * This class was * @author Apache Software Foundation commons codec (http://commons.apache.org/codec/) * @author Apache MINA Project */ public class Base64 { /** * Chunk size per RFC 2045 section 6.8. * *

The {@value} character limit does not count the trailing CRLF, but counts * all other characters, including any equal signs.

* * @see RFC 2045 section 6.8 */ static final int CHUNK_SIZE = 76; /** * Chunk separator per RFC 2045 section 2.1. * * @see RFC 2045 section 2.1 */ static final byte[] CHUNK_SEPARATOR = "\r\n".getBytes(); /** * The base length. */ static final int BASELENGTH = 255; /** * Lookup length. */ static final int LOOKUPLENGTH = 64; /** * Used to calculate the number of bits in a byte. */ static final int EIGHTBIT = 8; /** * Used when encoding something which has fewer than 24 bits. */ static final int SIXTEENBIT = 16; /** * Used to determine how many bits data contains. */ static final int TWENTYFOURBITGROUP = 24; /** * Used to get the number of Quadruples. */ static final int FOURBYTE = 4; /** * Used to test the sign of a byte. */ static final int SIGN = -128; /** * Byte used to pad output. */ static final byte PAD = (byte) '='; // Create arrays to hold the base64 characters and a // lookup for base64 chars private static byte[] base64Alphabet = new byte[BASELENGTH]; private static byte[] lookUpBase64Alphabet = new byte[LOOKUPLENGTH]; // Populating the lookup and character arrays static { for (int i = 0; i < BASELENGTH; i++) { base64Alphabet[i] = (byte) -1; } for (int i = 'Z'; i >= 'A'; i--) { base64Alphabet[i] = (byte) (i - 'A'); } for (int i = 'z'; i >= 'a'; i--) { base64Alphabet[i] = (byte) (i - 'a' + 26); } for (int i = '9'; i >= '0'; i--) { base64Alphabet[i] = (byte) (i - '0' + 52); } base64Alphabet['+'] = 62; base64Alphabet['/'] = 63; for (int i = 0; i <= 25; i++) { lookUpBase64Alphabet[i] = (byte) ('A' + i); } for (int i = 26, j = 0; i <= 51; i++, j++) { lookUpBase64Alphabet[i] = (byte) ('a' + j); } for (int i = 52, j = 0; i <= 61; i++, j++) { lookUpBase64Alphabet[i] = (byte) ('0' + j); } lookUpBase64Alphabet[62] = (byte) '+'; lookUpBase64Alphabet[63] = (byte) '/'; } private static boolean isBase64(byte octect) { if (octect == PAD) { return true; } else if (base64Alphabet[octect] == -1) { return false; } else { return true; } } /** * Tests a given byte array to see if it contains * only valid characters within the Base64 alphabet. * * @param arrayOctect byte array to test * @return true if all bytes are valid characters in the Base64 * alphabet or if the byte array is empty; false, otherwise */ public static boolean isArrayByteBase64(byte[] arrayOctect) { arrayOctect = discardWhitespace(arrayOctect); int length = arrayOctect.length; if (length == 0) { // shouldn't a 0 length array be valid base64 data? // return false; return true; } for (int i = 0; i < length; i++) { if (!isBase64(arrayOctect[i])) { return false; } } return true; } /** * Encodes binary data using the base64 algorithm but * does not chunk the output. * * @param binaryData binary data to encode * @return Base64 characters */ public static byte[] encodeBase64(byte[] binaryData) { return encodeBase64(binaryData, false); } /** * Encodes binary data using the base64 algorithm and chunks * the encoded output into 76 character blocks * * @param binaryData binary data to encode * @return Base64 characters chunked in 76 character blocks */ public static byte[] encodeBase64Chunked(byte[] binaryData) { return encodeBase64(binaryData, true); } /** * Decodes an Object using the base64 algorithm. This method * is provided in order to satisfy the requirements of the * Decoder interface, and will throw a DecoderException if the * supplied object is not of type byte[]. * * @param pObject Object to decode * @return An object (of type byte[]) containing the * binary data which corresponds to the byte[] supplied. * @throws InvalidParameterException if the parameter supplied is not * of type byte[] */ public Object decode(Object pObject) { if (!(pObject instanceof byte[])) { throw new InvalidParameterException("Parameter supplied to Base64 decode is not a byte[]"); } return decode((byte[]) pObject); } /** * Decodes a byte[] containing containing * characters in the Base64 alphabet. * * @param pArray A byte array containing Base64 character data * @return a byte array containing binary data */ public byte[] decode(byte[] pArray) { return decodeBase64(pArray); } /** * Encodes binary data using the base64 algorithm, optionally * chunking the output into 76 character blocks. * * @param binaryData Array containing binary data to encode. * @param isChunked if isChunked is true this encoder will chunk * the base64 output into 76 character blocks * @return Base64-encoded data. */ public static byte[] encodeBase64(byte[] binaryData, boolean isChunked) { int lengthDataBits = binaryData.length * EIGHTBIT; int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; byte encodedData[] = null; int encodedDataLength = 0; int nbrChunks = 0; if (fewerThan24bits != 0) { //data not divisible by 24 bit encodedDataLength = (numberTriplets + 1) * 4; } else { // 16 or 8 bit encodedDataLength = numberTriplets * 4; } // If the output is to be "chunked" into 76 character sections, // for compliance with RFC 2045 MIME, then it is important to // allow for extra length to account for the separator(s) if (isChunked) { nbrChunks = (CHUNK_SEPARATOR.length == 0 ? 0 : (int) Math.ceil((float) encodedDataLength / CHUNK_SIZE)); encodedDataLength += nbrChunks * CHUNK_SEPARATOR.length; } encodedData = new byte[encodedDataLength]; byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; int encodedIndex = 0; int dataIndex = 0; int i = 0; int nextSeparatorIndex = CHUNK_SIZE; int chunksSoFar = 0; //log.debug("number of triplets = " + numberTriplets); for (i = 0; i < numberTriplets; i++) { dataIndex = i * 3; b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex + 1]; b3 = binaryData[dataIndex + 2]; //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3); l = (byte) (b2 & 0x0f); k = (byte) (b1 & 0x03); byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc); encodedData[encodedIndex] = lookUpBase64Alphabet[val1]; //log.debug( "val2 = " + val2 ); //log.debug( "k4 = " + (k<<4) ); //log.debug( "vak = " + (val2 | (k<<4)) ); encodedData[encodedIndex + 1] = lookUpBase64Alphabet[val2 | (k << 4)]; encodedData[encodedIndex + 2] = lookUpBase64Alphabet[(l << 2) | val3]; encodedData[encodedIndex + 3] = lookUpBase64Alphabet[b3 & 0x3f]; encodedIndex += 4; // If we are chunking, let's put a chunk separator down. if (isChunked) { // this assumes that CHUNK_SIZE % 4 == 0 if (encodedIndex == nextSeparatorIndex) { System.arraycopy(CHUNK_SEPARATOR, 0, encodedData, encodedIndex, CHUNK_SEPARATOR.length); chunksSoFar++; nextSeparatorIndex = (CHUNK_SIZE * (chunksSoFar + 1)) + (chunksSoFar * CHUNK_SEPARATOR.length); encodedIndex += CHUNK_SEPARATOR.length; } } } // form integral number of 6-bit groups dataIndex = i * 3; if (fewerThan24bits == EIGHTBIT) { b1 = binaryData[dataIndex]; k = (byte) (b1 & 0x03); //log.debug("b1=" + b1); //log.debug("b1<<2 = " + (b1>>2) ); byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); encodedData[encodedIndex] = lookUpBase64Alphabet[val1]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[k << 4]; encodedData[encodedIndex + 2] = PAD; encodedData[encodedIndex + 3] = PAD; } else if (fewerThan24bits == SIXTEENBIT) { b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex + 1]; l = (byte) (b2 & 0x0f); k = (byte) (b1 & 0x03); byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); encodedData[encodedIndex] = lookUpBase64Alphabet[val1]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[val2 | (k << 4)]; encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2]; encodedData[encodedIndex + 3] = PAD; } if (isChunked) { // we also add a separator to the end of the final chunk. if (chunksSoFar < nbrChunks) { System.arraycopy(CHUNK_SEPARATOR, 0, encodedData, encodedDataLength - CHUNK_SEPARATOR.length, CHUNK_SEPARATOR.length); } } return encodedData; } /** * Decodes Base64 data into octects * * @param base64Data Byte array containing Base64 data * @return Array containing decoded data. */ public static byte[] decodeBase64(byte[] base64Data) { // RFC 2045 requires that we discard ALL non-Base64 characters base64Data = discardNonBase64(base64Data); // handle the edge case, so we don't have to worry about it later if (base64Data.length == 0) { return new byte[0]; } int numberQuadruple = base64Data.length / FOURBYTE; byte decodedData[] = null; byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0; // Throw away anything not in base64Data int encodedIndex = 0; int dataIndex = 0; { // this sizes the output array properly - rlw int lastData = base64Data.length; // ignore the '=' padding while (base64Data[lastData - 1] == PAD) { if (--lastData == 0) { return new byte[0]; } } decodedData = new byte[lastData - numberQuadruple]; } for (int i = 0; i < numberQuadruple; i++) { dataIndex = i * 4; marker0 = base64Data[dataIndex + 2]; marker1 = base64Data[dataIndex + 3]; b1 = base64Alphabet[base64Data[dataIndex]]; b2 = base64Alphabet[base64Data[dataIndex + 1]]; if (marker0 != PAD && marker1 != PAD) { //No PAD e.g 3cQl b3 = base64Alphabet[marker0]; b4 = base64Alphabet[marker1]; decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); decodedData[encodedIndex + 1] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4); } else if (marker0 == PAD) { //Two PAD e.g. 3c[Pad][Pad] decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); } else if (marker1 == PAD) { //One PAD e.g. 3cQ[Pad] b3 = base64Alphabet[marker0]; decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); decodedData[encodedIndex + 1] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); } encodedIndex += 3; } return decodedData; } /** * Discards any whitespace from a base-64 encoded block. * * @param data The base-64 encoded data to discard the whitespace * from. * @return The data, less whitespace (see RFC 2045). */ static byte[] discardWhitespace(byte[] data) { byte groomedData[] = new byte[data.length]; int bytesCopied = 0; for (int i = 0; i < data.length; i++) { switch (data[i]) { case (byte) ' ': case (byte) '\n': case (byte) '\r': case (byte) '\t': break; default: groomedData[bytesCopied++] = data[i]; } } byte packedData[] = new byte[bytesCopied]; System.arraycopy(groomedData, 0, packedData, 0, bytesCopied); return packedData; } /** * Discards any characters outside of the base64 alphabet, per * the requirements on page 25 of RFC 2045 - "Any characters * outside of the base64 alphabet are to be ignored in base64 * encoded data." * * @param data The base-64 encoded data to groom * @return The data, less non-base64 characters (see RFC 2045). */ static byte[] discardNonBase64(byte[] data) { byte groomedData[] = new byte[data.length]; int bytesCopied = 0; for (int i = 0; i < data.length; i++) { if (isBase64(data[i])) { groomedData[bytesCopied++] = data[i]; } } byte packedData[] = new byte[bytesCopied]; System.arraycopy(groomedData, 0, packedData, 0, bytesCopied); return packedData; } // Implementation of the Encoder Interface /** * Encodes an Object using the base64 algorithm. This method * is provided in order to satisfy the requirements of the * Encoder interface, and will throw an EncoderException if the * supplied object is not of type byte[]. * * @param pObject Object to encode * @return An object (of type byte[]) containing the * base64 encoded data which corresponds to the byte[] supplied. * @throws InvalidParameterException if the parameter supplied is not * of type byte[] */ public Object encode(Object pObject) { if (!(pObject instanceof byte[])) { throw new InvalidParameterException("Parameter supplied to Base64 encode is not a byte[]"); } return encode((byte[]) pObject); } /** * Encodes a byte[] containing binary data, into a byte[] containing * characters in the Base64 alphabet. * * @param pArray a byte array containing binary data * @return A byte array containing only Base64 character data */ public byte[] encode(byte[] pArray) { return encodeBase64(pArray, false); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/ExceptionMonitor.java0000644000175000017500000000427512032276034030203 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; /** * Monitors uncaught exceptions. {@link #exceptionCaught(Throwable)} is * invoked when there are any uncaught exceptions. *

* You can monitor any uncaught exceptions by setting {@link ExceptionMonitor} * by calling {@link #setInstance(ExceptionMonitor)}. The default * monitor logs all caught exceptions in WARN level using * SLF4J. * * @author Apache MINA Project * * @see DefaultExceptionMonitor */ public abstract class ExceptionMonitor { private static ExceptionMonitor instance = new DefaultExceptionMonitor(); /** * Returns the current exception monitor. */ public static ExceptionMonitor getInstance() { return instance; } /** * Sets the uncaught exception monitor. If null is specified, * the default monitor will be set. * * @param monitor A new instance of {@link DefaultExceptionMonitor} is set * if null is specified. */ public static void setInstance(ExceptionMonitor monitor) { if (monitor == null) { monitor = new DefaultExceptionMonitor(); } instance = monitor; } /** * Invoked when there are any uncaught exceptions. * * @param cause The caught exception */ public abstract void exceptionCaught(Throwable cause); }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/MapBackedSet.java0000644000175000017500000000400112032276034027143 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import java.io.Serializable; import java.util.AbstractSet; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * A {@link Map}-backed {@link Set}. * * @author Apache MINA Project */ public class MapBackedSet extends AbstractSet implements Serializable { private static final long serialVersionUID = -8347878570391674042L; protected final Map map; public MapBackedSet(Map map) { this.map = map; } public MapBackedSet(Map map, Collection c) { this.map = map; addAll(c); } @Override public int size() { return map.size(); } @Override public boolean contains(Object o) { return map.containsKey(o); } @Override public Iterator iterator() { return map.keySet().iterator(); } @Override public boolean add(E o) { return map.put(o, Boolean.TRUE) == null; } @Override public boolean remove(Object o) { return map.remove(o) != null; } @Override public void clear() { map.clear(); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/LazyInitializer.java0000644000175000017500000000327412032276034030016 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; /** * An abstract class which provides semantics for an object which will be only * fully initialized when requested to. It allows to avoid loosing time when * early initializing unnecessary objects. * * @author Apache MINA Project * @since MINA 2.0.0-M2 */ public abstract class LazyInitializer { /** * The value that results on the {@link #init()} call. If null, * it means that the value has not been initialized yet. */ private V value; /** * Initializes the value. * * @return the initialized value */ public abstract V init(); /** * Returns the value resulting from the initialization. * @return the initialized value */ public V get() { if (value == null) { value = init(); } return value; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/NamePreservingRunnable.java0000644000175000017500000000531012032276034031300 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.mina.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A {@link Runnable} wrapper that preserves the name of the thread after the runnable is * complete (for {@link Runnable}s that change the name of the Thread they use.) * * @author Apache MINA Project */ public class NamePreservingRunnable implements Runnable { private final static Logger LOGGER = LoggerFactory.getLogger(NamePreservingRunnable.class); /** The runnable name */ private final String newName; /** The runnable task */ private final Runnable runnable; /** * Creates a new instance of NamePreservingRunnable. * * @param runnable The underlying runnable * @param newName The runnable's name */ public NamePreservingRunnable(Runnable runnable, String newName) { this.runnable = runnable; this.newName = newName; } /** * Run the runnable after having renamed the current thread's name * to the new name. When the runnable has completed, set back the * current thread name back to its origin. */ public void run() { Thread currentThread = Thread.currentThread(); String oldName = currentThread.getName(); if (newName != null) { setName(currentThread, newName); } try { runnable.run(); } finally { setName(currentThread, oldName); } } /** * Wraps {@link Thread#setName(String)} to catch a possible {@link Exception}s such as * {@link SecurityException} in sandbox environments, such as applets */ private void setName(Thread thread, String name) { try { thread.setName(name); } catch (SecurityException se) { if (LOGGER.isWarnEnabled()) { LOGGER.warn("Failed to set the thread name.", se); } } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/Log4jXmlFormatter.java0000644000175000017500000001416012032276034030213 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import java.util.Arrays; import java.util.Map; import java.util.Set; import java.util.logging.Formatter; import java.util.logging.LogRecord; import org.slf4j.MDC; /** * Implementation of {@link java.util.logging.Formatter} that generates xml in the log4j format. *

* The generated xml corresponds 100% with what is generated by * log4j's XMLLayout *

* The MDC properties will only be correct when format is called from the same thread * that generated the LogRecord. *

* The file and line attributes in the locationInfo element will always be "?" * since java.util.logging.LogRecord does not provide that info. *

* The implementation is heavily based on org.apache.log4j.xml.XMLLayout *

* * @author Apache MINA Project */ public class Log4jXmlFormatter extends Formatter { private final int DEFAULT_SIZE = 256; private final int UPPER_LIMIT = 2048; private StringBuffer buf = new StringBuffer(DEFAULT_SIZE); private boolean locationInfo = false; private boolean properties = false; /** * The LocationInfo option takes a boolean value. By default, * it is set to false which means there will be no location * information output by this layout. If the the option is set to * true, then the file name and line number of the statement at the * origin of the log statement will be output. * * @param flag whether locationInfo should be output by this layout */ public void setLocationInfo(boolean flag) { locationInfo = flag; } /** * Returns the current value of the LocationInfo option. * * @return whether locationInfo will be output by this layout */ public boolean getLocationInfo() { return locationInfo; } /** * Sets whether MDC key-value pairs should be output, default false. * * @param flag new value. */ public void setProperties(final boolean flag) { properties = flag; } /** * Gets whether MDC key-value pairs should be output. * * @return true if MDC key-value pairs are output. */ public boolean getProperties() { return properties; } @Override @SuppressWarnings("unchecked") public String format(final LogRecord record) { // Reset working buffer. If the buffer is too large, then we need a new // one in order to avoid the penalty of creating a large array. if (buf.capacity() > UPPER_LIMIT) { buf = new StringBuffer(DEFAULT_SIZE); } else { buf.setLength(0); } buf.append("\r\n"); buf.append("\r\n"); if (record.getThrown() != null) { String[] s = Transform.getThrowableStrRep(record.getThrown()); if (s != null) { buf.append("\r\n"); } } if (locationInfo) { buf.append("\r\n"); } if (properties) { Map contextMap = MDC.getCopyOfContextMap(); if (contextMap != null) { Set keySet = contextMap.keySet(); if ((keySet != null) && (keySet.size() > 0)) { buf.append("\r\n"); Object[] keys = keySet.toArray(); Arrays.sort(keys); for (Object key1 : keys) { String key = (key1 == null ? "" : key1.toString()); Object val = contextMap.get(key); if (val != null) { buf.append("\r\n"); } } buf.append("\r\n"); } } } buf.append("\r\n\r\n"); return buf.toString(); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/0000755000175000017500000000000012162575507026162 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeWriter.java0000644000175000017500000000444212032276033032255 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util.byteaccess; import java.nio.ByteOrder; import org.apache.mina.core.buffer.IoBuffer; /** * Provides relative read access to a sequence of bytes. * * @author Apache MINA Project */ public interface IoRelativeWriter { /** * Gets the number of remaining bytes that can be read. */ int getRemaining(); /** * Checks if there are any remaining bytes that can be read. */ boolean hasRemaining(); /** * Advances the writer by the given number of bytes. */ void skip(int length); /** * Gets the order of the bytes. */ ByteOrder order(); /** * Puts a byte and advances the reader. */ void put(byte b); /** * Puts enough bytes to fill the IoBuffer and advances the reader. */ void put(IoBuffer bb); /** * Puts a short and advances the reader. */ void putShort(short s); /** * Puts an int and advances the reader. */ void putInt(int i); /** * Puts a long and advances the reader. */ void putLong(long l); /** * Puts a float and advances the reader. */ void putFloat(float f); /** * Puts a double and advances the reader. */ void putDouble(double d); /** * Puts a char and advances the reader. */ void putChar(char c); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/AbstractByteArray.java0000644000175000017500000000476112032276033032407 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util.byteaccess; /** * * Abstract class that implements {@link ByteArray}. This class will only be * used internally and should not be used by end users. * * @author Apache MINA Project */ abstract class AbstractByteArray implements ByteArray { /** * @inheritDoc */ public final int length() { return last() - first(); } /** * @inheritDoc */ @Override public final boolean equals(Object other) { // Optimization: compare pointers. if (other == this) { return true; } // Compare types. if (!(other instanceof ByteArray)) { return false; } ByteArray otherByteArray = (ByteArray) other; // Compare properties. if (first() != otherByteArray.first() || last() != otherByteArray.last() || !order().equals(otherByteArray.order())) { return false; } // Compare bytes. Cursor cursor = cursor(); Cursor otherCursor = otherByteArray.cursor(); for (int remaining = cursor.getRemaining(); remaining > 0;) { // Optimization: prefer int comparisons over byte comparisons if (remaining >= 4) { int i = cursor.getInt(); int otherI = otherCursor.getInt(); if (i != otherI) { return false; } } else { byte b = cursor.get(); byte otherB = otherCursor.get(); if (b != otherB) { return false; } } } return true; } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeBase.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelat0000644000175000017500000000742012032276033032651 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util.byteaccess; import java.nio.ByteOrder; import org.apache.mina.util.byteaccess.ByteArray.Cursor; import org.apache.mina.util.byteaccess.CompositeByteArray.CursorListener; /** * Provides common functionality between the * CompositeByteArrayRelativeReader and * CompositeByteArrayRelativeWriter. * * @author Apache MINA Project */ abstract class CompositeByteArrayRelativeBase { /** * The underlying CompositeByteArray. */ protected final CompositeByteArray cba; /** * A cursor of the underlying CompositeByteArray. This * cursor is never moved directly; its position only changes through calls * to relative read or write methods. */ protected final Cursor cursor; /** * * Creates a new instance of CompositeByteArrayRelativeBase. * * @param cba * The {@link CompositeByteArray} that will be the base for this class */ public CompositeByteArrayRelativeBase(CompositeByteArray cba) { this.cba = cba; cursor = cba.cursor(cba.first(), new CursorListener() { public void enteredFirstComponent(int componentIndex, ByteArray component) { // Do nothing. } public void enteredLastComponent(int componentIndex, ByteArray component) { assert false; } public void enteredNextComponent(int componentIndex, ByteArray component) { cursorPassedFirstComponent(); } public void enteredPreviousComponent(int componentIndex, ByteArray component) { assert false; } }); } /** * @inheritDoc */ public final int getRemaining() { return cursor.getRemaining(); } /** * @inheritDoc */ public final boolean hasRemaining() { return cursor.hasRemaining(); } /** * @inheritDoc */ public ByteOrder order() { return cba.order(); } /** * Make a ByteArray available for access at the end of this object. */ public final void append(ByteArray ba) { cba.addLast(ba); } /** * Free all resources associated with this object. */ public final void free() { cba.free(); } /** * Get the index that will be used for the next access. */ public final int getIndex() { return cursor.getIndex(); } /** * Get the index after the last byte that can be accessed. */ public final int last() { return cba.last(); } /** * Called whenever the cursor has passed from the cba's * first component. As the first component is no longer used, this provides * a good opportunity for subclasses to perform some action on it (such as * freeing it). */ protected abstract void cursorPassedFirstComponent(); } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeWriter.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelat0000644000175000017500000001356112032276033032654 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util.byteaccess; import org.apache.mina.core.buffer.IoBuffer; /** * Provides restricted, relative, write-only access to the bytes in a * CompositeByteArray. * * Using this interface has the advantage that it can be automatically * determined when a component ByteArray can no longer be written * to, and thus components can be automatically flushed. This makes it easier to * use pooling for underlying ByteArrays. * * By providing an appropriate Expander it is also possible to * automatically add more backing storage as more data is written. *

* TODO: Get flushing working. * * @author Apache MINA Project */ public class CompositeByteArrayRelativeWriter extends CompositeByteArrayRelativeBase implements IoRelativeWriter { /** * An object that knows how to expand a CompositeByteArray. */ public interface Expander { void expand(CompositeByteArray cba, int minSize); } /** * No-op expander. The overridden method does nothing. * */ public static class NopExpander implements Expander { public void expand(CompositeByteArray cba, int minSize) { // Do nothing. } } /** * Expands the supplied {@link CompositeByteArray} by the number of * bytes provided in the constructor * */ public static class ChunkedExpander implements Expander { private final ByteArrayFactory baf; private final int newComponentSize; public ChunkedExpander(ByteArrayFactory baf, int newComponentSize) { this.baf = baf; this.newComponentSize = newComponentSize; } public void expand(CompositeByteArray cba, int minSize) { int remaining = minSize; while (remaining > 0) { ByteArray component = baf.create(newComponentSize); cba.addLast(component); remaining -= newComponentSize; } } } /** * An object that knows how to flush a ByteArray. */ public interface Flusher { // document free() behaviour void flush(ByteArray ba); } /** * The expander to use when the array underflows. */ private final Expander expander; /** * The flusher to use when flushing component ByteArrays. */ private final Flusher flusher; /** * Whether or not to automatically flush a component once the cursor moves * past it. */ private final boolean autoFlush; /** * * Creates a new instance of CompositeByteArrayRelativeWriter. * * @param cba * The CompositeByteArray to use to back this class * @param expander * The expander. Will increase the size of the internal ByteArray * @param flusher * Flushed the ByteArray when necessary * @param autoFlush * Should this class automatically flush? */ public CompositeByteArrayRelativeWriter(CompositeByteArray cba, Expander expander, Flusher flusher, boolean autoFlush) { super(cba); this.expander = expander; this.flusher = flusher; this.autoFlush = autoFlush; } private void prepareForAccess(int size) { int underflow = cursor.getIndex() + size - last(); if (underflow > 0) { expander.expand(cba, underflow); } } /** * Flush to the current index. */ public void flush() { flushTo(cursor.getIndex()); } /** * Flush to the given index. */ public void flushTo(int index) { ByteArray removed = cba.removeTo(index); flusher.flush(removed); } /** * @inheritDoc */ public void skip(int length) { cursor.skip(length); } @Override protected void cursorPassedFirstComponent() { if (autoFlush) { flushTo(cba.first() + cba.getFirst().length()); } } /** * @inheritDoc */ public void put(byte b) { prepareForAccess(1); cursor.put(b); } /** * @inheritDoc */ public void put(IoBuffer bb) { prepareForAccess(bb.remaining()); cursor.put(bb); } /** * @inheritDoc */ public void putShort(short s) { prepareForAccess(2); cursor.putShort(s); } /** * @inheritDoc */ public void putInt(int i) { prepareForAccess(4); cursor.putInt(i); } /** * @inheritDoc */ public void putLong(long l) { prepareForAccess(8); cursor.putLong(l); } /** * @inheritDoc */ public void putFloat(float f) { prepareForAccess(4); cursor.putFloat(f); } /** * @inheritDoc */ public void putDouble(double d) { prepareForAccess(8); cursor.putDouble(d); } /** * @inheritDoc */ public void putChar(char c) { prepareForAccess(2); cursor.putChar(c); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeReader.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelat0000644000175000017500000000644412032276033032656 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util.byteaccess; import org.apache.mina.core.buffer.IoBuffer; /** * Provides restricted, relative, read-only access to the bytes in a * CompositeByteArray. Using this interface has the advantage * that it can be automatically determined when a component * ByteArray can no longer be read, and thus components can be * automatically freed. This makes it easier to use pooling for underlying * ByteArrays. * * @author Apache MINA Project */ public class CompositeByteArrayRelativeReader extends CompositeByteArrayRelativeBase implements IoRelativeReader { /** * Whether or not to free component CompositeByteArrays when * the cursor moves past them. */ private final boolean autoFree; /** * * Creates a new instance of CompositeByteArrayRelativeReader. * * @param cba * The backing ByteArray * @param autoFree * If data should be freed once it has been passed in the list */ public CompositeByteArrayRelativeReader(CompositeByteArray cba, boolean autoFree) { super(cba); this.autoFree = autoFree; } @Override protected void cursorPassedFirstComponent() { if (autoFree) { cba.removeFirst().free(); } } /** * @inheritDoc */ public void skip(int length) { cursor.skip(length); } /** * @inheritDoc */ public ByteArray slice(int length) { return cursor.slice(length); } /** * Returns the byte at the current position in the buffer * */ public byte get() { return cursor.get(); } /** * places the data starting at current position into the * supplied {@link IoBuffer} */ public void get(IoBuffer bb) { cursor.get(bb); } /** * @inheritDoc */ public short getShort() { return cursor.getShort(); } /** * @inheritDoc */ public int getInt() { return cursor.getInt(); } /** * @inheritDoc */ public long getLong() { return cursor.getLong(); } /** * @inheritDoc */ public float getFloat() { return cursor.getFloat(); } /** * @inheritDoc */ public double getDouble() { return cursor.getDouble(); } /** * @inheritDoc */ public char getChar() { return cursor.getChar(); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/SimpleByteArrayFactory.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/SimpleByteArrayFactory.0000644000175000017500000000341212032276033032553 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util.byteaccess; import org.apache.mina.core.buffer.IoBuffer; /** * Creates ByteArray backed by a heap-allocated * IoBuffer. The free method on returned * ByteArrays is a nop. * * @author Apache MINA Project */ public class SimpleByteArrayFactory implements ByteArrayFactory { /** * * Creates a new instance of SimpleByteArrayFactory. * */ public SimpleByteArrayFactory() { super(); } /** * @inheritDoc */ public ByteArray create(int size) { if (size < 0) { throw new IllegalArgumentException("Buffer size must not be negative:" + size); } IoBuffer bb = IoBuffer.allocate(size); ByteArray ba = new BufferByteArray(bb) { @Override public void free() { // Nothing to do. } }; return ba; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/ByteArrayFactory.java0000644000175000017500000000236412032276033032250 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util.byteaccess; /** * A factory for ByteArrays. * * @author Apache MINA Project */ public interface ByteArrayFactory { /** * Creates an instance of {@link ByteArray} of size specified by the * size parameter. * * @param size * The size of the ByteArray * @return * The ByteArray */ ByteArray create(int size); }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/BufferByteArray.java0000644000175000017500000002220712032276033032050 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util.byteaccess; import java.nio.ByteOrder; import java.util.Collections; import org.apache.mina.core.buffer.IoBuffer; /** * A ByteArray backed by a IoBuffer. This class * is abstract. Subclasses need to override the free() method. An * implementation backed by a heap IoBuffer can be created with * a SimpleByteArrayFactory. * * @author Apache MINA Project */ public abstract class BufferByteArray extends AbstractByteArray { /** * The backing IoBuffer. */ protected IoBuffer bb; /** * * Creates a new instance of BufferByteArray and uses the supplied * {@link IoBuffer} to back this class * * @param bb * The backing buffer */ public BufferByteArray(IoBuffer bb) { this.bb = bb; } /** * @inheritDoc */ public Iterable getIoBuffers() { return Collections.singletonList(bb); } /** * @inheritDoc */ public IoBuffer getSingleIoBuffer() { return bb; } /** * @inheritDoc * * Calling free() on the returned slice has no effect. */ public ByteArray slice(int index, int length) { int oldLimit = bb.limit(); bb.position(index); bb.limit(index + length); IoBuffer slice = bb.slice(); bb.limit(oldLimit); return new BufferByteArray(slice) { @Override public void free() { // Do nothing. } }; } /** * @inheritDoc */ public abstract void free(); /** * @inheritDoc */ public Cursor cursor() { return new CursorImpl(); } /** * @inheritDoc */ public Cursor cursor(int index) { return new CursorImpl(index); } /** * @inheritDoc */ public int first() { return 0; } /** * @inheritDoc */ public int last() { return bb.limit(); } /** * @inheritDoc */ public ByteOrder order() { return bb.order(); } /** * @inheritDoc */ public void order(ByteOrder order) { bb.order(order); } /** * @inheritDoc */ public byte get(int index) { return bb.get(index); } /** * @inheritDoc */ public void put(int index, byte b) { bb.put(index, b); } /** * @inheritDoc */ public void get(int index, IoBuffer other) { bb.position(index); other.put(bb); } /** * @inheritDoc */ public void put(int index, IoBuffer other) { bb.position(index); bb.put(other); } /** * @inheritDoc */ public short getShort(int index) { return bb.getShort(index); } /** * @inheritDoc */ public void putShort(int index, short s) { bb.putShort(index, s); } /** * @inheritDoc */ public int getInt(int index) { return bb.getInt(index); } /** * @inheritDoc */ public void putInt(int index, int i) { bb.putInt(index, i); } /** * @inheritDoc */ public long getLong(int index) { return bb.getLong(index); } /** * @inheritDoc */ public void putLong(int index, long l) { bb.putLong(index, l); } /** * @inheritDoc */ public float getFloat(int index) { return bb.getFloat(index); } /** * @inheritDoc */ public void putFloat(int index, float f) { bb.putFloat(index, f); } /** * @inheritDoc */ public double getDouble(int index) { return bb.getDouble(index); } /** * @inheritDoc */ public void putDouble(int index, double d) { bb.putDouble(index, d); } /** * @inheritDoc */ public char getChar(int index) { return bb.getChar(index); } /** * @inheritDoc */ public void putChar(int index, char c) { bb.putChar(index, c); } private class CursorImpl implements Cursor { private int index; public CursorImpl() { // This space intentionally blank. } public CursorImpl(int index) { setIndex(index); } /** * @inheritDoc */ public int getRemaining() { return last() - index; } /** * @inheritDoc */ public boolean hasRemaining() { return getRemaining() > 0; } /** * @inheritDoc */ public int getIndex() { return index; } /** * @inheritDoc */ public void setIndex(int index) { if (index < 0 || index > last()) { throw new IndexOutOfBoundsException(); } this.index = index; } public void skip(int length) { setIndex(index + length); } public ByteArray slice(int length) { ByteArray slice = BufferByteArray.this.slice(index, length); index += length; return slice; } /** * @inheritDoc */ public ByteOrder order() { return BufferByteArray.this.order(); } /** * @inheritDoc */ public byte get() { byte b = BufferByteArray.this.get(index); index += 1; return b; } /** * @inheritDoc */ public void put(byte b) { BufferByteArray.this.put(index, b); index += 1; } /** * @inheritDoc */ public void get(IoBuffer bb) { int size = Math.min(getRemaining(), bb.remaining()); BufferByteArray.this.get(index, bb); index += size; } /** * @inheritDoc */ public void put(IoBuffer bb) { int size = bb.remaining(); BufferByteArray.this.put(index, bb); index += size; } /** * @inheritDoc */ public short getShort() { short s = BufferByteArray.this.getShort(index); index += 2; return s; } /** * @inheritDoc */ public void putShort(short s) { BufferByteArray.this.putShort(index, s); index += 2; } /** * @inheritDoc */ public int getInt() { int i = BufferByteArray.this.getInt(index); index += 4; return i; } /** * @inheritDoc */ public void putInt(int i) { BufferByteArray.this.putInt(index, i); index += 4; } /** * @inheritDoc */ public long getLong() { long l = BufferByteArray.this.getLong(index); index += 8; return l; } /** * @inheritDoc */ public void putLong(long l) { BufferByteArray.this.putLong(index, l); index += 8; } /** * @inheritDoc */ public float getFloat() { float f = BufferByteArray.this.getFloat(index); index += 4; return f; } /** * @inheritDoc */ public void putFloat(float f) { BufferByteArray.this.putFloat(index, f); index += 4; } /** * @inheritDoc */ public double getDouble() { double d = BufferByteArray.this.getDouble(index); index += 8; return d; } /** * @inheritDoc */ public void putDouble(double d) { BufferByteArray.this.putDouble(index, d); index += 8; } /** * @inheritDoc */ public char getChar() { char c = BufferByteArray.this.getChar(index); index += 2; return c; } /** * @inheritDoc */ public void putChar(char c) { BufferByteArray.this.putChar(index, c); index += 2; } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/IoAbsoluteReader.java0000644000175000017500000000462012032276033032204 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util.byteaccess; import java.nio.ByteOrder; import org.apache.mina.core.buffer.IoBuffer; /** * Provides absolute read access to a sequence of bytes. * * @author Apache MINA Project */ public interface IoAbsoluteReader { /** * Get the index of the first byte that can be accessed. */ int first(); /** * Gets the index after the last byte that can be accessed. */ int last(); /** * Gets the total number of bytes that can be accessed. */ int length(); /** * Creates an array with a view of part of this array. */ ByteArray slice(int index, int length); /** * Gets the order of the bytes. */ ByteOrder order(); /** * Gets a byte from the given index. */ byte get(int index); /** * Gets enough bytes to fill the IoBuffer from the given index. */ public void get(int index, IoBuffer bb); /** * Gets a short from the given index. */ short getShort(int index); /** * Gets an int from the given index. */ int getInt(int index); /** * Gets a long from the given index. */ long getLong(int index); /** * Gets a float from the given index. */ float getFloat(int index); /** * Gets a double from the given index. */ double getDouble(int index); /** * Gets a char from the given index. */ char getChar(int index); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/ByteArrayList.java0000644000175000017500000001471212032276033031554 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util.byteaccess; import java.util.NoSuchElementException; /** * A linked list that stores ByteArrays and maintains several useful invariants. * * @author Apache MINA Project */ class ByteArrayList { /** * A {@link Node} which indicates the start and end of the list and does not * hold a value. The value of next is the first item in the * list. The value of of previous is the last item in the list. */ private final Node header; /** * The first byte in the array list */ private int firstByte; /** * The last byte in the array list */ private int lastByte; /** * * Creates a new instance of ByteArrayList. * */ protected ByteArrayList() { header = new Node(); } /** * * Returns the last byte in the array list * * @return * The last byte in the array list */ public int lastByte() { return lastByte; } /** * * Returns the first byte in the array list * * @return * The first byte in the array list */ public int firstByte() { return firstByte; } /** * * Check to see if this is empty * * @return * True if empty, otherwise false */ public boolean isEmpty() { return header.next == header; } /** * Returns the first node in the byte array * * @return * */ public Node getFirst() { return header.getNextNode(); } /** * Returns the last {@link Node} in the list * * @return * The last node in the list */ public Node getLast() { return header.getPreviousNode(); } /** * Adds the specified {@link ByteArray} to * the beginning of the list * * @param ba * The ByteArray to be added to the list */ public void addFirst(ByteArray ba) { addNode(new Node(ba), header.next); firstByte -= ba.last(); } /** * Add the specified {@link ByteArray} to * the end of the list * * @param ba * The ByteArray to be added to the list */ public void addLast(ByteArray ba) { addNode(new Node(ba), header); lastByte += ba.last(); } /** * Removes the first node from this list * * @return * The node that was removed */ public Node removeFirst() { Node node = header.getNextNode(); firstByte += node.ba.last(); return removeNode(node); } /** * Removes the last node in this list * * @return * The node that was taken off of the list */ public Node removeLast() { Node node = header.getPreviousNode(); lastByte -= node.ba.last(); return removeNode(node); } //----------------------------------------------------------------------- /** * Inserts a new node into the list. * * @param nodeToInsert new node to insert * @param insertBeforeNode node to insert before */ protected void addNode(Node nodeToInsert, Node insertBeforeNode) { // Insert node. nodeToInsert.next = insertBeforeNode; nodeToInsert.previous = insertBeforeNode.previous; insertBeforeNode.previous.next = nodeToInsert; insertBeforeNode.previous = nodeToInsert; } /** * Removes the specified node from the list. * * @param node the node to remove */ protected Node removeNode(Node node) { // Remove node. node.previous.next = node.next; node.next.previous = node.previous; node.removed = true; return node; } //----------------------------------------------------------------------- /** * A node within the linked list. *

* From Commons Collections 3.1, all access to the value property * is via the methods on this class. */ public class Node { /** A pointer to the node before this node */ private Node previous; /** A pointer to the node after this node */ private Node next; /** The ByteArray contained within this node */ private ByteArray ba; private boolean removed; /** * Constructs a new header node. */ private Node() { super(); previous = this; next = this; } /** * Constructs a new node with a value. */ private Node(ByteArray ba) { super(); if (ba == null) { throw new IllegalArgumentException("ByteArray must not be null."); } this.ba = ba; } /** * Gets the previous node. * * @return the previous node */ public Node getPreviousNode() { if (!hasPreviousNode()) { throw new NoSuchElementException(); } return previous; } /** * Gets the next node. * * @return the next node */ public Node getNextNode() { if (!hasNextNode()) { throw new NoSuchElementException(); } return next; } public boolean hasPreviousNode() { return previous != header; } public boolean hasNextNode() { return next != header; } public ByteArray getByteArray() { return ba; } public boolean isRemoved() { return removed; } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeReader.java0000644000175000017500000000454512032276033032207 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util.byteaccess; import java.nio.ByteOrder; import org.apache.mina.core.buffer.IoBuffer; /** * Provides relative read access to a sequence of bytes. * * @author Apache MINA Project */ public interface IoRelativeReader { /** * Gets the number of remaining bytes that can be read. */ int getRemaining(); /** * Checks if there are any remaining bytes that can be read. */ boolean hasRemaining(); /** * Advances the reader by the given number of bytes. */ void skip(int length); /** * Creates an array with a view of part of this array. */ ByteArray slice(int length); /** * Gets the order of the bytes. */ ByteOrder order(); /** * Gets a byte and advances the reader. */ byte get(); /** * Gets enough bytes to fill the IoBuffer and advances the reader. */ void get(IoBuffer bb); /** * Gets a short and advances the reader. */ short getShort(); /** * Gets an int and advances the reader. */ int getInt(); /** * Gets a long and advances the reader. */ long getLong(); /** * Gets a float and advances the reader. */ float getFloat(); /** * Gets a double and advances the reader. */ double getDouble(); /** * Gets a char and advances the reader. */ char getChar(); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/ByteArray.java0000644000175000017500000000744712032276033030727 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util.byteaccess; import java.nio.ByteOrder; import org.apache.mina.core.buffer.IoBuffer; /** * Represents a sequence of bytes that can be read or written directly or * through a cursor. * * @author Apache MINA Project */ public interface ByteArray extends IoAbsoluteReader, IoAbsoluteWriter { /** * @inheritDoc */ int first(); /** * @inheritDoc */ int last(); /** * @inheritDoc */ ByteOrder order(); /** * Set the byte order of the array. */ void order(ByteOrder order); /** * Remove any resources associated with this object. Using the object after * this method is called may result in undefined behaviour. */ void free(); /** * Get the sequence of IoBuffers that back this array. * Compared to getSingleIoBuffer(), this method should be * relatively efficient for all implementations. */ Iterable getIoBuffers(); /** * Gets a single IoBuffer that backs this array. Some * implementations may initially have data split across multiple buffers, so * calling this method may require a new buffer to be allocated and * populated. */ IoBuffer getSingleIoBuffer(); /** * A ByteArray is equal to another ByteArray if they start and end at the * same index, have the same byte order, and contain the same bytes at each * index. */ public boolean equals(Object other); /** * @inheritDoc */ byte get(int index); /** * @inheritDoc */ public void get(int index, IoBuffer bb); /** * @inheritDoc */ int getInt(int index); /** * Get a cursor starting at index 0 (which may not be the start of the array). */ Cursor cursor(); /** * Get a cursor starting at the given index. */ Cursor cursor(int index); /** * Provides relocatable, relative access to the underlying array. Multiple * cursors may be used simultaneously, and cursors will stay consistent with * the underlying array, even across modifications. * * Should this be Cloneable to allow cheap mark/position * emulation? */ public interface Cursor extends IoRelativeReader, IoRelativeWriter { /** * Gets the current index of the cursor. */ int getIndex(); /** * Sets the current index of the cursor. No bounds checking will occur * until an access occurs. */ void setIndex(int index); /** * @inheritDoc */ int getRemaining(); /** * @inheritDoc */ boolean hasRemaining(); /** * @inheritDoc */ byte get(); /** * @inheritDoc */ void get(IoBuffer bb); /** * @inheritDoc */ int getInt(); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/ByteArrayPool.java0000644000175000017500000001066512032276033031555 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util.byteaccess; import java.util.ArrayList; import java.util.Stack; import org.apache.mina.core.buffer.IoBuffer; /** * Creates ByteArrays, using a pool to reduce allocation where possible. * * WARNING: This code has never been run! * * * @author Apache MINA Project */ public class ByteArrayPool implements ByteArrayFactory { private final int MAX_BITS = 32; private boolean freed; private final boolean direct; private ArrayList> freeBuffers; private int freeBufferCount = 0; private long freeMemory = 0; private final int maxFreeBuffers; private final int maxFreeMemory; /** * Creates a new instance of ByteArrayPool. * * @param direct * If we should use direct buffers * @param maxFreeBuffers * The maximum number of free buffers * @param maxFreeMemory * The maximum amount of free memory allowed */ public ByteArrayPool(boolean direct, int maxFreeBuffers, int maxFreeMemory) { this.direct = direct; freeBuffers = new ArrayList>(); for (int i = 0; i < MAX_BITS; i++) { freeBuffers.add(new Stack()); } this.maxFreeBuffers = maxFreeBuffers; this.maxFreeMemory = maxFreeMemory; this.freed = false; } /** * Creates a new instance of a {@link ByteArray} * * @param size * The size of the array to build */ public ByteArray create(int size) { if (size < 1) { throw new IllegalArgumentException("Buffer size must be at least 1: " + size); } int bits = bits(size); synchronized (this) { if (!freeBuffers.get(bits).isEmpty()) { DirectBufferByteArray ba = freeBuffers.get(bits).pop(); ba.setFreed(false); ba.getSingleIoBuffer().limit(size); return ba; } } IoBuffer bb; int bbSize = 1 << bits; bb = IoBuffer.allocate(bbSize, direct); bb.limit(size); DirectBufferByteArray ba = new DirectBufferByteArray(bb); ba.setFreed(false); return ba; } private int bits(int index) { int bits = 0; while (1 << bits < index) { bits++; } return bits; } /** * Frees the buffers * */ public void free() { synchronized (this) { if (freed) { throw new IllegalStateException("Already freed."); } freed = true; freeBuffers.clear(); freeBuffers = null; } } private class DirectBufferByteArray extends BufferByteArray { public boolean freed; public DirectBufferByteArray(IoBuffer bb) { super(bb); } public void setFreed(boolean freed) { this.freed = freed; } @Override public void free() { synchronized (this) { if (freed) { throw new IllegalStateException("Already freed."); } freed = true; } int bits = bits(last()); synchronized (ByteArrayPool.this) { if (freeBuffers != null && freeBufferCount < maxFreeBuffers && freeMemory + last() <= maxFreeMemory) { freeBuffers.get(bits).push(this); freeBufferCount++; freeMemory += last(); return; } } } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArray.java0000644000175000017500000007225612032276033032612 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util.byteaccess; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.util.byteaccess.ByteArrayList.Node; /** * A ByteArray composed of other ByteArrays. Optimised for fast relative access * via cursors. Absolute access methods are provided, but may perform poorly. * * TODO: Write about laziness of cursor implementation - how movement doesn't * happen until actual get/put. * * @author Apache MINA Project */ public final class CompositeByteArray extends AbstractByteArray { /** * Allows for efficient detection of component boundaries when using a cursor. * * TODO: Is this interface right? */ public interface CursorListener { /** * Called when the first component in the composite is entered by the cursor. */ public void enteredFirstComponent(int componentIndex, ByteArray component); /** * Called when the next component in the composite is entered by the cursor. */ public void enteredNextComponent(int componentIndex, ByteArray component); /** * Called when the previous component in the composite is entered by the cursor. */ public void enteredPreviousComponent(int componentIndex, ByteArray component); /** * Called when the last component in the composite is entered by the cursor. */ public void enteredLastComponent(int componentIndex, ByteArray component); } /** * Stores the underlying ByteArrays. */ private final ByteArrayList bas = new ByteArrayList(); /** * The byte order for data in the buffer */ private ByteOrder order; /** * May be used in getSingleIoBuffer. Optional. */ private final ByteArrayFactory byteArrayFactory; /** * Creates a new instance of CompositeByteArray. */ public CompositeByteArray() { this(null); } /** * * Creates a new instance of CompositeByteArray. * * @param byteArrayFactory * The factory used to create the ByteArray objects */ public CompositeByteArray(ByteArrayFactory byteArrayFactory) { this.byteArrayFactory = byteArrayFactory; } /** * Returns the first {@link ByteArray} in the list * * @return * The first ByteArray in the list */ public ByteArray getFirst() { if (bas.isEmpty()) { return null; } return bas.getFirst().getByteArray(); } /** * Adds the specified {@link ByteArray} to the first * position in the list * * @param ba * The ByteArray to add to the list */ public void addFirst(ByteArray ba) { addHook(ba); bas.addFirst(ba); } /** * Remove the first {@link ByteArray} in the list * * @return * The first ByteArray in the list */ public ByteArray removeFirst() { Node node = bas.removeFirst(); return node == null ? null : node.getByteArray(); } /** * Remove component ByteArrays to the given index (splitting * them if necessary) and returning them in a single ByteArray. * The caller is responsible for freeing the returned object. * * TODO: Document free behaviour more thoroughly. */ public ByteArray removeTo(int index) { if (index < first() || index > last()) { throw new IndexOutOfBoundsException(); } // Optimisation when removing exactly one component. // if (index == start() + getFirst().length()) { // ByteArray component = getFirst(); // removeFirst(); // return component; // } // Removing CompositeByteArray prefix = new CompositeByteArray(byteArrayFactory); int remaining = index - first(); while (remaining > 0) { ByteArray component = removeFirst(); if (component.last() <= remaining) { // Remove entire component. prefix.addLast(component); remaining -= component.last(); } else { // Remove part of component. Do this by removing entire // component then readding remaining bytes. // TODO: Consider using getIoBuffers(), as would avoid // performance problems for nested ComponentByteArrays. IoBuffer bb = component.getSingleIoBuffer(); // get the limit of the buffer int originalLimit = bb.limit(); // set the position to the beginning of the buffer bb.position(0); // set the limit of the buffer to what is remaining bb.limit(remaining); // create a new IoBuffer, sharing the data with 'bb' IoBuffer bb1 = bb.slice(); // set the position at the end of the buffer bb.position(remaining); // gets the limit of the buffer bb.limit(originalLimit); // create a new IoBuffer, sharing teh data with 'bb' IoBuffer bb2 = bb.slice(); // create a new ByteArray with 'bb1' ByteArray ba1 = new BufferByteArray(bb1) { @Override public void free() { // Do not free. This will get freed } }; // add the new ByteArray to the CompositeByteArray prefix.addLast(ba1); remaining -= ba1.last(); // final for anonymous inner class final ByteArray componentFinal = component; ByteArray ba2 = new BufferByteArray(bb2) { @Override public void free() { componentFinal.free(); } }; // add the new ByteArray to the CompositeByteArray addFirst(ba2); } } // return the CompositeByteArray return prefix; } /** * Adds the specified {@link ByteArray} to the end of the list * * @param ba * The ByteArray to add to the end of the list */ public void addLast(ByteArray ba) { addHook(ba); bas.addLast(ba); } /** * Removes the last {@link ByteArray} in the list * * @return * The ByteArray that was removed */ public ByteArray removeLast() { Node node = bas.removeLast(); return node == null ? null : node.getByteArray(); } /** * @inheritDoc */ public void free() { while (!bas.isEmpty()) { Node node = bas.getLast(); node.getByteArray().free(); bas.removeLast(); } } private void checkBounds(int index, int accessSize) { int lower = index; int upper = index + accessSize; if (lower < first()) { throw new IndexOutOfBoundsException("Index " + lower + " less than start " + first() + "."); } if (upper > last()) { throw new IndexOutOfBoundsException("Index " + upper + " greater than length " + last() + "."); } } /** * @inheritDoc */ public Iterable getIoBuffers() { if (bas.isEmpty()) { return Collections.emptyList(); } Collection result = new ArrayList(); Node node = bas.getFirst(); for (IoBuffer bb : node.getByteArray().getIoBuffers()) { result.add(bb); } while (node.hasNextNode()) { node = node.getNextNode(); for (IoBuffer bb : node.getByteArray().getIoBuffers()) { result.add(bb); } } return result; } /** * @inheritDoc */ public IoBuffer getSingleIoBuffer() { if (byteArrayFactory == null) { throw new IllegalStateException( "Can't get single buffer from CompositeByteArray unless it has a ByteArrayFactory."); } if (bas.isEmpty()) { ByteArray ba = byteArrayFactory.create(1); return ba.getSingleIoBuffer(); } int actualLength = last() - first(); { Node node = bas.getFirst(); ByteArray ba = node.getByteArray(); if (ba.last() == actualLength) { return ba.getSingleIoBuffer(); } } // Replace all nodes with a single node. ByteArray target = byteArrayFactory.create(actualLength); IoBuffer bb = target.getSingleIoBuffer(); Cursor cursor = cursor(); cursor.put(bb); // Copy all existing data into target IoBuffer. while (!bas.isEmpty()) { Node node = bas.getLast(); ByteArray component = node.getByteArray(); bas.removeLast(); component.free(); } bas.addLast(target); return bb; } /** * @inheritDoc */ public Cursor cursor() { return new CursorImpl(); } /** * @inheritDoc */ public Cursor cursor(int index) { return new CursorImpl(index); } /** * Get a cursor starting at index 0 (which may not be the start of the * array) and with the given listener. * * @param listener * Returns a new {@link Cursor} instance */ public Cursor cursor(CursorListener listener) { return new CursorImpl(listener); } /** * Get a cursor starting at the given index and with the given listener. * * @param index * The position of the array to start the Cursor at * @param listener * The listener for the Cursor that is returned */ public Cursor cursor(int index, CursorListener listener) { return new CursorImpl(index, listener); } /** * @inheritDoc */ public ByteArray slice(int index, int length) { return cursor(index).slice(length); } /** * @inheritDoc */ public byte get(int index) { return cursor(index).get(); } /** * @inheritDoc */ public void put(int index, byte b) { cursor(index).put(b); } /** * @inheritDoc */ public void get(int index, IoBuffer bb) { cursor(index).get(bb); } /** * @inheritDoc */ public void put(int index, IoBuffer bb) { cursor(index).put(bb); } /** * @inheritDoc */ public int first() { return bas.firstByte(); } /** * @inheritDoc */ public int last() { return bas.lastByte(); } /** * This method should be called prior to adding any component * ByteArray to a composite. * * @param ba * The component to add. */ private void addHook(ByteArray ba) { // Check first() is zero, otherwise cursor might not work. // TODO: Remove this restriction? if (ba.first() != 0) { throw new IllegalArgumentException("Cannot add byte array that doesn't start from 0: " + ba.first()); } // Check order. if (order == null) { order = ba.order(); } else if (!order.equals(ba.order())) { throw new IllegalArgumentException("Cannot add byte array with different byte order: " + ba.order()); } } /** * @inheritDoc */ public ByteOrder order() { if (order == null) { throw new IllegalStateException("Byte order not yet set."); } return order; } /** * @inheritDoc */ public void order(ByteOrder order) { if (order == null || !order.equals(this.order)) { this.order = order; if (!bas.isEmpty()) { for (Node node = bas.getFirst(); node.hasNextNode(); node = node.getNextNode()) { node.getByteArray().order(order); } } } } /** * @inheritDoc */ public short getShort(int index) { return cursor(index).getShort(); } /** * @inheritDoc */ public void putShort(int index, short s) { cursor(index).putShort(s); } /** * @inheritDoc */ public int getInt(int index) { return cursor(index).getInt(); } /** * @inheritDoc */ public void putInt(int index, int i) { cursor(index).putInt(i); } /** * @inheritDoc */ public long getLong(int index) { return cursor(index).getLong(); } /** * @inheritDoc */ public void putLong(int index, long l) { cursor(index).putLong(l); } /** * @inheritDoc */ public float getFloat(int index) { return cursor(index).getFloat(); } /** * @inheritDoc */ public void putFloat(int index, float f) { cursor(index).putFloat(f); } /** * @inheritDoc */ public double getDouble(int index) { return cursor(index).getDouble(); } /** * @inheritDoc */ public void putDouble(int index, double d) { cursor(index).putDouble(d); } /** * @inheritDoc */ public char getChar(int index) { return cursor(index).getChar(); } /** * @inheritDoc */ public void putChar(int index, char c) { cursor(index).putChar(c); } private class CursorImpl implements Cursor { private int index; private final CursorListener listener; private Node componentNode; // Index of start of current component. private int componentIndex; // Cursor within current component. private ByteArray.Cursor componentCursor; public CursorImpl() { this(0, null); } public CursorImpl(int index) { this(index, null); } public CursorImpl(CursorListener listener) { this(0, listener); } public CursorImpl(int index, CursorListener listener) { this.index = index; this.listener = listener; } /** * @inheritDoc */ public int getIndex() { return index; } /** * @inheritDoc */ public void setIndex(int index) { checkBounds(index, 0); this.index = index; } /** * @inheritDoc */ public void skip(int length) { setIndex(index + length); } /** * @inheritDoc */ public ByteArray slice(int length) { CompositeByteArray slice = new CompositeByteArray(byteArrayFactory); int remaining = length; while (remaining > 0) { prepareForAccess(remaining); int componentSliceSize = Math.min(remaining, componentCursor.getRemaining()); ByteArray componentSlice = componentCursor.slice(componentSliceSize); slice.addLast(componentSlice); index += componentSliceSize; remaining -= componentSliceSize; } return slice; } /** * @inheritDoc */ public ByteOrder order() { return CompositeByteArray.this.order(); } private void prepareForAccess(int accessSize) { // Handle removed node. Do this first so we can remove the reference // even if bounds checking fails. if (componentNode != null && componentNode.isRemoved()) { componentNode = null; componentCursor = null; } // Bounds checks checkBounds(index, accessSize); // Remember the current node so we can later tell whether or not we // need to create a new cursor. Node oldComponentNode = componentNode; // Handle missing node. if (componentNode == null) { int basMidpoint = (last() - first()) / 2 + first(); if (index <= basMidpoint) { // Search from the start. componentNode = bas.getFirst(); componentIndex = first(); if (listener != null) { listener.enteredFirstComponent(componentIndex, componentNode.getByteArray()); } } else { // Search from the end. componentNode = bas.getLast(); componentIndex = last() - componentNode.getByteArray().last(); if (listener != null) { listener.enteredLastComponent(componentIndex, componentNode.getByteArray()); } } } // Go back, if necessary. while (index < componentIndex) { componentNode = componentNode.getPreviousNode(); componentIndex -= componentNode.getByteArray().last(); if (listener != null) { listener.enteredPreviousComponent(componentIndex, componentNode.getByteArray()); } } // Go forward, if necessary. while (index >= componentIndex + componentNode.getByteArray().length()) { componentIndex += componentNode.getByteArray().last(); componentNode = componentNode.getNextNode(); if (listener != null) { listener.enteredNextComponent(componentIndex, componentNode.getByteArray()); } } // Update the cursor. int internalComponentIndex = index - componentIndex; if (componentNode == oldComponentNode) { // Move existing cursor. componentCursor.setIndex(internalComponentIndex); } else { // Create new cursor. componentCursor = componentNode.getByteArray().cursor(internalComponentIndex); } } /** * @inheritDoc */ public int getRemaining() { return last() - index + 1; } /** * @inheritDoc */ public boolean hasRemaining() { return getRemaining() > 0; } /** * @inheritDoc */ public byte get() { prepareForAccess(1); byte b = componentCursor.get(); index += 1; return b; } /** * @inheritDoc */ public void put(byte b) { prepareForAccess(1); componentCursor.put(b); index += 1; } /** * @inheritDoc */ public void get(IoBuffer bb) { while (bb.hasRemaining()) { int remainingBefore = bb.remaining(); prepareForAccess(remainingBefore); componentCursor.get(bb); int remainingAfter = bb.remaining(); // Advance index by actual amount got. int chunkSize = remainingBefore - remainingAfter; index += chunkSize; } } /** * @inheritDoc */ public void put(IoBuffer bb) { while (bb.hasRemaining()) { int remainingBefore = bb.remaining(); prepareForAccess(remainingBefore); componentCursor.put(bb); int remainingAfter = bb.remaining(); // Advance index by actual amount put. int chunkSize = remainingBefore - remainingAfter; index += chunkSize; } } /** * @inheritDoc */ public short getShort() { prepareForAccess(2); if (componentCursor.getRemaining() >= 4) { short s = componentCursor.getShort(); index += 2; return s; } else { byte b0 = get(); byte b1 = get(); if (order.equals(ByteOrder.BIG_ENDIAN)) { return (short) ((b0 << 8) | (b1 << 0)); } else { return (short) ((b1 << 8) | (b0 << 0)); } } } /** * @inheritDoc */ public void putShort(short s) { prepareForAccess(2); if (componentCursor.getRemaining() >= 4) { componentCursor.putShort(s); index += 2; } else { byte b0; byte b1; if (order.equals(ByteOrder.BIG_ENDIAN)) { b0 = (byte) ((s >> 8) & 0xff); b1 = (byte) ((s >> 0) & 0xff); } else { b0 = (byte) ((s >> 0) & 0xff); b1 = (byte) ((s >> 8) & 0xff); } put(b0); put(b1); } } /** * @inheritDoc */ public int getInt() { prepareForAccess(4); if (componentCursor.getRemaining() >= 4) { int i = componentCursor.getInt(); index += 4; return i; } else { byte b0 = get(); byte b1 = get(); byte b2 = get(); byte b3 = get(); if (order.equals(ByteOrder.BIG_ENDIAN)) { return ((b0 << 24) | (b1 << 16) | (b2 << 8) | (b3 << 0)); } else { return ((b3 << 24) | (b2 << 16) | (b1 << 8) | (b0 << 0)); } } } /** * @inheritDoc */ public void putInt(int i) { prepareForAccess(4); if (componentCursor.getRemaining() >= 4) { componentCursor.putInt(i); index += 4; } else { byte b0; byte b1; byte b2; byte b3; if (order.equals(ByteOrder.BIG_ENDIAN)) { b0 = (byte) ((i >> 24) & 0xff); b1 = (byte) ((i >> 16) & 0xff); b2 = (byte) ((i >> 8) & 0xff); b3 = (byte) ((i >> 0) & 0xff); } else { b0 = (byte) ((i >> 0) & 0xff); b1 = (byte) ((i >> 8) & 0xff); b2 = (byte) ((i >> 16) & 0xff); b3 = (byte) ((i >> 24) & 0xff); } put(b0); put(b1); put(b2); put(b3); } } /** * @inheritDoc */ public long getLong() { prepareForAccess(8); if (componentCursor.getRemaining() >= 4) { long l = componentCursor.getLong(); index += 8; return l; } else { byte b0 = get(); byte b1 = get(); byte b2 = get(); byte b3 = get(); byte b4 = get(); byte b5 = get(); byte b6 = get(); byte b7 = get(); if (order.equals(ByteOrder.BIG_ENDIAN)) { return ((b0 & 0xffL) << 56) | ((b1 & 0xffL) << 48) | ((b2 & 0xffL) << 40) | ((b3 & 0xffL) << 32) | ((b4 & 0xffL) << 24) | ((b5 & 0xffL) << 16) | ((b6 & 0xffL) << 8) | ((b7 & 0xffL) << 0); } else { return ((b7 & 0xffL) << 56) | ((b6 & 0xffL) << 48) | ((b5 & 0xffL) << 40) | ((b4 & 0xffL) << 32) | ((b3 & 0xffL) << 24) | ((b2 & 0xffL) << 16) | ((b1 & 0xffL) << 8) | ((b0 & 0xffL) << 0); } } } /** * @inheritDoc */ public void putLong(long l) { //TODO: see if there is some optimizing that can be done here prepareForAccess(8); if (componentCursor.getRemaining() >= 4) { componentCursor.putLong(l); index += 8; } else { byte b0; byte b1; byte b2; byte b3; byte b4; byte b5; byte b6; byte b7; if (order.equals(ByteOrder.BIG_ENDIAN)) { b0 = (byte) ((l >> 56) & 0xff); b1 = (byte) ((l >> 48) & 0xff); b2 = (byte) ((l >> 40) & 0xff); b3 = (byte) ((l >> 32) & 0xff); b4 = (byte) ((l >> 24) & 0xff); b5 = (byte) ((l >> 16) & 0xff); b6 = (byte) ((l >> 8) & 0xff); b7 = (byte) ((l >> 0) & 0xff); } else { b0 = (byte) ((l >> 0) & 0xff); b1 = (byte) ((l >> 8) & 0xff); b2 = (byte) ((l >> 16) & 0xff); b3 = (byte) ((l >> 24) & 0xff); b4 = (byte) ((l >> 32) & 0xff); b5 = (byte) ((l >> 40) & 0xff); b6 = (byte) ((l >> 48) & 0xff); b7 = (byte) ((l >> 56) & 0xff); } put(b0); put(b1); put(b2); put(b3); put(b4); put(b5); put(b6); put(b7); } } /** * @inheritDoc */ public float getFloat() { prepareForAccess(4); if (componentCursor.getRemaining() >= 4) { float f = componentCursor.getFloat(); index += 4; return f; } else { int i = getInt(); return Float.intBitsToFloat(i); } } /** * @inheritDoc */ public void putFloat(float f) { prepareForAccess(4); if (componentCursor.getRemaining() >= 4) { componentCursor.putFloat(f); index += 4; } else { int i = Float.floatToIntBits(f); putInt(i); } } /** * @inheritDoc */ public double getDouble() { prepareForAccess(8); if (componentCursor.getRemaining() >= 4) { double d = componentCursor.getDouble(); index += 8; return d; } else { long l = getLong(); return Double.longBitsToDouble(l); } } /** * @inheritDoc */ public void putDouble(double d) { prepareForAccess(8); if (componentCursor.getRemaining() >= 4) { componentCursor.putDouble(d); index += 8; } else { long l = Double.doubleToLongBits(d); putLong(l); } } /** * @inheritDoc */ public char getChar() { prepareForAccess(2); if (componentCursor.getRemaining() >= 4) { char c = componentCursor.getChar(); index += 2; return c; } else { byte b0 = get(); byte b1 = get(); if (order.equals(ByteOrder.BIG_ENDIAN)) { return (char) ((b0 << 8) | (b1 << 0)); } else { return (char) ((b1 << 8) | (b0 << 0)); } } } /** * @inheritDoc */ public void putChar(char c) { prepareForAccess(2); if (componentCursor.getRemaining() >= 4) { componentCursor.putChar(c); index += 2; } else { byte b0; byte b1; if (order.equals(ByteOrder.BIG_ENDIAN)) { b0 = (byte) ((c >> 8) & 0xff); b1 = (byte) ((c >> 0) & 0xff); } else { b0 = (byte) ((c >> 0) & 0xff); b1 = (byte) ((c >> 8) & 0xff); } put(b0); put(b1); } } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/byteaccess/IoAbsoluteWriter.java0000644000175000017500000000433012032276033032254 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util.byteaccess; import java.nio.ByteOrder; import org.apache.mina.core.buffer.IoBuffer; /** * Provides absolute write access to a sequence of bytes. * * @author Apache MINA Project */ public interface IoAbsoluteWriter { /** * Get the index of the first byte that can be accessed. */ int first(); /** * Gets the index after the last byte that can be accessed. */ int last(); /** * Gets the order of the bytes. */ ByteOrder order(); /** * Puts a byte at the given index. */ void put(int index, byte b); /** * Puts bytes from the IoBuffer at the given index. */ public void put(int index, IoBuffer bb); /** * Puts a short at the given index. */ void putShort(int index, short s); /** * Puts an int at the given index. */ void putInt(int index, int i); /** * Puts a long at the given index. */ void putLong(int index, long l); /** * Puts a float at the given index. */ void putFloat(int index, float f); /** * Puts a double at the given index. */ void putDouble(int index, double d); /** * Puts a char at the given index. */ void putChar(int index, char c); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/IdentityHashSet.java0000644000175000017500000000275712032276034027751 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import java.util.Collection; import java.util.IdentityHashMap; import java.util.Set; /** * An {@link IdentityHashMap}-backed {@link Set}. * * @author Apache MINA Project */ public class IdentityHashSet extends MapBackedSet { private static final long serialVersionUID = 6948202189467167147L; public IdentityHashSet() { super(new IdentityHashMap()); } public IdentityHashSet(int expectedMaxSize) { super(new IdentityHashMap(expectedMaxSize)); } public IdentityHashSet(Collection c) { super(new IdentityHashMap(), c); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/CopyOnWriteMap.java0000644000175000017500000001330712032276034027551 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * A thread-safe version of {@link Map} in which all operations that change the * Map are implemented by making a new copy of the underlying Map. * * While the creation of a new Map can be expensive, this class is designed for * cases in which the primary function is to read data from the Map, not to * modify the Map. Therefore the operations that do not cause a change to this * class happen quickly and concurrently. * * @author Apache MINA Project */ public class CopyOnWriteMap implements Map, Cloneable { private volatile Map internalMap; /** * Creates a new instance of CopyOnWriteMap. * */ public CopyOnWriteMap() { internalMap = new HashMap(); } /** * Creates a new instance of CopyOnWriteMap with the specified initial size * * @param initialCapacity * The initial size of the Map. */ public CopyOnWriteMap(int initialCapacity) { internalMap = new HashMap(initialCapacity); } /** * Creates a new instance of CopyOnWriteMap in which the * initial data being held by this map is contained in * the supplied map. * * @param data * A Map containing the initial contents to be placed into * this class. */ public CopyOnWriteMap(Map data) { internalMap = new HashMap(data); } /** * Adds the provided key and value to this map. * * @see java.util.Map#put(java.lang.Object, java.lang.Object) */ public V put(K key, V value) { synchronized (this) { Map newMap = new HashMap(internalMap); V val = newMap.put(key, value); internalMap = newMap; return val; } } /** * Removed the value and key from this map based on the * provided key. * * @see java.util.Map#remove(java.lang.Object) */ public V remove(Object key) { synchronized (this) { Map newMap = new HashMap(internalMap); V val = newMap.remove(key); internalMap = newMap; return val; } } /** * Inserts all the keys and values contained in the * provided map to this map. * * @see java.util.Map#putAll(java.util.Map) */ public void putAll(Map newData) { synchronized (this) { Map newMap = new HashMap(internalMap); newMap.putAll(newData); internalMap = newMap; } } /** * Removes all entries in this map. * * @see java.util.Map#clear() */ public void clear() { synchronized (this) { internalMap = new HashMap(); } } // ============================================== // ==== Below are methods that do not modify ==== // ==== the internal Maps ==== // ============================================== /** * Returns the number of key/value pairs in this map. * * @see java.util.Map#size() */ public int size() { return internalMap.size(); } /** * Returns true if this map is empty, otherwise false. * * @see java.util.Map#isEmpty() */ public boolean isEmpty() { return internalMap.isEmpty(); } /** * Returns true if this map contains the provided key, otherwise * this method return false. * * @see java.util.Map#containsKey(java.lang.Object) */ public boolean containsKey(Object key) { return internalMap.containsKey(key); } /** * Returns true if this map contains the provided value, otherwise * this method returns false. * * @see java.util.Map#containsValue(java.lang.Object) */ public boolean containsValue(Object value) { return internalMap.containsValue(value); } /** * Returns the value associated with the provided key from this * map. * * @see java.util.Map#get(java.lang.Object) */ public V get(Object key) { return internalMap.get(key); } /** * This method will return a read-only {@link Set}. */ public Set keySet() { return internalMap.keySet(); } /** * This method will return a read-only {@link Collection}. */ public Collection values() { return internalMap.values(); } /** * This method will return a read-only {@link Set}. */ public Set> entrySet() { return internalMap.entrySet(); } @Override public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(); } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/package.html0000644000175000017500000000161412032276034026305 0ustar ebourgebourg Miscellaneous utility classes mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/DefaultExceptionMonitor.java0000644000175000017500000000315712032276034031506 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import org.apache.mina.core.service.IoService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A default {@link ExceptionMonitor} implementation that logs uncaught * exceptions using {@link Logger}. *

* All {@link IoService}s have this implementation as a default exception * monitor. * * @author Apache MINA Project */ public class DefaultExceptionMonitor extends ExceptionMonitor { private final static Logger LOGGER = LoggerFactory.getLogger(DefaultExceptionMonitor.class); /** * {@inheritDoc} */ @Override public void exceptionCaught(Throwable cause) { if (cause instanceof Error) { throw (Error) cause; } LOGGER.warn("Unexpected exception.", cause); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/util/SynchronizedQueue.java0000644000175000017500000000620112032276034030350 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.util; import java.io.Serializable; import java.util.Collection; import java.util.Iterator; import java.util.Queue; /** * A decorator that makes the specified {@link Queue} thread-safe. * Like any other synchronizing wrappers, iteration is not thread-safe. * * @author Apache MINA Project */ public class SynchronizedQueue implements Queue, Serializable { private static final long serialVersionUID = -1439242290701194806L; private final Queue q; public SynchronizedQueue(Queue q) { this.q = q; } public synchronized boolean add(E e) { return q.add(e); } public synchronized E element() { return q.element(); } public synchronized boolean offer(E e) { return q.offer(e); } public synchronized E peek() { return q.peek(); } public synchronized E poll() { return q.poll(); } public synchronized E remove() { return q.remove(); } public synchronized boolean addAll(Collection c) { return q.addAll(c); } public synchronized void clear() { q.clear(); } public synchronized boolean contains(Object o) { return q.contains(o); } public synchronized boolean containsAll(Collection c) { return q.containsAll(c); } public synchronized boolean isEmpty() { return q.isEmpty(); } public synchronized Iterator iterator() { return q.iterator(); } public synchronized boolean remove(Object o) { return q.remove(o); } public synchronized boolean removeAll(Collection c) { return q.removeAll(c); } public synchronized boolean retainAll(Collection c) { return q.retainAll(c); } public synchronized int size() { return q.size(); } public synchronized Object[] toArray() { return q.toArray(); } public synchronized T[] toArray(T[] a) { return q.toArray(a); } @Override public synchronized boolean equals(Object obj) { return q.equals(obj); } @Override public synchronized int hashCode() { return q.hashCode(); } @Override public synchronized String toString() { return q.toString(); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/0000755000175000017500000000000012162575507024345 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/executor/0000755000175000017500000000000012162575507026203 5ustar ebourgebourg././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/executor/UnorderedThreadPoolExecutor.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/executor/UnorderedThreadPoolExec0000644000175000017500000003377612032276026032652 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.executor; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.apache.mina.core.session.IoEvent; /** * A {@link ThreadPoolExecutor} that does not maintain the order of {@link IoEvent}s. * This means more than one event handler methods can be invoked at the same * time with mixed order. For example, let's assume that messageReceived, messageSent, * and sessionClosed events are fired. *

    *
  • All event handler methods can be called simultaneously. * (e.g. messageReceived and messageSent can be invoked at the same time.)
  • *
  • The event order can be mixed up. * (e.g. sessionClosed or messageSent can be invoked before messageReceived * is invoked.)
  • *
* If you need to maintain the order of events per session, please use * {@link OrderedThreadPoolExecutor}. * * @author Apache MINA Project * @org.apache.xbean.XBean */ public class UnorderedThreadPoolExecutor extends ThreadPoolExecutor { private static final Runnable EXIT_SIGNAL = new Runnable() { public void run() { throw new Error("This method shouldn't be called. " + "Please file a bug report."); } }; private final Set workers = new HashSet(); private volatile int corePoolSize; private volatile int maximumPoolSize; private volatile int largestPoolSize; private final AtomicInteger idleWorkers = new AtomicInteger(); private long completedTaskCount; private volatile boolean shutdown; private final IoEventQueueHandler queueHandler; public UnorderedThreadPoolExecutor() { this(16); } public UnorderedThreadPoolExecutor(int maximumPoolSize) { this(0, maximumPoolSize); } public UnorderedThreadPoolExecutor(int corePoolSize, int maximumPoolSize) { this(corePoolSize, maximumPoolSize, 30, TimeUnit.SECONDS); } public UnorderedThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, Executors.defaultThreadFactory()); } public UnorderedThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, IoEventQueueHandler queueHandler) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, Executors.defaultThreadFactory(), queueHandler); } public UnorderedThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, ThreadFactory threadFactory) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, threadFactory, null); } public UnorderedThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, ThreadFactory threadFactory, IoEventQueueHandler queueHandler) { super(0, 1, keepAliveTime, unit, new LinkedBlockingQueue(), threadFactory, new AbortPolicy()); if (corePoolSize < 0) { throw new IllegalArgumentException("corePoolSize: " + corePoolSize); } if (maximumPoolSize == 0 || maximumPoolSize < corePoolSize) { throw new IllegalArgumentException("maximumPoolSize: " + maximumPoolSize); } if (queueHandler == null) { queueHandler = IoEventQueueHandler.NOOP; } this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.queueHandler = queueHandler; } public IoEventQueueHandler getQueueHandler() { return queueHandler; } @Override public void setRejectedExecutionHandler(RejectedExecutionHandler handler) { // Ignore the request. It must always be AbortPolicy. } private void addWorker() { synchronized (workers) { if (workers.size() >= maximumPoolSize) { return; } Worker worker = new Worker(); Thread thread = getThreadFactory().newThread(worker); idleWorkers.incrementAndGet(); thread.start(); workers.add(worker); if (workers.size() > largestPoolSize) { largestPoolSize = workers.size(); } } } private void addWorkerIfNecessary() { if (idleWorkers.get() == 0) { synchronized (workers) { if (workers.isEmpty() || idleWorkers.get() == 0) { addWorker(); } } } } private void removeWorker() { synchronized (workers) { if (workers.size() <= corePoolSize) { return; } getQueue().offer(EXIT_SIGNAL); } } @Override public int getMaximumPoolSize() { return maximumPoolSize; } @Override public void setMaximumPoolSize(int maximumPoolSize) { if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize) { throw new IllegalArgumentException("maximumPoolSize: " + maximumPoolSize); } synchronized (workers) { this.maximumPoolSize = maximumPoolSize; int difference = workers.size() - maximumPoolSize; while (difference > 0) { removeWorker(); --difference; } } } @Override public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { long deadline = System.currentTimeMillis() + unit.toMillis(timeout); synchronized (workers) { while (!isTerminated()) { long waitTime = deadline - System.currentTimeMillis(); if (waitTime <= 0) { break; } workers.wait(waitTime); } } return isTerminated(); } @Override public boolean isShutdown() { return shutdown; } @Override public boolean isTerminated() { if (!shutdown) { return false; } synchronized (workers) { return workers.isEmpty(); } } @Override public void shutdown() { if (shutdown) { return; } shutdown = true; synchronized (workers) { for (int i = workers.size(); i > 0; i--) { getQueue().offer(EXIT_SIGNAL); } } } @Override public List shutdownNow() { shutdown(); List answer = new ArrayList(); Runnable task; while ((task = getQueue().poll()) != null) { if (task == EXIT_SIGNAL) { getQueue().offer(EXIT_SIGNAL); Thread.yield(); // Let others take the signal. continue; } getQueueHandler().polled(this, (IoEvent) task); answer.add(task); } return answer; } @Override public void execute(Runnable task) { if (shutdown) { rejectTask(task); } checkTaskType(task); IoEvent e = (IoEvent) task; boolean offeredEvent = queueHandler.accept(this, e); if (offeredEvent) { getQueue().offer(e); } addWorkerIfNecessary(); if (offeredEvent) { queueHandler.offered(this, e); } } private void rejectTask(Runnable task) { getRejectedExecutionHandler().rejectedExecution(task, this); } private void checkTaskType(Runnable task) { if (!(task instanceof IoEvent)) { throw new IllegalArgumentException("task must be an IoEvent or its subclass."); } } @Override public int getActiveCount() { synchronized (workers) { return workers.size() - idleWorkers.get(); } } @Override public long getCompletedTaskCount() { synchronized (workers) { long answer = completedTaskCount; for (Worker w : workers) { answer += w.completedTaskCount; } return answer; } } @Override public int getLargestPoolSize() { return largestPoolSize; } @Override public int getPoolSize() { synchronized (workers) { return workers.size(); } } @Override public long getTaskCount() { return getCompletedTaskCount(); } @Override public boolean isTerminating() { synchronized (workers) { return isShutdown() && !isTerminated(); } } @Override public int prestartAllCoreThreads() { int answer = 0; synchronized (workers) { for (int i = corePoolSize - workers.size(); i > 0; i--) { addWorker(); answer++; } } return answer; } @Override public boolean prestartCoreThread() { synchronized (workers) { if (workers.size() < corePoolSize) { addWorker(); return true; } return false; } } @Override public void purge() { // Nothing to purge in this implementation. } @Override public boolean remove(Runnable task) { boolean removed = super.remove(task); if (removed) { getQueueHandler().polled(this, (IoEvent) task); } return removed; } @Override public int getCorePoolSize() { return corePoolSize; } @Override public void setCorePoolSize(int corePoolSize) { if (corePoolSize < 0) { throw new IllegalArgumentException("corePoolSize: " + corePoolSize); } if (corePoolSize > maximumPoolSize) { throw new IllegalArgumentException("corePoolSize exceeds maximumPoolSize"); } synchronized (workers) { if (this.corePoolSize > corePoolSize) { for (int i = this.corePoolSize - corePoolSize; i > 0; i--) { removeWorker(); } } this.corePoolSize = corePoolSize; } } private class Worker implements Runnable { private volatile long completedTaskCount; private Thread thread; public void run() { thread = Thread.currentThread(); try { for (;;) { Runnable task = fetchTask(); idleWorkers.decrementAndGet(); if (task == null) { synchronized (workers) { if (workers.size() > corePoolSize) { // Remove now to prevent duplicate exit. workers.remove(this); break; } } } if (task == EXIT_SIGNAL) { break; } try { if (task != null) { queueHandler.polled(UnorderedThreadPoolExecutor.this, (IoEvent) task); runTask(task); } } finally { idleWorkers.incrementAndGet(); } } } finally { synchronized (workers) { workers.remove(this); UnorderedThreadPoolExecutor.this.completedTaskCount += completedTaskCount; workers.notifyAll(); } } } private Runnable fetchTask() { Runnable task = null; long currentTime = System.currentTimeMillis(); long deadline = currentTime + getKeepAliveTime(TimeUnit.MILLISECONDS); for (;;) { try { long waitTime = deadline - currentTime; if (waitTime <= 0) { break; } try { task = getQueue().poll(waitTime, TimeUnit.MILLISECONDS); break; } finally { if (task == null) { currentTime = System.currentTimeMillis(); } } } catch (InterruptedException e) { // Ignore. continue; } } return task; } private void runTask(Runnable task) { beforeExecute(thread, task); boolean ran = false; try { task.run(); ran = true; afterExecute(task, null); completedTaskCount++; } catch (RuntimeException e) { if (!ran) { afterExecute(task, e); } throw e; } } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/executor/ExecutorFilter.java0000644000175000017500000006060212032276026032004 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.executor; import java.util.EnumSet; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.filterchain.IoFilterEvent; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoEventType; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; /** * A filter that forwards I/O events to {@link Executor} to enforce a certain * thread model while allowing the events per session to be processed * simultaneously. You can apply various thread model by inserting this filter * to a {@link IoFilterChain}. * *

Life Cycle Management

* * Please note that this filter doesn't manage the life cycle of the {@link Executor}. * If you created this filter using {@link #ExecutorFilter(Executor)} or similar * constructor that accepts an {@link Executor} that you've instantiated, you have * full control and responsibility of managing its life cycle (e.g. calling * {@link ExecutorService#shutdown()}. *

* If you created this filter using convenience constructors like * {@link #ExecutorFilter(int)}, then you can shut down the executor by calling * {@link #destroy()} explicitly. * *

Event Ordering

* * All convenience constructors of this filter creates a new * {@link OrderedThreadPoolExecutor} instance. Therefore, the order of event is * maintained like the following: *
    *
  • All event handler methods are called exclusively. * (e.g. messageReceived and messageSent can't be invoked at the same time.)
  • *
  • The event order is never mixed up. * (e.g. messageReceived is always invoked before sessionClosed or messageSent.)
  • *
* However, if you specified other {@link Executor} instance in the constructor, * the order of events are not maintained at all. This means more than one event * handler methods can be invoked at the same time with mixed order. For example, * let's assume that messageReceived, messageSent, and sessionClosed events are * fired. *
    *
  • All event handler methods can be called simultaneously. * (e.g. messageReceived and messageSent can be invoked at the same time.)
  • *
  • The event order can be mixed up. * (e.g. sessionClosed or messageSent can be invoked before messageReceived * is invoked.)
  • *
* If you need to maintain the order of events per session, please specify an * {@link OrderedThreadPoolExecutor} instance or use the convenience constructors. * *

Selective Filtering

* * By default, all event types but sessionCreated, filterWrite, * filterClose and filterSetTrafficMask are submitted to the * underlying executor, which is most common setting. *

* If you want to submit only a certain set of event types, you can specify them * in the constructor. For example, you could configure a thread pool for * write operation for the maximum performance: *


 * IoService service = ...;
 * DefaultIoFilterChainBuilder chain = service.getFilterChain();
 * 
 * chain.addLast("codec", new ProtocolCodecFilter(...));
 * // Use one thread pool for most events.
 * chain.addLast("executor1", new ExecutorFilter());
 * // and another dedicated thread pool for 'filterWrite' events.
 * chain.addLast("executor2", new ExecutorFilter(IoEventType.WRITE));
 * 
* *

Preventing {@link OutOfMemoryError}

* * Please refer to {@link IoEventQueueThrottle}, which is specified as * a parameter of the convenience constructors. * * @author Apache MINA Project * * @see OrderedThreadPoolExecutor * @see UnorderedThreadPoolExecutor * @org.apache.xbean.XBean */ public class ExecutorFilter extends IoFilterAdapter { /** The list of handled events */ private EnumSet eventTypes; /** The associated executor */ private Executor executor; /** A flag set if the executor can be managed */ private boolean manageableExecutor; /** The default pool size */ private static final int DEFAULT_MAX_POOL_SIZE = 16; /** The number of thread to create at startup */ private static final int BASE_THREAD_NUMBER = 0; /** The default KeepAlive time, in seconds */ private static final long DEFAULT_KEEPALIVE_TIME = 30; /** * A set of flags used to tell if the Executor has been created * in the constructor or passed as an argument. In the second case, * the executor state can be managed. **/ private static final boolean MANAGEABLE_EXECUTOR = true; private static final boolean NOT_MANAGEABLE_EXECUTOR = false; /** A list of default EventTypes to be handled by the executor */ private static IoEventType[] DEFAULT_EVENT_SET = new IoEventType[] { IoEventType.EXCEPTION_CAUGHT, IoEventType.MESSAGE_RECEIVED, IoEventType.MESSAGE_SENT, IoEventType.SESSION_CLOSED, IoEventType.SESSION_IDLE, IoEventType.SESSION_OPENED }; /** * (Convenience constructor) Creates a new instance with a new * {@link OrderedThreadPoolExecutor}, no thread in the pool, and a * maximum of 16 threads in the pool. All the event will be handled * by this default executor. */ public ExecutorFilter() { // Create a new default Executor Executor executor = createDefaultExecutor(BASE_THREAD_NUMBER, DEFAULT_MAX_POOL_SIZE, DEFAULT_KEEPALIVE_TIME, TimeUnit.SECONDS, Executors.defaultThreadFactory(), null); // Initialize the filter init(executor, MANAGEABLE_EXECUTOR); } /** * (Convenience constructor) Creates a new instance with a new * {@link OrderedThreadPoolExecutor}, no thread in the pool, but * a maximum of threads in the pool is given. All the event will be handled * by this default executor. * * @param maximumPoolSize The maximum pool size */ public ExecutorFilter(int maximumPoolSize) { // Create a new default Executor Executor executor = createDefaultExecutor(BASE_THREAD_NUMBER, maximumPoolSize, DEFAULT_KEEPALIVE_TIME, TimeUnit.SECONDS, Executors.defaultThreadFactory(), null); // Initialize the filter init(executor, MANAGEABLE_EXECUTOR); } /** * (Convenience constructor) Creates a new instance with a new * {@link OrderedThreadPoolExecutor}, a number of thread to start with, a * maximum of threads the pool can contain. All the event will be handled * by this default executor. * * @param corePoolSize The initial pool size * @param maximumPoolSize The maximum pool size */ public ExecutorFilter(int corePoolSize, int maximumPoolSize) { // Create a new default Executor Executor executor = createDefaultExecutor(corePoolSize, maximumPoolSize, DEFAULT_KEEPALIVE_TIME, TimeUnit.SECONDS, Executors.defaultThreadFactory(), null); // Initialize the filter init(executor, MANAGEABLE_EXECUTOR); } /** * (Convenience constructor) Creates a new instance with a new * {@link OrderedThreadPoolExecutor}. * * @param corePoolSize The initial pool size * @param maximumPoolSize The maximum pool size * @param keepAliveTime Default duration for a thread * @param unit Time unit used for the keepAlive value */ public ExecutorFilter(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit) { // Create a new default Executor Executor executor = createDefaultExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, Executors.defaultThreadFactory(), null); // Initialize the filter init(executor, MANAGEABLE_EXECUTOR); } /** * (Convenience constructor) Creates a new instance with a new * {@link OrderedThreadPoolExecutor}. * * @param corePoolSize The initial pool size * @param maximumPoolSize The maximum pool size * @param keepAliveTime Default duration for a thread * @param unit Time unit used for the keepAlive value * @param queueHandler The queue used to store events */ public ExecutorFilter(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, IoEventQueueHandler queueHandler) { // Create a new default Executor Executor executor = createDefaultExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, Executors.defaultThreadFactory(), queueHandler); // Initialize the filter init(executor, MANAGEABLE_EXECUTOR); } /** * (Convenience constructor) Creates a new instance with a new * {@link OrderedThreadPoolExecutor}. * * @param corePoolSize The initial pool size * @param maximumPoolSize The maximum pool size * @param keepAliveTime Default duration for a thread * @param unit Time unit used for the keepAlive value * @param threadFactory The factory used to create threads */ public ExecutorFilter(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, ThreadFactory threadFactory) { // Create a new default Executor Executor executor = createDefaultExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, threadFactory, null); // Initialize the filter init(executor, MANAGEABLE_EXECUTOR); } /** * (Convenience constructor) Creates a new instance with a new * {@link OrderedThreadPoolExecutor}. * * @param corePoolSize The initial pool size * @param maximumPoolSize The maximum pool size * @param keepAliveTime Default duration for a thread * @param unit Time unit used for the keepAlive value * @param threadFactory The factory used to create threads * @param queueHandler The queue used to store events */ public ExecutorFilter(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, ThreadFactory threadFactory, IoEventQueueHandler queueHandler) { // Create a new default Executor Executor executor = new OrderedThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, threadFactory, queueHandler); // Initialize the filter init(executor, MANAGEABLE_EXECUTOR); } /** * (Convenience constructor) Creates a new instance with a new * {@link OrderedThreadPoolExecutor}. * * @param eventTypes The event for which the executor will be used */ public ExecutorFilter(IoEventType... eventTypes) { // Create a new default Executor Executor executor = createDefaultExecutor(BASE_THREAD_NUMBER, DEFAULT_MAX_POOL_SIZE, DEFAULT_KEEPALIVE_TIME, TimeUnit.SECONDS, Executors.defaultThreadFactory(), null); // Initialize the filter init(executor, MANAGEABLE_EXECUTOR, eventTypes); } /** * (Convenience constructor) Creates a new instance with a new * {@link OrderedThreadPoolExecutor}. * * @param maximumPoolSize The maximum pool size * @param eventTypes The event for which the executor will be used */ public ExecutorFilter(int maximumPoolSize, IoEventType... eventTypes) { // Create a new default Executor Executor executor = createDefaultExecutor(BASE_THREAD_NUMBER, maximumPoolSize, DEFAULT_KEEPALIVE_TIME, TimeUnit.SECONDS, Executors.defaultThreadFactory(), null); // Initialize the filter init(executor, MANAGEABLE_EXECUTOR, eventTypes); } /** * (Convenience constructor) Creates a new instance with a new * {@link OrderedThreadPoolExecutor}. * * @param corePoolSize The initial pool size * @param maximumPoolSize The maximum pool size * @param eventTypes The event for which the executor will be used */ public ExecutorFilter(int corePoolSize, int maximumPoolSize, IoEventType... eventTypes) { // Create a new default Executor Executor executor = createDefaultExecutor(corePoolSize, maximumPoolSize, DEFAULT_KEEPALIVE_TIME, TimeUnit.SECONDS, Executors.defaultThreadFactory(), null); // Initialize the filter init(executor, MANAGEABLE_EXECUTOR, eventTypes); } /** * (Convenience constructor) Creates a new instance with a new * {@link OrderedThreadPoolExecutor}. * * @param corePoolSize The initial pool size * @param maximumPoolSize The maximum pool size * @param keepAliveTime Default duration for a thread * @param unit Time unit used for the keepAlive value * @param eventTypes The event for which the executor will be used */ public ExecutorFilter(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, IoEventType... eventTypes) { // Create a new default Executor Executor executor = createDefaultExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, Executors.defaultThreadFactory(), null); // Initialize the filter init(executor, MANAGEABLE_EXECUTOR, eventTypes); } /** * (Convenience constructor) Creates a new instance with a new * {@link OrderedThreadPoolExecutor}. * * @param corePoolSize The initial pool size * @param maximumPoolSize The maximum pool size * @param keepAliveTime Default duration for a thread * @param unit Time unit used for the keepAlive value * @param queueHandler The queue used to store events * @param eventTypes The event for which the executor will be used */ public ExecutorFilter(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, IoEventQueueHandler queueHandler, IoEventType... eventTypes) { // Create a new default Executor Executor executor = createDefaultExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, Executors.defaultThreadFactory(), queueHandler); // Initialize the filter init(executor, MANAGEABLE_EXECUTOR, eventTypes); } /** * (Convenience constructor) Creates a new instance with a new * {@link OrderedThreadPoolExecutor}. * * @param corePoolSize The initial pool size * @param maximumPoolSize The maximum pool size * @param keepAliveTime Default duration for a thread * @param unit Time unit used for the keepAlive value * @param threadFactory The factory used to create threads * @param eventTypes The event for which the executor will be used */ public ExecutorFilter(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, ThreadFactory threadFactory, IoEventType... eventTypes) { // Create a new default Executor Executor executor = createDefaultExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, threadFactory, null); // Initialize the filter init(executor, MANAGEABLE_EXECUTOR, eventTypes); } /** * (Convenience constructor) Creates a new instance with a new * {@link OrderedThreadPoolExecutor}. * * @param corePoolSize The initial pool size * @param maximumPoolSize The maximum pool size * @param keepAliveTime Default duration for a thread * @param unit Time unit used for the keepAlive value * @param threadFactory The factory used to create threads * @param queueHandler The queue used to store events * @param eventTypes The event for which the executor will be used */ public ExecutorFilter(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, ThreadFactory threadFactory, IoEventQueueHandler queueHandler, IoEventType... eventTypes) { // Create a new default Executor Executor executor = new OrderedThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, threadFactory, queueHandler); // Initialize the filter init(executor, MANAGEABLE_EXECUTOR, eventTypes); } /** * Creates a new instance with the specified {@link Executor}. * * @param executor the user's managed Executor to use in this filter */ public ExecutorFilter(Executor executor) { // Initialize the filter init(executor, NOT_MANAGEABLE_EXECUTOR); } /** * Creates a new instance with the specified {@link Executor}. * * @param executor the user's managed Executor to use in this filter * @param eventTypes The event for which the executor will be used */ public ExecutorFilter(Executor executor, IoEventType... eventTypes) { // Initialize the filter init(executor, NOT_MANAGEABLE_EXECUTOR, eventTypes); } /** * Create an OrderedThreadPool executor. * * @param corePoolSize The initial pool sizePoolSize * @param maximumPoolSize The maximum pool size * @param keepAliveTime Default duration for a thread * @param unit Time unit used for the keepAlive value * @param threadFactory The factory used to create threads * @param queueHandler The queue used to store events * @return An instance of the created Executor */ private Executor createDefaultExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, ThreadFactory threadFactory, IoEventQueueHandler queueHandler) { // Create a new Executor Executor executor = new OrderedThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, threadFactory, queueHandler); return executor; } /** * Create an EnumSet from an array of EventTypes, and set the associated * eventTypes field. * * @param eventTypes The array of handled events */ private void initEventTypes(IoEventType... eventTypes) { if ((eventTypes == null) || (eventTypes.length == 0)) { eventTypes = DEFAULT_EVENT_SET; } // Copy the list of handled events in the event set this.eventTypes = EnumSet.of(eventTypes[0], eventTypes); // Check that we don't have the SESSION_CREATED event in the set if (this.eventTypes.contains(IoEventType.SESSION_CREATED)) { this.eventTypes = null; throw new IllegalArgumentException(IoEventType.SESSION_CREATED + " is not allowed."); } } /** * Creates a new instance of ExecutorFilter. This private constructor is called by all * the public constructor. * * @param executor The underlying {@link Executor} in charge of managing the Thread pool. * @param manageableExecutor Tells if the Executor's Life Cycle can be managed or not * @param eventTypes The lit of event which are handled by the executor * @param */ private void init(Executor executor, boolean manageableExecutor, IoEventType... eventTypes) { if (executor == null) { throw new IllegalArgumentException("executor"); } initEventTypes(eventTypes); this.executor = executor; this.manageableExecutor = manageableExecutor; } /** * Shuts down the underlying executor if this filter hase been created via * a convenience constructor. */ @Override public void destroy() { if (manageableExecutor) { ((ExecutorService) executor).shutdown(); } } /** * Returns the underlying {@link Executor} instance this filter uses. * * @return The underlying {@link Executor} */ public final Executor getExecutor() { return executor; } /** * Fires the specified event through the underlying executor. * * @param event The filtered event */ protected void fireEvent(IoFilterEvent event) { executor.execute(event); } /** * {@inheritDoc} */ @Override public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { if (parent.contains(this)) { throw new IllegalArgumentException( "You can't add the same filter instance more than once. Create another instance and add it."); } } /** * {@inheritDoc} */ @Override public final void sessionOpened(NextFilter nextFilter, IoSession session) { if (eventTypes.contains(IoEventType.SESSION_OPENED)) { IoFilterEvent event = new IoFilterEvent(nextFilter, IoEventType.SESSION_OPENED, session, null); fireEvent(event); } else { nextFilter.sessionOpened(session); } } /** * {@inheritDoc} */ @Override public final void sessionClosed(NextFilter nextFilter, IoSession session) { if (eventTypes.contains(IoEventType.SESSION_CLOSED)) { IoFilterEvent event = new IoFilterEvent(nextFilter, IoEventType.SESSION_CLOSED, session, null); fireEvent(event); } else { nextFilter.sessionClosed(session); } } /** * {@inheritDoc} */ @Override public final void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) { if (eventTypes.contains(IoEventType.SESSION_IDLE)) { IoFilterEvent event = new IoFilterEvent(nextFilter, IoEventType.SESSION_IDLE, session, status); fireEvent(event); } else { nextFilter.sessionIdle(session, status); } } /** * {@inheritDoc} */ @Override public final void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) { if (eventTypes.contains(IoEventType.EXCEPTION_CAUGHT)) { IoFilterEvent event = new IoFilterEvent(nextFilter, IoEventType.EXCEPTION_CAUGHT, session, cause); fireEvent(event); } else { nextFilter.exceptionCaught(session, cause); } } /** * {@inheritDoc} */ @Override public final void messageReceived(NextFilter nextFilter, IoSession session, Object message) { if (eventTypes.contains(IoEventType.MESSAGE_RECEIVED)) { IoFilterEvent event = new IoFilterEvent(nextFilter, IoEventType.MESSAGE_RECEIVED, session, message); fireEvent(event); } else { nextFilter.messageReceived(session, message); } } /** * {@inheritDoc} */ @Override public final void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) { if (eventTypes.contains(IoEventType.MESSAGE_SENT)) { IoFilterEvent event = new IoFilterEvent(nextFilter, IoEventType.MESSAGE_SENT, session, writeRequest); fireEvent(event); } else { nextFilter.messageSent(session, writeRequest); } } /** * {@inheritDoc} */ @Override public final void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) { if (eventTypes.contains(IoEventType.WRITE)) { IoFilterEvent event = new IoFilterEvent(nextFilter, IoEventType.WRITE, session, writeRequest); fireEvent(event); } else { nextFilter.filterWrite(session, writeRequest); } } /** * {@inheritDoc} */ @Override public final void filterClose(NextFilter nextFilter, IoSession session) throws Exception { if (eventTypes.contains(IoEventType.CLOSE)) { IoFilterEvent event = new IoFilterEvent(nextFilter, IoEventType.CLOSE, session, null); fireEvent(event); } else { nextFilter.filterClose(session); } } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/executor/IoEventSizeEstimator.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/executor/IoEventSizeEstimator.ja0000644000175000017500000000250612032276026032604 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.executor; import org.apache.mina.core.session.IoEvent; /** * Estimates the amount of memory that the specified {@link IoEvent} occupies * in the current JVM. * * @author Apache MINA Project */ public interface IoEventSizeEstimator { /** * Estimate the IoEvent size in numberof bytes * @param event The event we want to estimate the size of * @return The estimated size of this event */ int estimateSize(IoEvent event); } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/executor/IoEventQueueHandler.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/executor/IoEventQueueHandler.jav0000644000175000017500000000431412032276026032551 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.executor; import java.util.EventListener; import org.apache.mina.core.session.IoEvent; /** * Listens and filters all event queue operations occurring in * {@link OrderedThreadPoolExecutor} and {@link UnorderedThreadPoolExecutor}. * * @author Apache MINA Project */ public interface IoEventQueueHandler extends EventListener { /** * A dummy handler which always accepts event doing nothing particular. */ static IoEventQueueHandler NOOP = new IoEventQueueHandler() { public boolean accept(Object source, IoEvent event) { return true; } public void offered(Object source, IoEvent event) { // NOOP } public void polled(Object source, IoEvent event) { // NOOP } }; /** * Returns true if and only if the specified event is * allowed to be offered to the event queue. The event is dropped * if false is returned. */ boolean accept(Object source, IoEvent event); /** * Invoked after the specified event has been offered to the * event queue. */ void offered(Object source, IoEvent event); /** * Invoked after the specified event has been polled from the * event queue. */ void polled(Object source, IoEvent event); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/executor/WriteRequestFilter.java0000644000175000017500000001061312032276026032646 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.executor; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.session.IoEvent; import org.apache.mina.core.session.IoEventType; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; /** * Attaches an {@link IoEventQueueHandler} to an {@link IoSession}'s * {@link WriteRequest} queue to provide accurate write queue status tracking. *

* The biggest difference from {@link OrderedThreadPoolExecutor} and * {@link UnorderedThreadPoolExecutor} is that {@link IoEventQueueHandler#polled(Object, IoEvent)} * is invoked when the write operation is completed by an {@link IoProcessor}, * consequently providing the accurate tracking of the write request queue * status to the {@link IoEventQueueHandler}. *

* Most common usage of this filter could be detecting an {@link IoSession} * which writes too fast which will cause {@link OutOfMemoryError} soon: *

 *     session.getFilterChain().addLast(
 *             "writeThrottle",
 *             new WriteRequestFilter(new IoEventQueueThrottle()));
 * 
* *

Known issues

* * You can run into a dead lock if you run this filter with the blocking * {@link IoEventQueueHandler} implementation such as {@link IoEventQueueThrottle} * in the {@link IoProcessor} thread. It's because an {@link IoProcessor} * thread is what processes the {@link WriteRequest}s and notifies related * {@link WriteFuture}s; the {@link IoEventQueueHandler} implementation that * waits for the size of the write request queue to decrease will never wake * up. To use such an handler, you have to insert an {@link ExecutorFilter} * before this filter or call {@link IoSession#write(Object)} method always * from a different thread. * * @author Apache MINA Project */ public class WriteRequestFilter extends IoFilterAdapter { private final IoEventQueueHandler queueHandler; /** * Creates a new instance with a new default {@link IoEventQueueThrottle}. */ public WriteRequestFilter() { this(new IoEventQueueThrottle()); } /** * Creates a new instance with the specified {@link IoEventQueueHandler}. */ public WriteRequestFilter(IoEventQueueHandler queueHandler) { if (queueHandler == null) { throw new IllegalArgumentException("queueHandler"); } this.queueHandler = queueHandler; } /** * Returns the {@link IoEventQueueHandler} which is attached to this * filter. */ public IoEventQueueHandler getQueueHandler() { return queueHandler; } @Override public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { final IoEvent e = new IoEvent(IoEventType.WRITE, session, writeRequest); if (queueHandler.accept(this, e)) { nextFilter.filterWrite(session, writeRequest); WriteFuture writeFuture = writeRequest.getFuture(); if (writeFuture == null) { return; } // We can track the write request only when it has a future. queueHandler.offered(this, e); writeFuture.addListener(new IoFutureListener() { public void operationComplete(WriteFuture future) { queueHandler.polled(WriteRequestFilter.this, e); } }); } } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/executor/DefaultIoEventSizeEstimator.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/executor/DefaultIoEventSizeEstim0000644000175000017500000001167412032276026032640 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.executor; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoEvent; import org.apache.mina.core.write.WriteRequest; /** * A default {@link IoEventSizeEstimator} implementation. *

* Martin's Java Notes * was used for estimation. For unknown types, it inspects declaring fields of the * class of the specified event and the parameter of the event. The size of unknown * declaring fields are approximated to the specified averageSizePerField * (default: 64). *

* All the estimated sizes of classes are cached for performance improvement. * * @author Apache MINA Project */ public class DefaultIoEventSizeEstimator implements IoEventSizeEstimator { /** A map containing the estimated size of each Java objects we know for */ private final ConcurrentMap, Integer> class2size = new ConcurrentHashMap, Integer>(); /** * Create a new instance of this class, injecting the known size of * basic java types. */ public DefaultIoEventSizeEstimator() { class2size.put(boolean.class, 4); // Probably an integer. class2size.put(byte.class, 1); class2size.put(char.class, 2); class2size.put(int.class, 4); class2size.put(short.class, 2); class2size.put(long.class, 8); class2size.put(float.class, 4); class2size.put(double.class, 8); class2size.put(void.class, 0); } /** * {@inheritDoc} */ public int estimateSize(IoEvent event) { return estimateSize((Object) event) + estimateSize(event.getParameter()); } /** * Estimate the size of an Objecr in number of bytes * @param message The object to estimate * @return The estimated size of the object */ public int estimateSize(Object message) { if (message == null) { return 8; } int answer = 8 + estimateSize(message.getClass(), null); if (message instanceof IoBuffer) { answer += ((IoBuffer) message).remaining(); } else if (message instanceof WriteRequest) { answer += estimateSize(((WriteRequest) message).getMessage()); } else if (message instanceof CharSequence) { answer += ((CharSequence) message).length() << 1; } else if (message instanceof Iterable) { for (Object m : (Iterable) message) { answer += estimateSize(m); } } return align(answer); } private int estimateSize(Class clazz, Set> visitedClasses) { Integer objectSize = class2size.get(clazz); if (objectSize != null) { return objectSize; } if (visitedClasses != null) { if (visitedClasses.contains(clazz)) { return 0; } } else { visitedClasses = new HashSet>(); } visitedClasses.add(clazz); int answer = 8; // Basic overhead. for (Class c = clazz; c != null; c = c.getSuperclass()) { Field[] fields = c.getDeclaredFields(); for (Field f : fields) { if ((f.getModifiers() & Modifier.STATIC) != 0) { // Ignore static fields. continue; } answer += estimateSize(f.getType(), visitedClasses); } } visitedClasses.remove(clazz); // Some alignment. answer = align(answer); // Put the final answer. Integer tmpAnswer = class2size.putIfAbsent(clazz, answer); if (tmpAnswer != null) { answer = tmpAnswer; } return answer; } private static int align(int size) { if (size % 8 != 0) { size /= 8; size++; size *= 8; } return size; } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/executor/OrderedThreadPoolExecutor.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/executor/OrderedThreadPoolExecut0000644000175000017500000005667212032276026032660 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.executor; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Queue; import java.util.Set; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.DummySession; import org.apache.mina.core.session.IoEvent; import org.apache.mina.core.session.IoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A {@link ThreadPoolExecutor} that maintains the order of {@link IoEvent}s. *

* If you don't need to maintain the order of events per session, please use * {@link UnorderedThreadPoolExecutor}. * @author Apache MINA Project * @org.apache.xbean.XBean */ public class OrderedThreadPoolExecutor extends ThreadPoolExecutor { /** A logger for this class (commented as it breaks MDCFlter tests) */ static Logger LOGGER = LoggerFactory.getLogger(OrderedThreadPoolExecutor.class); /** A default value for the initial pool size */ private static final int DEFAULT_INITIAL_THREAD_POOL_SIZE = 0; /** A default value for the maximum pool size */ private static final int DEFAULT_MAX_THREAD_POOL = 16; /** A default value for the KeepAlive delay */ private static final int DEFAULT_KEEP_ALIVE = 30; private static final IoSession EXIT_SIGNAL = new DummySession(); /** A key stored into the session's attribute for the event tasks being queued */ private final AttributeKey TASKS_QUEUE = new AttributeKey(getClass(), "tasksQueue"); /** A queue used to store the available sessions */ private final BlockingQueue waitingSessions = new LinkedBlockingQueue(); private final Set workers = new HashSet(); private volatile int largestPoolSize; private final AtomicInteger idleWorkers = new AtomicInteger(); private long completedTaskCount; private volatile boolean shutdown; private final IoEventQueueHandler eventQueueHandler; /** * Creates a default ThreadPool, with default values : * - minimum pool size is 0 * - maximum pool size is 16 * - keepAlive set to 30 seconds * - A default ThreadFactory * - All events are accepted */ public OrderedThreadPoolExecutor() { this(DEFAULT_INITIAL_THREAD_POOL_SIZE, DEFAULT_MAX_THREAD_POOL, DEFAULT_KEEP_ALIVE, TimeUnit.SECONDS, Executors .defaultThreadFactory(), null); } /** * Creates a default ThreadPool, with default values : * - minimum pool size is 0 * - keepAlive set to 30 seconds * - A default ThreadFactory * - All events are accepted * * @param maximumPoolSize The maximum pool size */ public OrderedThreadPoolExecutor(int maximumPoolSize) { this(DEFAULT_INITIAL_THREAD_POOL_SIZE, maximumPoolSize, DEFAULT_KEEP_ALIVE, TimeUnit.SECONDS, Executors .defaultThreadFactory(), null); } /** * Creates a default ThreadPool, with default values : * - keepAlive set to 30 seconds * - A default ThreadFactory * - All events are accepted * * @param corePoolSize The initial pool sizePoolSize * @param maximumPoolSize The maximum pool size */ public OrderedThreadPoolExecutor(int corePoolSize, int maximumPoolSize) { this(corePoolSize, maximumPoolSize, DEFAULT_KEEP_ALIVE, TimeUnit.SECONDS, Executors.defaultThreadFactory(), null); } /** * Creates a default ThreadPool, with default values : * - A default ThreadFactory * - All events are accepted * * @param corePoolSize The initial pool sizePoolSize * @param maximumPoolSize The maximum pool size * @param keepAliveTime Default duration for a thread * @param unit Time unit used for the keepAlive value */ public OrderedThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, Executors.defaultThreadFactory(), null); } /** * Creates a default ThreadPool, with default values : * - A default ThreadFactory * * @param corePoolSize The initial pool sizePoolSize * @param maximumPoolSize The maximum pool size * @param keepAliveTime Default duration for a thread * @param unit Time unit used for the keepAlive value * @param eventQueueHandler The queue used to store events */ public OrderedThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, IoEventQueueHandler eventQueueHandler) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, Executors.defaultThreadFactory(), eventQueueHandler); } /** * Creates a default ThreadPool, with default values : * - A default ThreadFactory * * @param corePoolSize The initial pool sizePoolSize * @param maximumPoolSize The maximum pool size * @param keepAliveTime Default duration for a thread * @param unit Time unit used for the keepAlive value * @param threadFactory The factory used to create threads */ public OrderedThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, ThreadFactory threadFactory) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, threadFactory, null); } /** * Creates a new instance of a OrderedThreadPoolExecutor. * * @param corePoolSize The initial pool sizePoolSize * @param maximumPoolSize The maximum pool size * @param keepAliveTime Default duration for a thread * @param unit Time unit used for the keepAlive value * @param threadFactory The factory used to create threads * @param eventQueueHandler The queue used to store events */ public OrderedThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, ThreadFactory threadFactory, IoEventQueueHandler eventQueueHandler) { // We have to initialize the pool with default values (0 and 1) in order to // handle the exception in a better way. We can't add a try {} catch() {} // around the super() call. super(DEFAULT_INITIAL_THREAD_POOL_SIZE, 1, keepAliveTime, unit, new SynchronousQueue(), threadFactory, new AbortPolicy()); if (corePoolSize < DEFAULT_INITIAL_THREAD_POOL_SIZE) { throw new IllegalArgumentException("corePoolSize: " + corePoolSize); } if ((maximumPoolSize == 0) || (maximumPoolSize < corePoolSize)) { throw new IllegalArgumentException("maximumPoolSize: " + maximumPoolSize); } // Now, we can setup the pool sizes super.setCorePoolSize(corePoolSize); super.setMaximumPoolSize(maximumPoolSize); // The queueHandler might be null. if (eventQueueHandler == null) { this.eventQueueHandler = IoEventQueueHandler.NOOP; } else { this.eventQueueHandler = eventQueueHandler; } } /** * Get the session's tasks queue. */ private SessionTasksQueue getSessionTasksQueue(IoSession session) { SessionTasksQueue queue = (SessionTasksQueue) session.getAttribute(TASKS_QUEUE); if (queue == null) { queue = new SessionTasksQueue(); SessionTasksQueue oldQueue = (SessionTasksQueue) session.setAttributeIfAbsent(TASKS_QUEUE, queue); if (oldQueue != null) { queue = oldQueue; } } return queue; } /** * @return The associated queue handler. */ public IoEventQueueHandler getQueueHandler() { return eventQueueHandler; } /** * {@inheritDoc} */ @Override public void setRejectedExecutionHandler(RejectedExecutionHandler handler) { // Ignore the request. It must always be AbortPolicy. } /** * Add a new thread to execute a task, if needed and possible. * It depends on the current pool size. If it's full, we do nothing. */ private void addWorker() { synchronized (workers) { if (workers.size() >= super.getMaximumPoolSize()) { return; } // Create a new worker, and add it to the thread pool Worker worker = new Worker(); Thread thread = getThreadFactory().newThread(worker); // As we have added a new thread, it's considered as idle. idleWorkers.incrementAndGet(); // Now, we can start it. thread.start(); workers.add(worker); if (workers.size() > largestPoolSize) { largestPoolSize = workers.size(); } } } /** * Add a new Worker only if there are no idle worker. */ private void addWorkerIfNecessary() { if (idleWorkers.get() == 0) { synchronized (workers) { if (workers.isEmpty() || (idleWorkers.get() == 0)) { addWorker(); } } } } private void removeWorker() { synchronized (workers) { if (workers.size() <= super.getCorePoolSize()) { return; } waitingSessions.offer(EXIT_SIGNAL); } } /** * {@inheritDoc} */ @Override public int getMaximumPoolSize() { return super.getMaximumPoolSize(); } /** * {@inheritDoc} */ @Override public void setMaximumPoolSize(int maximumPoolSize) { if ((maximumPoolSize <= 0) || (maximumPoolSize < super.getCorePoolSize())) { throw new IllegalArgumentException("maximumPoolSize: " + maximumPoolSize); } synchronized (workers) { super.setMaximumPoolSize(maximumPoolSize); int difference = workers.size() - maximumPoolSize; while (difference > 0) { removeWorker(); --difference; } } } /** * {@inheritDoc} */ @Override public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { long deadline = System.currentTimeMillis() + unit.toMillis(timeout); synchronized (workers) { while (!isTerminated()) { long waitTime = deadline - System.currentTimeMillis(); if (waitTime <= 0) { break; } workers.wait(waitTime); } } return isTerminated(); } /** * {@inheritDoc} */ @Override public boolean isShutdown() { return shutdown; } /** * {@inheritDoc} */ @Override public boolean isTerminated() { if (!shutdown) { return false; } synchronized (workers) { return workers.isEmpty(); } } /** * {@inheritDoc} */ @Override public void shutdown() { if (shutdown) { return; } shutdown = true; synchronized (workers) { for (int i = workers.size(); i > 0; i--) { waitingSessions.offer(EXIT_SIGNAL); } } } /** * {@inheritDoc} */ @Override public List shutdownNow() { shutdown(); List answer = new ArrayList(); IoSession session; while ((session = waitingSessions.poll()) != null) { if (session == EXIT_SIGNAL) { waitingSessions.offer(EXIT_SIGNAL); Thread.yield(); // Let others take the signal. continue; } SessionTasksQueue sessionTasksQueue = (SessionTasksQueue) session.getAttribute(TASKS_QUEUE); synchronized (sessionTasksQueue.tasksQueue) { for (Runnable task : sessionTasksQueue.tasksQueue) { getQueueHandler().polled(this, (IoEvent) task); answer.add(task); } sessionTasksQueue.tasksQueue.clear(); } } return answer; } /** * A Helper class used to print the list of events being queued. */ private void print(Queue queue, IoEvent event) { StringBuilder sb = new StringBuilder(); sb.append("Adding event ").append(event.getType()).append(" to session ").append(event.getSession().getId()); boolean first = true; sb.append("\nQueue : ["); for (Runnable elem : queue) { if (first) { first = false; } else { sb.append(", "); } sb.append(((IoEvent) elem).getType()).append(", "); } sb.append("]\n"); LOGGER.debug(sb.toString()); } /** * {@inheritDoc} */ @Override public void execute(Runnable task) { if (shutdown) { rejectTask(task); } // Check that it's a IoEvent task checkTaskType(task); IoEvent event = (IoEvent) task; // Get the associated session IoSession session = event.getSession(); // Get the session's queue of events SessionTasksQueue sessionTasksQueue = getSessionTasksQueue(session); Queue tasksQueue = sessionTasksQueue.tasksQueue; boolean offerSession; // propose the new event to the event queue handler. If we // use a throttle queue handler, the message may be rejected // if the maximum size has been reached. boolean offerEvent = eventQueueHandler.accept(this, event); if (offerEvent) { // Ok, the message has been accepted synchronized (tasksQueue) { // Inject the event into the executor taskQueue tasksQueue.offer(event); if (sessionTasksQueue.processingCompleted) { sessionTasksQueue.processingCompleted = false; offerSession = true; } else { offerSession = false; } if (LOGGER.isDebugEnabled()) { print(tasksQueue, event); } } } else { offerSession = false; } if (offerSession) { // As the tasksQueue was empty, the task has been executed // immediately, so we can move the session to the queue // of sessions waiting for completion. waitingSessions.offer(session); } addWorkerIfNecessary(); if (offerEvent) { eventQueueHandler.offered(this, event); } } private void rejectTask(Runnable task) { getRejectedExecutionHandler().rejectedExecution(task, this); } private void checkTaskType(Runnable task) { if (!(task instanceof IoEvent)) { throw new IllegalArgumentException("task must be an IoEvent or its subclass."); } } /** * {@inheritDoc} */ @Override public int getActiveCount() { synchronized (workers) { return workers.size() - idleWorkers.get(); } } /** * {@inheritDoc} */ @Override public long getCompletedTaskCount() { synchronized (workers) { long answer = completedTaskCount; for (Worker w : workers) { answer += w.completedTaskCount; } return answer; } } /** * {@inheritDoc} */ @Override public int getLargestPoolSize() { return largestPoolSize; } /** * {@inheritDoc} */ @Override public int getPoolSize() { synchronized (workers) { return workers.size(); } } /** * {@inheritDoc} */ @Override public long getTaskCount() { return getCompletedTaskCount(); } /** * {@inheritDoc} */ @Override public boolean isTerminating() { synchronized (workers) { return isShutdown() && !isTerminated(); } } /** * {@inheritDoc} */ @Override public int prestartAllCoreThreads() { int answer = 0; synchronized (workers) { for (int i = super.getCorePoolSize() - workers.size(); i > 0; i--) { addWorker(); answer++; } } return answer; } /** * {@inheritDoc} */ @Override public boolean prestartCoreThread() { synchronized (workers) { if (workers.size() < super.getCorePoolSize()) { addWorker(); return true; } else { return false; } } } /** * {@inheritDoc} */ @Override public BlockingQueue getQueue() { throw new UnsupportedOperationException(); } /** * {@inheritDoc} */ @Override public void purge() { // Nothing to purge in this implementation. } /** * {@inheritDoc} */ @Override public boolean remove(Runnable task) { checkTaskType(task); IoEvent event = (IoEvent) task; IoSession session = event.getSession(); SessionTasksQueue sessionTasksQueue = (SessionTasksQueue) session.getAttribute(TASKS_QUEUE); Queue tasksQueue = sessionTasksQueue.tasksQueue; if (sessionTasksQueue == null) { return false; } boolean removed; synchronized (tasksQueue) { removed = tasksQueue.remove(task); } if (removed) { getQueueHandler().polled(this, event); } return removed; } /** * {@inheritDoc} */ @Override public int getCorePoolSize() { return super.getCorePoolSize(); } /** * {@inheritDoc} */ @Override public void setCorePoolSize(int corePoolSize) { if (corePoolSize < 0) { throw new IllegalArgumentException("corePoolSize: " + corePoolSize); } if (corePoolSize > super.getMaximumPoolSize()) { throw new IllegalArgumentException("corePoolSize exceeds maximumPoolSize"); } synchronized (workers) { if (super.getCorePoolSize() > corePoolSize) { for (int i = super.getCorePoolSize() - corePoolSize; i > 0; i--) { removeWorker(); } } super.setCorePoolSize(corePoolSize); } } private class Worker implements Runnable { private volatile long completedTaskCount; private Thread thread; public void run() { thread = Thread.currentThread(); try { for (;;) { IoSession session = fetchSession(); idleWorkers.decrementAndGet(); if (session == null) { synchronized (workers) { if (workers.size() > getCorePoolSize()) { // Remove now to prevent duplicate exit. workers.remove(this); break; } } } if (session == EXIT_SIGNAL) { break; } try { if (session != null) { runTasks(getSessionTasksQueue(session)); } } finally { idleWorkers.incrementAndGet(); } } } finally { synchronized (workers) { workers.remove(this); OrderedThreadPoolExecutor.this.completedTaskCount += completedTaskCount; workers.notifyAll(); } } } private IoSession fetchSession() { IoSession session = null; long currentTime = System.currentTimeMillis(); long deadline = currentTime + getKeepAliveTime(TimeUnit.MILLISECONDS); for (;;) { try { long waitTime = deadline - currentTime; if (waitTime <= 0) { break; } try { session = waitingSessions.poll(waitTime, TimeUnit.MILLISECONDS); break; } finally { if (session == null) { currentTime = System.currentTimeMillis(); } } } catch (InterruptedException e) { // Ignore. continue; } } return session; } private void runTasks(SessionTasksQueue sessionTasksQueue) { for (;;) { Runnable task; Queue tasksQueue = sessionTasksQueue.tasksQueue; synchronized (tasksQueue) { task = tasksQueue.poll(); if (task == null) { sessionTasksQueue.processingCompleted = true; break; } } eventQueueHandler.polled(OrderedThreadPoolExecutor.this, (IoEvent) task); runTask(task); } } private void runTask(Runnable task) { beforeExecute(thread, task); boolean ran = false; try { task.run(); ran = true; afterExecute(task, null); completedTaskCount++; } catch (RuntimeException e) { if (!ran) { afterExecute(task, e); } throw e; } } } /** * A class used to store the ordered list of events to be processed by the * session, and the current task state. */ private class SessionTasksQueue { /** A queue of ordered event waiting to be processed */ private final Queue tasksQueue = new ConcurrentLinkedQueue(); /** The current task state */ private boolean processingCompleted = true; } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/executor/IoEventQueueThrottle.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/executor/IoEventQueueThrottle.ja0000644000175000017500000001077412032276026032622 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.executor; import java.util.concurrent.atomic.AtomicInteger; import org.apache.mina.core.session.IoEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Throttles incoming or outgoing events. * * @author Apache MINA Project */ public class IoEventQueueThrottle implements IoEventQueueHandler { /** A logger for this class */ private final static Logger LOGGER = LoggerFactory.getLogger(IoEventQueueThrottle.class); /** The event size estimator instance */ private final IoEventSizeEstimator eventSizeEstimator; private volatile int threshold; private final Object lock = new Object(); private final AtomicInteger counter = new AtomicInteger(); private int waiters; public IoEventQueueThrottle() { this(new DefaultIoEventSizeEstimator(), 65536); } public IoEventQueueThrottle(int threshold) { this(new DefaultIoEventSizeEstimator(), threshold); } public IoEventQueueThrottle(IoEventSizeEstimator eventSizeEstimator, int threshold) { if (eventSizeEstimator == null) { throw new IllegalArgumentException("eventSizeEstimator"); } this.eventSizeEstimator = eventSizeEstimator; setThreshold(threshold); } public IoEventSizeEstimator getEventSizeEstimator() { return eventSizeEstimator; } public int getThreshold() { return threshold; } public int getCounter() { return counter.get(); } public void setThreshold(int threshold) { if (threshold <= 0) { throw new IllegalArgumentException("threshold: " + threshold); } this.threshold = threshold; } public boolean accept(Object source, IoEvent event) { return true; } public void offered(Object source, IoEvent event) { int eventSize = estimateSize(event); int currentCounter = counter.addAndGet(eventSize); logState(); if (currentCounter >= threshold) { block(); } } public void polled(Object source, IoEvent event) { int eventSize = estimateSize(event); int currentCounter = counter.addAndGet(-eventSize); logState(); if (currentCounter < threshold) { unblock(); } } private int estimateSize(IoEvent event) { int size = getEventSizeEstimator().estimateSize(event); if (size < 0) { throw new IllegalStateException(IoEventSizeEstimator.class.getSimpleName() + " returned " + "a negative value (" + size + "): " + event); } return size; } private void logState() { if (LOGGER.isDebugEnabled()) { LOGGER.debug(Thread.currentThread().getName() + " state: " + counter.get() + " / " + getThreshold()); } } protected void block() { if (LOGGER.isDebugEnabled()) { LOGGER.debug(Thread.currentThread().getName() + " blocked: " + counter.get() + " >= " + threshold); } synchronized (lock) { while (counter.get() >= threshold) { waiters++; try { lock.wait(); } catch (InterruptedException e) { // Wait uninterruptably. } finally { waiters--; } } } if (LOGGER.isDebugEnabled()) { LOGGER.debug(Thread.currentThread().getName() + " unblocked: " + counter.get() + " < " + threshold); } } protected void unblock() { synchronized (lock) { if (waiters > 0) { lock.notify(); } } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/executor/package.html0000644000175000017500000000171212032276026030453 0ustar ebourgebourg IoFilters that provide flexible thread model and event queue monitoring interface. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/logging/0000755000175000017500000000000012162575507025773 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/logging/LogLevel.java0000644000175000017500000000367512032276024030346 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.logging; /** * Defines a logging level. * * @author Apache MINA Project * * @see NoopFilter */ public enum LogLevel { /** * {@link LogLevel} which logs messages on the TRACE level. */ TRACE(5), /** * {@link LogLevel} which logs messages on the DEBUG level. */ DEBUG(4), /** * {@link LogLevel} which logs messages on the INFO level. */ INFO(3), /** * {@link LogLevel} which logs messages on the WARN level. */ WARN(2), /** * {@link LogLevel} which logs messages on the ERROR level. */ ERROR(1), /** * {@link LogLevel} which will not log any information */ NONE(0); /** The internal numeric value associated with the log level */ private int level; /** * Create a new instance of a LogLevel. * * @param level The log level */ private LogLevel(int level) { this.level = level; } /** * @return The numeric value associated with the log level */ public int getLevel() { return level; } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/logging/LoggingFilter.java0000644000175000017500000002534712032276024031371 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.logging; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoEventType; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Logs all MINA protocol events. Each event can be * tuned to use a different level based on the user's specific requirements. Methods * are in place that allow the user to use either the get or set method for each event * and pass in the {@link IoEventType} and the {@link LogLevel}. * * By default, all events are logged to the {@link LogLevel#INFO} level except * {@link IoFilterAdapter#exceptionCaught(IoFilter.NextFilter, IoSession, Throwable)}, * which is logged to {@link LogLevel#WARN}. * * @author Apache MINA Project * @org.apache.xbean.XBean */ public class LoggingFilter extends IoFilterAdapter { /** The logger name */ private final String name; /** The logger */ private final Logger logger; /** The log level for the exceptionCaught event. Default to WARN. */ private LogLevel exceptionCaughtLevel = LogLevel.WARN; /** The log level for the messageSent event. Default to INFO. */ private LogLevel messageSentLevel = LogLevel.INFO; /** The log level for the messageReceived event. Default to INFO. */ private LogLevel messageReceivedLevel = LogLevel.INFO; /** The log level for the sessionCreated event. Default to INFO. */ private LogLevel sessionCreatedLevel = LogLevel.INFO; /** The log level for the sessionOpened event. Default to INFO. */ private LogLevel sessionOpenedLevel = LogLevel.INFO; /** The log level for the sessionIdle event. Default to INFO. */ private LogLevel sessionIdleLevel = LogLevel.INFO; /** The log level for the sessionClosed event. Default to INFO. */ private LogLevel sessionClosedLevel = LogLevel.INFO; /** * Default Constructor. */ public LoggingFilter() { this(LoggingFilter.class.getName()); } /** * Create a new NoopFilter using a class name * * @param clazz the cass which name will be used to create the logger */ public LoggingFilter(Class clazz) { this(clazz.getName()); } /** * Create a new NoopFilter using a name * * @param name the name used to create the logger. If null, will default to "NoopFilter" */ public LoggingFilter(String name) { if (name == null) { this.name = LoggingFilter.class.getName(); } else { this.name = name; } logger = LoggerFactory.getLogger(this.name); } /** * @return The logger's name */ public String getName() { return name; } /** * Log if the logger and the current event log level are compatible. We log * a message and an exception. * * @param eventLevel the event log level as requested by the user * @param message the message to log * @param cause the exception cause to log */ private void log(LogLevel eventLevel, String message, Throwable cause) { switch (eventLevel) { case TRACE: logger.trace(message, cause); return; case DEBUG: logger.debug(message, cause); return; case INFO: logger.info(message, cause); return; case WARN: logger.warn(message, cause); return; case ERROR: logger.error(message, cause); return; default: return; } } /** * Log if the logger and the current event log level are compatible. We log * a formated message and its parameters. * * @param eventLevel the event log level as requested by the user * @param message the formated message to log * @param param the parameter injected into the message */ private void log(LogLevel eventLevel, String message, Object param) { switch (eventLevel) { case TRACE: logger.trace(message, param); return; case DEBUG: logger.debug(message, param); return; case INFO: logger.info(message, param); return; case WARN: logger.warn(message, param); return; case ERROR: logger.error(message, param); return; default: return; } } /** * Log if the logger and the current event log level are compatible. We log * a simple message. * * @param eventLevel the event log level as requested by the user * @param message the message to log */ private void log(LogLevel eventLevel, String message) { switch (eventLevel) { case TRACE: logger.trace(message); return; case DEBUG: logger.debug(message); return; case INFO: logger.info(message); return; case WARN: logger.warn(message); return; case ERROR: logger.error(message); return; default: return; } } @Override public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) throws Exception { log(exceptionCaughtLevel, "EXCEPTION :", cause); nextFilter.exceptionCaught(session, cause); } @Override public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception { log(messageReceivedLevel, "RECEIVED: {}", message); nextFilter.messageReceived(session, message); } @Override public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { log(messageSentLevel, "SENT: {}", writeRequest.getMessage()); nextFilter.messageSent(session, writeRequest); } @Override public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception { log(sessionCreatedLevel, "CREATED"); nextFilter.sessionCreated(session); } @Override public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception { log(sessionOpenedLevel, "OPENED"); nextFilter.sessionOpened(session); } @Override public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception { log(sessionIdleLevel, "IDLE"); nextFilter.sessionIdle(session, status); } @Override public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception { log(sessionClosedLevel, "CLOSED"); nextFilter.sessionClosed(session); } /** * Set the LogLevel for the ExceptionCaught event. * * @param level The LogLevel to set */ public void setExceptionCaughtLogLevel(LogLevel level) { exceptionCaughtLevel = level; } /** * Get the LogLevel for the ExceptionCaught event. * * @return The LogLevel for the ExceptionCaught eventType */ public LogLevel getExceptionCaughtLogLevel() { return exceptionCaughtLevel; } /** * Set the LogLevel for the MessageReceived event. * * @param level The LogLevel to set */ public void setMessageReceivedLogLevel(LogLevel level) { messageReceivedLevel = level; } /** * Get the LogLevel for the MessageReceived event. * * @return The LogLevel for the MessageReceived eventType */ public LogLevel getMessageReceivedLogLevel() { return messageReceivedLevel; } /** * Set the LogLevel for the MessageSent event. * * @param level The LogLevel to set */ public void setMessageSentLogLevel(LogLevel level) { messageSentLevel = level; } /** * Get the LogLevel for the MessageSent event. * * @return The LogLevel for the MessageSent eventType */ public LogLevel getMessageSentLogLevel() { return messageSentLevel; } /** * Set the LogLevel for the SessionCreated event. * * @param level The LogLevel to set */ public void setSessionCreatedLogLevel(LogLevel level) { sessionCreatedLevel = level; } /** * Get the LogLevel for the SessionCreated event. * * @return The LogLevel for the SessionCreated eventType */ public LogLevel getSessionCreatedLogLevel() { return sessionCreatedLevel; } /** * Set the LogLevel for the SessionOpened event. * * @param level The LogLevel to set */ public void setSessionOpenedLogLevel(LogLevel level) { sessionOpenedLevel = level; } /** * Get the LogLevel for the SessionOpened event. * * @return The LogLevel for the SessionOpened eventType */ public LogLevel getSessionOpenedLogLevel() { return sessionOpenedLevel; } /** * Set the LogLevel for the SessionIdle event. * * @param level The LogLevel to set */ public void setSessionIdleLogLevel(LogLevel level) { sessionIdleLevel = level; } /** * Get the LogLevel for the SessionIdle event. * * @return The LogLevel for the SessionIdle eventType */ public LogLevel getSessionIdleLogLevel() { return sessionIdleLevel; } /** * Set the LogLevel for the SessionClosed event. * * @param level The LogLevel to set */ public void setSessionClosedLogLevel(LogLevel level) { sessionClosedLevel = level; } /** * Get the LogLevel for the SessionClosed event. * * @return The LogLevel for the SessionClosed eventType */ public LogLevel getSessionClosedLogLevel() { return sessionClosedLevel; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/logging/MdcInjectionFilter.java0000644000175000017500000002203612032276024032341 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.logging; import java.net.InetSocketAddress; import java.util.EnumSet; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.Arrays; import java.util.concurrent.ConcurrentHashMap; import org.apache.mina.core.filterchain.IoFilterEvent; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.util.CommonEventFilter; import org.slf4j.MDC; /** * This filter will inject some key IoSession properties into the Mapped Diagnostic Context (MDC) *

* These properties will be set in the MDC for all logging events that are generated * down the call stack, even in code that is not aware of MINA. * * By default, the following properties will be set for all transports: *

    *
  • "handlerClass"
  • *
  • "remoteAddress"
  • *
  • "localAddress"
  • *
* * When session.getTransportMetadata().getAddressType() == InetSocketAddress.class * the following properties will also be set: *
    *
  • "remoteIp"
  • *
  • "remotePort"
  • *
  • "localIp"
  • *
  • "localPort"
  • *
* * User code can also add custom properties to the context, via {@link #setProperty(IoSession, String, String)} * * If you only want the MDC to be set for the IoHandler code, it's enough to add * one MdcInjectionFilter at the end of the filter chain. * * If you want the MDC to be set for ALL code, you should * add an MdcInjectionFilter to the start of the chain * and add that same MdcInjectionFilter instance after EVERY ExecutorFilter in the chain * * Thus it's ok to have one instance of the MdcInjectionFilter and add it multiple times to the chain * but you should avoid adding multiple instances to the chain. * * @author Apache MINA Project */ public class MdcInjectionFilter extends CommonEventFilter { public enum MdcKey { handlerClass, remoteAddress, localAddress, remoteIp, remotePort, localIp, localPort } /** key used for storing the context map in the IoSession */ private static final AttributeKey CONTEXT_KEY = new AttributeKey(MdcInjectionFilter.class, "context"); private ThreadLocal callDepth = new ThreadLocal() { @Override protected Integer initialValue() { return 0; } }; private EnumSet mdcKeys; /** * Use this constructor when you want to specify which keys to add to the MDC. * You could still add custom keys via {@link #setProperty(IoSession, String, String)} * @param keys set of keys that should be added to the MDC * * @see #setProperty(org.apache.mina.core.session.IoSession, String, String) */ public MdcInjectionFilter(EnumSet keys) { this.mdcKeys = keys.clone(); } /** * Use this constructor when you want to specify which keys to add to the MDC * You could still add custom keys via {@link #setProperty(IoSession, String, String)} * @param keys list of keys that should be added to the MDC * * @see #setProperty(org.apache.mina.core.session.IoSession, String, String) */ public MdcInjectionFilter(MdcKey... keys) { Set keySet = new HashSet(Arrays.asList(keys)); this.mdcKeys = EnumSet.copyOf(keySet); } public MdcInjectionFilter() { this.mdcKeys = EnumSet.allOf(MdcKey.class); } @Override protected void filter(IoFilterEvent event) throws Exception { // since this method can potentially call into itself // we need to check the call depth before clearing the MDC int currentCallDepth = callDepth.get(); callDepth.set(currentCallDepth + 1); Map context = getAndFillContext(event.getSession()); if (currentCallDepth == 0) { /* copy context to the MDC when necessary. */ for (Map.Entry e : context.entrySet()) { MDC.put(e.getKey(), e.getValue()); } } try { /* propagate event down the filter chain */ event.fire(); } finally { if (currentCallDepth == 0) { /* remove context from the MDC */ for (String key : context.keySet()) { MDC.remove(key); } callDepth.remove(); } else { callDepth.set(currentCallDepth); } } } private Map getAndFillContext(final IoSession session) { Map context = getContext(session); if (context.isEmpty()) { fillContext(session, context); } return context; } @SuppressWarnings("unchecked") private static Map getContext(final IoSession session) { Map context = (Map) session.getAttribute(CONTEXT_KEY); if (context == null) { context = new ConcurrentHashMap(); session.setAttribute(CONTEXT_KEY, context); } return context; } /** * write key properties of the session to the Mapped Diagnostic Context * sub-classes could override this method to map more/other attributes * @param session the session to map * @param context key properties will be added to this map */ protected void fillContext(final IoSession session, final Map context) { if (mdcKeys.contains(MdcKey.handlerClass)) { context.put(MdcKey.handlerClass.name(), session.getHandler().getClass().getName()); } if (mdcKeys.contains(MdcKey.remoteAddress)) { context.put(MdcKey.remoteAddress.name(), session.getRemoteAddress().toString()); } if (mdcKeys.contains(MdcKey.localAddress)) { context.put(MdcKey.localAddress.name(), session.getLocalAddress().toString()); } if (session.getTransportMetadata().getAddressType() == InetSocketAddress.class) { InetSocketAddress remoteAddress = (InetSocketAddress) session.getRemoteAddress(); InetSocketAddress localAddress = (InetSocketAddress) session.getLocalAddress(); if (mdcKeys.contains(MdcKey.remoteIp)) { context.put(MdcKey.remoteIp.name(), remoteAddress.getAddress().getHostAddress()); } if (mdcKeys.contains(MdcKey.remotePort)) { context.put(MdcKey.remotePort.name(), String.valueOf(remoteAddress.getPort())); } if (mdcKeys.contains(MdcKey.localIp)) { context.put(MdcKey.localIp.name(), localAddress.getAddress().getHostAddress()); } if (mdcKeys.contains(MdcKey.localPort)) { context.put(MdcKey.localPort.name(), String.valueOf(localAddress.getPort())); } } } public static String getProperty(IoSession session, String key) { if (key == null) { throw new IllegalArgumentException("key should not be null"); } Map context = getContext(session); String answer = context.get(key); if (answer != null) { return answer; } return MDC.get(key); } /** * Add a property to the context for the given session * This property will be added to the MDC for all subsequent events * @param session The session for which you want to set a property * @param key The name of the property (should not be null) * @param value The value of the property */ public static void setProperty(IoSession session, String key, String value) { if (key == null) { throw new IllegalArgumentException("key should not be null"); } if (value == null) { removeProperty(session, key); } Map context = getContext(session); context.put(key, value); MDC.put(key, value); } public static void removeProperty(IoSession session, String key) { if (key == null) { throw new IllegalArgumentException("key should not be null"); } Map context = getContext(session); context.remove(key); MDC.remove(key); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/logging/package.html0000644000175000017500000000175212032276024030245 0ustar ebourgebourg Classes that implement IoFilter and provide logging of the events and data that flows through a MINA-based system. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/keepalive/0000755000175000017500000000000012162575507026312 5ustar ebourgebourg././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveRequestTimeoutHandler.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveRequestTimeou0000644000175000017500000000712412032276024032626 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.keepalive; import org.apache.mina.core.session.IoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Tells {@link KeepAliveFilter} what to do when a keep-alive response message * was not received within a certain timeout. * * @author Apache MINA Project */ public interface KeepAliveRequestTimeoutHandler { /** * Do nothing. */ static KeepAliveRequestTimeoutHandler NOOP = new KeepAliveRequestTimeoutHandler() { public void keepAliveRequestTimedOut(KeepAliveFilter filter, IoSession session) throws Exception { // Do nothing. } }; /** * Logs a warning message, but doesn't do anything else. */ static KeepAliveRequestTimeoutHandler LOG = new KeepAliveRequestTimeoutHandler() { private final Logger LOGGER = LoggerFactory.getLogger(KeepAliveFilter.class); public void keepAliveRequestTimedOut(KeepAliveFilter filter, IoSession session) throws Exception { LOGGER.warn("A keep-alive response message was not received within " + "{} second(s).", filter.getRequestTimeout()); } }; /** * Throws a {@link KeepAliveRequestTimeoutException}. */ static KeepAliveRequestTimeoutHandler EXCEPTION = new KeepAliveRequestTimeoutHandler() { public void keepAliveRequestTimedOut(KeepAliveFilter filter, IoSession session) throws Exception { throw new KeepAliveRequestTimeoutException("A keep-alive response message was not received within " + filter.getRequestTimeout() + " second(s)."); } }; /** * Closes the connection after logging. */ static KeepAliveRequestTimeoutHandler CLOSE = new KeepAliveRequestTimeoutHandler() { private final Logger LOGGER = LoggerFactory.getLogger(KeepAliveFilter.class); public void keepAliveRequestTimedOut(KeepAliveFilter filter, IoSession session) throws Exception { LOGGER.warn("Closing the session because a keep-alive response " + "message was not received within {} second(s).", filter.getRequestTimeout()); session.close(true); } }; /** * A special handler for the 'deaf speaker' mode. */ static KeepAliveRequestTimeoutHandler DEAF_SPEAKER = new KeepAliveRequestTimeoutHandler() { public void keepAliveRequestTimedOut(KeepAliveFilter filter, IoSession session) throws Exception { throw new Error("Shouldn't be invoked. Please file a bug report."); } }; /** * Invoked when {@link KeepAliveFilter} couldn't receive the response for * the sent keep alive message. */ void keepAliveRequestTimedOut(KeepAliveFilter filter, IoSession session) throws Exception; } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveFilter.java0000644000175000017500000003773012032276024032166 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.keepalive; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoEventType; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSessionConfig; import org.apache.mina.core.write.DefaultWriteRequest; import org.apache.mina.core.write.WriteRequest; /** * An {@link IoFilter} that sends a keep-alive request on * {@link IoEventType#SESSION_IDLE} and sends back the response for the * sent keep-alive request. * *

Interference with {@link IoSessionConfig#setIdleTime(IdleStatus, int)}

* * This filter adjusts idleTime of the {@link IdleStatus}s that * this filter is interested in automatically (e.g. {@link IdleStatus#READER_IDLE} * and {@link IdleStatus#WRITER_IDLE}.) Changing the idleTime * of the {@link IdleStatus}s can lead this filter to a unexpected behavior. * Please also note that any {@link IoFilter} and {@link IoHandler} behind * {@link KeepAliveFilter} will not get any {@link IoEventType#SESSION_IDLE} * event. To receive the internal {@link IoEventType#SESSION_IDLE} event, * you can call {@link #setForwardEvent(boolean)} with true. * *

Implementing {@link KeepAliveMessageFactory}

* * To use this filter, you have to provide an implementation of * {@link KeepAliveMessageFactory}, which determines a received or sent * message is a keep-alive message or not and creates a new keep-alive * message: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
NameDescriptionImplementation
ActiveYou want a keep-alive request is sent when the reader is idle. * Once the request is sent, the response for the request should be * received within keepAliveRequestTimeout seconds. Otherwise, * the specified {@link KeepAliveRequestTimeoutHandler} will be invoked. * If a keep-alive request is received, its response also should be sent back. * Both {@link KeepAliveMessageFactory#getRequest(IoSession)} and * {@link KeepAliveMessageFactory#getResponse(IoSession, Object)} must * return a non-null.
Semi-activeYou want a keep-alive request to be sent when the reader is idle. * However, you don't really care if the response is received or not. * If a keep-alive request is received, its response should * also be sent back. * Both {@link KeepAliveMessageFactory#getRequest(IoSession)} and * {@link KeepAliveMessageFactory#getResponse(IoSession, Object)} must * return a non-null, and the timeoutHandler property * should be set to {@link KeepAliveRequestTimeoutHandler#NOOP}, * {@link KeepAliveRequestTimeoutHandler#LOG} or the custom {@link KeepAliveRequestTimeoutHandler} * implementation that doesn't affect the session state nor throw an exception. *
PassiveYou don't want to send a keep-alive request by yourself, but the * response should be sent back if a keep-alive request is received.{@link KeepAliveMessageFactory#getRequest(IoSession)} must return * null and {@link KeepAliveMessageFactory#getResponse(IoSession, Object)} * must return a non-null.
Deaf SpeakerYou want a keep-alive request to be sent when the reader is idle, but * you don't want to send any response back.{@link KeepAliveMessageFactory#getRequest(IoSession)} must return * a non-null, * {@link KeepAliveMessageFactory#getResponse(IoSession, Object)} must * return null and the timeoutHandler must be set to * {@link KeepAliveRequestTimeoutHandler#DEAF_SPEAKER}.
Silent ListenerYou don't want to send a keep-alive request by yourself nor send any * response back.Both {@link KeepAliveMessageFactory#getRequest(IoSession)} and * {@link KeepAliveMessageFactory#getResponse(IoSession, Object)} must * return null.
* Please note that you must implement * {@link KeepAliveMessageFactory#isRequest(IoSession, Object)} and * {@link KeepAliveMessageFactory#isResponse(IoSession, Object)} properly * whatever case you chose. * *

Handling timeout

* * {@link KeepAliveFilter} will notify its {@link KeepAliveRequestTimeoutHandler} * when {@link KeepAliveFilter} didn't receive the response message for a sent * keep-alive message. The default handler is {@link KeepAliveRequestTimeoutHandler#CLOSE}, * but you can use other presets such as {@link KeepAliveRequestTimeoutHandler#NOOP}, * {@link KeepAliveRequestTimeoutHandler#LOG} or {@link KeepAliveRequestTimeoutHandler#EXCEPTION}. * You can even implement your own handler. * *

Special handler: {@link KeepAliveRequestTimeoutHandler#DEAF_SPEAKER}

* * {@link KeepAliveRequestTimeoutHandler#DEAF_SPEAKER} is a special handler which is * dedicated for the 'deaf speaker' mode mentioned above. Setting the * timeoutHandler property to {@link KeepAliveRequestTimeoutHandler#DEAF_SPEAKER} * stops this filter from waiting for response messages and therefore disables * response timeout detection. * * @author Apache MINA Project * @org.apache.xbean.XBean */ public class KeepAliveFilter extends IoFilterAdapter { private final AttributeKey WAITING_FOR_RESPONSE = new AttributeKey(getClass(), "waitingForResponse"); private final AttributeKey IGNORE_READER_IDLE_ONCE = new AttributeKey(getClass(), "ignoreReaderIdleOnce"); private final KeepAliveMessageFactory messageFactory; private final IdleStatus interestedIdleStatus; private volatile KeepAliveRequestTimeoutHandler requestTimeoutHandler; private volatile int requestInterval; private volatile int requestTimeout; private volatile boolean forwardEvent; /** * Creates a new instance with the default properties. * The default property values are: *
    *
  • interestedIdleStatus - {@link IdleStatus#READER_IDLE}
  • *
  • policy = {@link KeepAliveRequestTimeoutHandler#CLOSE}
  • *
  • keepAliveRequestInterval - 60 (seconds)
  • *
  • keepAliveRequestTimeout - 30 (seconds)
  • *
*/ public KeepAliveFilter(KeepAliveMessageFactory messageFactory) { this(messageFactory, IdleStatus.READER_IDLE, KeepAliveRequestTimeoutHandler.CLOSE); } /** * Creates a new instance with the default properties. * The default property values are: *
    *
  • policy = {@link KeepAliveRequestTimeoutHandler#CLOSE}
  • *
  • keepAliveRequestInterval - 60 (seconds)
  • *
  • keepAliveRequestTimeout - 30 (seconds)
  • *
*/ public KeepAliveFilter(KeepAliveMessageFactory messageFactory, IdleStatus interestedIdleStatus) { this(messageFactory, interestedIdleStatus, KeepAliveRequestTimeoutHandler.CLOSE, 60, 30); } /** * Creates a new instance with the default properties. * The default property values are: *
    *
  • interestedIdleStatus - {@link IdleStatus#READER_IDLE}
  • *
  • keepAliveRequestInterval - 60 (seconds)
  • *
  • keepAliveRequestTimeout - 30 (seconds)
  • *
*/ public KeepAliveFilter(KeepAliveMessageFactory messageFactory, KeepAliveRequestTimeoutHandler policy) { this(messageFactory, IdleStatus.READER_IDLE, policy, 60, 30); } /** * Creates a new instance with the default properties. * The default property values are: *
    *
  • keepAliveRequestInterval - 60 (seconds)
  • *
  • keepAliveRequestTimeout - 30 (seconds)
  • *
*/ public KeepAliveFilter(KeepAliveMessageFactory messageFactory, IdleStatus interestedIdleStatus, KeepAliveRequestTimeoutHandler policy) { this(messageFactory, interestedIdleStatus, policy, 60, 30); } /** * Creates a new instance. */ public KeepAliveFilter(KeepAliveMessageFactory messageFactory, IdleStatus interestedIdleStatus, KeepAliveRequestTimeoutHandler policy, int keepAliveRequestInterval, int keepAliveRequestTimeout) { if (messageFactory == null) { throw new IllegalArgumentException("messageFactory"); } if (interestedIdleStatus == null) { throw new IllegalArgumentException("interestedIdleStatus"); } if (policy == null) { throw new IllegalArgumentException("policy"); } this.messageFactory = messageFactory; this.interestedIdleStatus = interestedIdleStatus; requestTimeoutHandler = policy; setRequestInterval(keepAliveRequestInterval); setRequestTimeout(keepAliveRequestTimeout); } public IdleStatus getInterestedIdleStatus() { return interestedIdleStatus; } public KeepAliveRequestTimeoutHandler getRequestTimeoutHandler() { return requestTimeoutHandler; } public void setRequestTimeoutHandler(KeepAliveRequestTimeoutHandler timeoutHandler) { if (timeoutHandler == null) { throw new IllegalArgumentException("timeoutHandler"); } requestTimeoutHandler = timeoutHandler; } public int getRequestInterval() { return requestInterval; } public void setRequestInterval(int keepAliveRequestInterval) { if (keepAliveRequestInterval <= 0) { throw new IllegalArgumentException("keepAliveRequestInterval must be a positive integer: " + keepAliveRequestInterval); } requestInterval = keepAliveRequestInterval; } public int getRequestTimeout() { return requestTimeout; } public void setRequestTimeout(int keepAliveRequestTimeout) { if (keepAliveRequestTimeout <= 0) { throw new IllegalArgumentException("keepAliveRequestTimeout must be a positive integer: " + keepAliveRequestTimeout); } requestTimeout = keepAliveRequestTimeout; } public KeepAliveMessageFactory getMessageFactory() { return messageFactory; } /** * Returns true if and only if this filter forwards * a {@link IoEventType#SESSION_IDLE} event to the next filter. * By default, the value of this property is false. */ public boolean isForwardEvent() { return forwardEvent; } /** * Sets if this filter needs to forward a * {@link IoEventType#SESSION_IDLE} event to the next filter. * By default, the value of this property is false. */ public void setForwardEvent(boolean forwardEvent) { this.forwardEvent = forwardEvent; } @Override public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { if (parent.contains(this)) { throw new IllegalArgumentException("You can't add the same filter instance more than once. " + "Create another instance and add it."); } } @Override public void onPostAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { resetStatus(parent.getSession()); } @Override public void onPostRemove(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { resetStatus(parent.getSession()); } @Override public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception { try { if (messageFactory.isRequest(session, message)) { Object pongMessage = messageFactory.getResponse(session, message); if (pongMessage != null) { nextFilter.filterWrite(session, new DefaultWriteRequest(pongMessage)); } } if (messageFactory.isResponse(session, message)) { resetStatus(session); } } finally { if (!isKeepAliveMessage(session, message)) { nextFilter.messageReceived(session, message); } } } @Override public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { Object message = writeRequest.getMessage(); if (!isKeepAliveMessage(session, message)) { nextFilter.messageSent(session, writeRequest); } } @Override public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception { if (status == interestedIdleStatus) { if (!session.containsAttribute(WAITING_FOR_RESPONSE)) { Object pingMessage = messageFactory.getRequest(session); if (pingMessage != null) { nextFilter.filterWrite(session, new DefaultWriteRequest(pingMessage)); // If policy is OFF, there's no need to wait for // the response. if (getRequestTimeoutHandler() != KeepAliveRequestTimeoutHandler.DEAF_SPEAKER) { markStatus(session); if (interestedIdleStatus == IdleStatus.BOTH_IDLE) { session.setAttribute(IGNORE_READER_IDLE_ONCE); } } else { resetStatus(session); } } } else { handlePingTimeout(session); } } else if (status == IdleStatus.READER_IDLE) { if (session.removeAttribute(IGNORE_READER_IDLE_ONCE) == null) { if (session.containsAttribute(WAITING_FOR_RESPONSE)) { handlePingTimeout(session); } } } if (forwardEvent) { nextFilter.sessionIdle(session, status); } } private void handlePingTimeout(IoSession session) throws Exception { resetStatus(session); KeepAliveRequestTimeoutHandler handler = getRequestTimeoutHandler(); if (handler == KeepAliveRequestTimeoutHandler.DEAF_SPEAKER) { return; } handler.keepAliveRequestTimedOut(this, session); } private void markStatus(IoSession session) { session.getConfig().setIdleTime(interestedIdleStatus, 0); session.getConfig().setReaderIdleTime(getRequestTimeout()); session.setAttribute(WAITING_FOR_RESPONSE); } private void resetStatus(IoSession session) { session.getConfig().setReaderIdleTime(0); session.getConfig().setWriterIdleTime(0); session.getConfig().setIdleTime(interestedIdleStatus, getRequestInterval()); session.removeAttribute(WAITING_FOR_RESPONSE); } private boolean isKeepAliveMessage(IoSession session, Object message) { return messageFactory.isRequest(session, message) || messageFactory.isResponse(session, message); } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveMessageFactory.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveMessageFactor0000644000175000017500000000346412032276024032541 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.keepalive; import org.apache.mina.core.session.IoSession; /** * Provides keep-alive messages to {@link KeepAliveFilter}. * * @author Apache MINA Project */ public interface KeepAliveMessageFactory { /** * Returns true if and only if the specified message is a * keep-alive request message. */ boolean isRequest(IoSession session, Object message); /** * Returns true if and only if the specified message is a * keep-alive response message; */ boolean isResponse(IoSession session, Object message); /** * Returns a (new) keep-alive request message. * Returns null if no request is required. */ Object getRequest(IoSession session); /** * Returns a (new) response message for the specified keep-alive request. * Returns null if no response is required. */ Object getResponse(IoSession session, Object request); } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveRequestTimeoutException.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveRequestTimeou0000644000175000017500000000307512032276024032627 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.keepalive; /** * A {@link RuntimeException} which is thrown when a keep-alive response * message was not received within a certain timeout. * * @author Apache MINA Project */ public class KeepAliveRequestTimeoutException extends RuntimeException { private static final long serialVersionUID = -1985092764656546558L; public KeepAliveRequestTimeoutException() { super(); } public KeepAliveRequestTimeoutException(String message, Throwable cause) { super(message, cause); } public KeepAliveRequestTimeoutException(String message) { super(message); } public KeepAliveRequestTimeoutException(Throwable cause) { super(cause); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/keepalive/package.html0000644000175000017500000000173512032276024030565 0ustar ebourgebourg IoFilter that provides the ability for connections to remain open when data is not being transferred. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/ssl/0000755000175000017500000000000012162575507025146 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/ssl/KeyStoreFactory.java0000644000175000017500000001240112032276024031070 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.ssl; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.cert.CertificateException; /** * A factory that creates and configures a new {@link KeyStore} instance. * * @author Apache MINA Project */ public class KeyStoreFactory { private String type = "JKS"; private String provider = null; private char[] password = null; private byte[] data = null; /** * Creates a new {@link KeyStore}. This method will be called * by the base class when Spring creates a bean using this FactoryBean. * * @return a new {@link KeyStore} instance. */ public KeyStore newInstance() throws KeyStoreException, NoSuchProviderException, NoSuchAlgorithmException, CertificateException, IOException { if (data == null) { throw new IllegalStateException("data property is not set."); } KeyStore ks; if (provider == null) { ks = KeyStore.getInstance(type); } else { ks = KeyStore.getInstance(type, provider); } InputStream is = new ByteArrayInputStream(data); try { ks.load(is, password); } finally { try { is.close(); } catch (IOException ignored) { // Do nothing } } return ks; } /** * Sets the type of key store to create. The default is to create a * JKS key store. * * @param type the type to use when creating the key store. * @throws IllegalArgumentException if the specified value is * null. */ public void setType(String type) { if (type == null) { throw new IllegalArgumentException("type"); } this.type = type; } /** * Sets the key store password. If this value is null no * password will be used to check the integrity of the key store. * * @param password the password or null if no password is * needed. */ public void setPassword(String password) { if (password != null) { this.password = password.toCharArray(); } else { this.password = null; } } /** * Sets the name of the provider to use when creating the key store. The * default is to use the platform default provider. * * @param provider the name of the provider, e.g. "SUN". */ public void setProvider(String provider) { this.provider = provider; } /** * Sets the data which contains the key store. * * @param data the byte array that contains the key store */ public void setData(byte[] data) { byte[] copy = new byte[data.length]; System.arraycopy(data, 0, copy, 0, data.length); this.data = copy; } /** * Sets the data which contains the key store. * * @param dataStream the {@link InputStream} that contains the key store */ private void setData(InputStream dataStream) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); try { for (;;) { int data = dataStream.read(); if (data < 0) { break; } out.write(data); } setData(out.toByteArray()); } finally { try { dataStream.close(); } catch (IOException e) { // Ignore. } } } /** * Sets the data which contains the key store. * * @param dataFile the {@link File} that contains the key store */ public void setDataFile(File dataFile) throws IOException { setData(new BufferedInputStream(new FileInputStream(dataFile))); } /** * Sets the data which contains the key store. * * @param dataUrl the {@link URL} that contains the key store. */ public void setDataUrl(URL dataUrl) throws IOException { setData(dataUrl.openStream()); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/ssl/SslFilter.java0000644000175000017500000006613012033664266027724 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.ssl; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLException; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLSession; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.future.DefaultWriteFuture; import org.apache.mina.core.future.IoFuture; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.core.write.WriteRequestWrapper; import org.apache.mina.core.write.WriteToClosedSessionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An SSL filter that encrypts and decrypts the data exchanged in the session. * Adding this filter triggers SSL handshake procedure immediately by sending * a SSL 'hello' message, so you don't need to call * {@link #startSsl(IoSession)} manually unless you are implementing StartTLS * (see below). If you don't want the handshake procedure to start * immediately, please specify {@code false} as {@code autoStart} parameter in * the constructor. *

* This filter uses an {@link SSLEngine} which was introduced in Java 5, so * Java version 5 or above is mandatory to use this filter. And please note that * this filter only works for TCP/IP connections. *

* *

Implementing StartTLS

*

* You can use {@link #DISABLE_ENCRYPTION_ONCE} attribute to implement StartTLS: *

 * public void messageReceived(IoSession session, Object message) {
 *    if (message instanceof MyStartTLSRequest) {
 *        // Insert SSLFilter to get ready for handshaking
 *        session.getFilterChain().addFirst(sslFilter);
 *
 *        // Disable encryption temporarilly.
 *        // This attribute will be removed by SSLFilter
 *        // inside the Session.write() call below.
 *        session.setAttribute(SSLFilter.DISABLE_ENCRYPTION_ONCE, Boolean.TRUE);
 *
 *        // Write StartTLSResponse which won't be encrypted.
 *        session.write(new MyStartTLSResponse(OK));
 *
 *        // Now DISABLE_ENCRYPTION_ONCE attribute is cleared.
 *        assert session.getAttribute(SSLFilter.DISABLE_ENCRYPTION_ONCE) == null;
 *    }
 * }
 * 
* * @author Apache MINA Project * @org.apache.xbean.XBean */ public class SslFilter extends IoFilterAdapter { /** The logger */ private static final Logger LOGGER = LoggerFactory.getLogger(SslFilter.class); /** * A session attribute key that stores underlying {@link SSLSession} * for each session. */ public static final AttributeKey SSL_SESSION = new AttributeKey(SslFilter.class, "session"); /** * A session attribute key that makes next one write request bypass * this filter (not encrypting the data). This is a marker attribute, * which means that you can put whatever as its value. ({@link Boolean#TRUE} * is preferred.) The attribute is automatically removed from the session * attribute map as soon as {@link IoSession#write(Object)} is invoked, * and therefore should be put again if you want to make more messages * bypass this filter. This is especially useful when you implement * StartTLS. */ public static final AttributeKey DISABLE_ENCRYPTION_ONCE = new AttributeKey(SslFilter.class, "disableOnce"); /** * A session attribute key that makes this filter to emit a * {@link IoHandler#messageReceived(IoSession, Object)} event with a * special message ({@link #SESSION_SECURED} or {@link #SESSION_UNSECURED}). * This is a marker attribute, which means that you can put whatever as its * value. ({@link Boolean#TRUE} is preferred.) By default, this filter * doesn't emit any events related with SSL session flow control. */ public static final AttributeKey USE_NOTIFICATION = new AttributeKey(SslFilter.class, "useNotification"); /** * A session attribute key that should be set to an {@link InetSocketAddress}. * Setting this attribute causes * {@link SSLContext#createSSLEngine(String, int)} to be called passing the * hostname and port of the {@link InetSocketAddress} to get an * {@link SSLEngine} instance. If not set {@link SSLContext#createSSLEngine()} * will be called.
* Using this feature {@link SSLSession} objects may be cached and reused * when in client mode. * * @see SSLContext#createSSLEngine(String, int) */ public static final AttributeKey PEER_ADDRESS = new AttributeKey(SslFilter.class, "peerAddress"); /** * A special message object which is emitted with a {@link IoHandler#messageReceived(IoSession, Object)} * event when the session is secured and its {@link #USE_NOTIFICATION} * attribute is set. */ public static final SslFilterMessage SESSION_SECURED = new SslFilterMessage("SESSION_SECURED"); /** * A special message object which is emitted with a {@link IoHandler#messageReceived(IoSession, Object)} * event when the session is not secure anymore and its {@link #USE_NOTIFICATION} * attribute is set. */ public static final SslFilterMessage SESSION_UNSECURED = new SslFilterMessage("SESSION_UNSECURED"); private static final AttributeKey NEXT_FILTER = new AttributeKey(SslFilter.class, "nextFilter"); private static final AttributeKey SSL_HANDLER = new AttributeKey(SslFilter.class, "handler"); /** The SslContext used */ /* No qualifier */final SSLContext sslContext; /** A flag used to tell the filter to start the handshake immediately */ private final boolean autoStart; /** A flag used to determinate if the handshake should start immediately */ private static final boolean START_HANDSHAKE = true; private boolean client; private boolean needClientAuth; private boolean wantClientAuth; private String[] enabledCipherSuites; private String[] enabledProtocols; /** * Creates a new SSL filter using the specified {@link SSLContext}. * The handshake will start immediately. */ public SslFilter(SSLContext sslContext) { this(sslContext, START_HANDSHAKE); } /** * Creates a new SSL filter using the specified {@link SSLContext}. * If the autostart flag is set to true, the * handshake will start immediately. */ public SslFilter(SSLContext sslContext, boolean autoStart) { if (sslContext == null) { throw new IllegalArgumentException("sslContext"); } this.sslContext = sslContext; this.autoStart = autoStart; } /** * Returns the underlying {@link SSLSession} for the specified session. * * @return null if no {@link SSLSession} is initialized yet. */ public SSLSession getSslSession(IoSession session) { return (SSLSession) session.getAttribute(SSL_SESSION); } /** * (Re)starts SSL session for the specified session if not started yet. * Please note that SSL session is automatically started by default, and therefore * you don't need to call this method unless you've used TLS closure. * * @return true if the SSL session has been started, false if already started. * @throws SSLException if failed to start the SSL session */ public boolean startSsl(IoSession session) throws SSLException { SslHandler handler = getSslSessionHandler(session); boolean started; synchronized (handler) { if (handler.isOutboundDone()) { NextFilter nextFilter = (NextFilter) session.getAttribute(NEXT_FILTER); handler.destroy(); handler.init(); handler.handshake(nextFilter); started = true; } else { started = false; } } handler.flushScheduledEvents(); return started; } /** * An extended toString() method for sessions. If the SSL handshake * is not yet completed, we will print (ssl) in small caps. Once it's * completed, we will use SSL capitalized. */ /* no qualifier */String getSessionInfo(IoSession session) { StringBuilder sb = new StringBuilder(); if (session.getService() instanceof IoAcceptor) { sb.append("Session Server"); } else { sb.append("Session Client"); } sb.append('[').append(session.getId()).append(']'); SslHandler handler = (SslHandler) session.getAttribute(SSL_HANDLER); if (handler == null) { sb.append("(no sslEngine)"); } else if (isSslStarted(session)) { if (handler.isHandshakeComplete()) { sb.append("(SSL)"); } else { sb.append("(ssl...)"); } } return sb.toString(); } /** * Returns true if and only if the specified session is * encrypted/decrypted over SSL/TLS currently. This method will start * to return false after TLS close_notify message * is sent and any messages written after then is not going to get encrypted. */ public boolean isSslStarted(IoSession session) { SslHandler handler = (SslHandler) session.getAttribute(SSL_HANDLER); if (handler == null) { return false; } synchronized (handler) { return !handler.isOutboundDone(); } } /** * Stops the SSL session by sending TLS close_notify message to * initiate TLS closure. * * @param session the {@link IoSession} to initiate TLS closure * @throws SSLException if failed to initiate TLS closure * @throws IllegalArgumentException if this filter is not managing the specified session */ public WriteFuture stopSsl(IoSession session) throws SSLException { SslHandler handler = getSslSessionHandler(session); NextFilter nextFilter = (NextFilter) session.getAttribute(NEXT_FILTER); WriteFuture future; synchronized (handler) { future = initiateClosure(nextFilter, session); } handler.flushScheduledEvents(); return future; } /** * Returns true if the engine is set to use client mode * when handshaking. */ public boolean isUseClientMode() { return client; } /** * Configures the engine to use client (or server) mode when handshaking. */ public void setUseClientMode(boolean clientMode) { this.client = clientMode; } /** * Returns true if the engine will require client authentication. * This option is only useful to engines in the server mode. */ public boolean isNeedClientAuth() { return needClientAuth; } /** * Configures the engine to require client authentication. * This option is only useful for engines in the server mode. */ public void setNeedClientAuth(boolean needClientAuth) { this.needClientAuth = needClientAuth; } /** * Returns true if the engine will request client authentication. * This option is only useful to engines in the server mode. */ public boolean isWantClientAuth() { return wantClientAuth; } /** * Configures the engine to request client authentication. * This option is only useful for engines in the server mode. */ public void setWantClientAuth(boolean wantClientAuth) { this.wantClientAuth = wantClientAuth; } /** * Returns the list of cipher suites to be enabled when {@link SSLEngine} * is initialized. * * @return null means 'use {@link SSLEngine}'s default.' */ public String[] getEnabledCipherSuites() { return enabledCipherSuites; } /** * Sets the list of cipher suites to be enabled when {@link SSLEngine} * is initialized. * * @param cipherSuites null means 'use {@link SSLEngine}'s default.' */ public void setEnabledCipherSuites(String[] cipherSuites) { this.enabledCipherSuites = cipherSuites; } /** * Returns the list of protocols to be enabled when {@link SSLEngine} * is initialized. * * @return null means 'use {@link SSLEngine}'s default.' */ public String[] getEnabledProtocols() { return enabledProtocols; } /** * Sets the list of protocols to be enabled when {@link SSLEngine} * is initialized. * * @param protocols null means 'use {@link SSLEngine}'s default.' */ public void setEnabledProtocols(String[] protocols) { this.enabledProtocols = protocols; } /** * Executed just before the filter is added into the chain, we do : *
    *
  • check that we don't have a SSL filter already present *
  • we update the next filter *
  • we create the SSL handler helper class *
  • and we store it into the session's Attributes *
*/ @Override public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws SSLException { // Check that we don't have a SSL filter already present in the chain if (parent.contains(SslFilter.class)) { String msg = "Only one SSL filter is permitted in a chain."; LOGGER.error(msg); throw new IllegalStateException(msg); } LOGGER.debug("Adding the SSL Filter {} to the chain", name); IoSession session = parent.getSession(); session.setAttribute(NEXT_FILTER, nextFilter); // Create a SSL handler and start handshake. SslHandler handler = new SslHandler(this, session); handler.init(); session.setAttribute(SSL_HANDLER, handler); } @Override public void onPostAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws SSLException { if (autoStart == START_HANDSHAKE) { initiateHandshake(nextFilter, parent.getSession()); } } @Override public void onPreRemove(IoFilterChain parent, String name, NextFilter nextFilter) throws SSLException { IoSession session = parent.getSession(); stopSsl(session); session.removeAttribute(NEXT_FILTER); session.removeAttribute(SSL_HANDLER); } // IoFilter impl. @Override public void sessionClosed(NextFilter nextFilter, IoSession session) throws SSLException { SslHandler handler = getSslSessionHandler(session); try { synchronized (handler) { // release resources handler.destroy(); } handler.flushScheduledEvents(); } finally { // notify closed session nextFilter.sessionClosed(session); } } @Override public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws SSLException { if (LOGGER.isDebugEnabled()) { LOGGER.debug("{}: Message received : {}", getSessionInfo(session), message); } SslHandler handler = getSslSessionHandler(session); synchronized (handler) { if (!isSslStarted(session) && handler.isInboundDone()) { // The SSL session must be established first before we // can push data to the application. Store the incoming // data into a queue for a later processing handler.scheduleMessageReceived(nextFilter, message); } else { IoBuffer buf = (IoBuffer) message; try { // forward read encrypted data to SSL handler handler.messageReceived(nextFilter, buf.buf()); // Handle data to be forwarded to application or written to net handleSslData(nextFilter, handler); if (handler.isInboundDone()) { if (handler.isOutboundDone()) { handler.destroy(); } else { initiateClosure(nextFilter, session); } if (buf.hasRemaining()) { // Forward the data received after closure. handler.scheduleMessageReceived(nextFilter, buf); } } } catch (SSLException ssle) { if (!handler.isHandshakeComplete()) { SSLException newSsle = new SSLHandshakeException("SSL handshake failed."); newSsle.initCause(ssle); ssle = newSsle; } throw ssle; } } } handler.flushScheduledEvents(); } @Override public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) { if (writeRequest instanceof EncryptedWriteRequest) { EncryptedWriteRequest wrappedRequest = (EncryptedWriteRequest) writeRequest; nextFilter.messageSent(session, wrappedRequest.getParentRequest()); } else { // ignore extra buffers used for handshaking } } @Override public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) throws Exception { if (cause instanceof WriteToClosedSessionException) { // Filter out SSL close notify, which is likely to fail to flush // due to disconnection. WriteToClosedSessionException e = (WriteToClosedSessionException) cause; List failedRequests = e.getRequests(); boolean containsCloseNotify = false; for (WriteRequest r : failedRequests) { if (isCloseNotify(r.getMessage())) { containsCloseNotify = true; break; } } if (containsCloseNotify) { if (failedRequests.size() == 1) { // close notify is the only failed request; bail out. return; } List newFailedRequests = new ArrayList(failedRequests.size() - 1); for (WriteRequest r : failedRequests) { if (!isCloseNotify(r.getMessage())) { newFailedRequests.add(r); } } if (newFailedRequests.isEmpty()) { // the failedRequests were full with close notify; bail out. return; } cause = new WriteToClosedSessionException(newFailedRequests, cause.getMessage(), cause.getCause()); } } nextFilter.exceptionCaught(session, cause); } private boolean isCloseNotify(Object message) { if (!(message instanceof IoBuffer)) { return false; } IoBuffer buf = (IoBuffer) message; int offset = buf.position(); return (buf.get(offset + 0) == 0x15) /* Alert */ && (buf.get(offset + 1) == 0x03) /* TLS/SSL */ && ((buf.get(offset + 2) == 0x00) /* SSL 3.0 */ || (buf.get(offset + 2) == 0x01) /* TLS 1.0 */ || (buf.get(offset + 2) == 0x02) /* TLS 1.1 */ || (buf.get(offset + 2) == 0x03)) /* TLS 1.2 */ && (buf.get(offset + 3) == 0x00); /* close_notify */ } @Override public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws SSLException { if (LOGGER.isDebugEnabled()) { LOGGER.debug("{}: Writing Message : {}", getSessionInfo(session), writeRequest); } boolean needsFlush = true; SslHandler handler = getSslSessionHandler(session); synchronized (handler) { if (!isSslStarted(session)) { handler.scheduleFilterWrite(nextFilter, writeRequest); } // Don't encrypt the data if encryption is disabled. else if (session.containsAttribute(DISABLE_ENCRYPTION_ONCE)) { // Remove the marker attribute because it is temporary. session.removeAttribute(DISABLE_ENCRYPTION_ONCE); handler.scheduleFilterWrite(nextFilter, writeRequest); } else { // Otherwise, encrypt the buffer. IoBuffer buf = (IoBuffer) writeRequest.getMessage(); if (handler.isWritingEncryptedData()) { // data already encrypted; simply return buffer handler.scheduleFilterWrite(nextFilter, writeRequest); } else if (handler.isHandshakeComplete()) { // SSL encrypt int pos = buf.position(); handler.encrypt(buf.buf()); buf.position(pos); IoBuffer encryptedBuffer = handler.fetchOutNetBuffer(); handler.scheduleFilterWrite(nextFilter, new EncryptedWriteRequest(writeRequest, encryptedBuffer)); } else { if (session.isConnected()) { // Handshake not complete yet. handler.schedulePreHandshakeWriteRequest(nextFilter, writeRequest); } needsFlush = false; } } } if (needsFlush) { handler.flushScheduledEvents(); } } @Override public void filterClose(final NextFilter nextFilter, final IoSession session) throws SSLException { SslHandler handler = (SslHandler) session.getAttribute(SSL_HANDLER); if (handler == null) { // The connection might already have closed, or // SSL might have not started yet. nextFilter.filterClose(session); return; } WriteFuture future = null; try { synchronized (handler) { if (isSslStarted(session)) { future = initiateClosure(nextFilter, session); future.addListener(new IoFutureListener() { public void operationComplete(IoFuture future) { nextFilter.filterClose(session); } }); } } handler.flushScheduledEvents(); } finally { if (future == null) { nextFilter.filterClose(session); } } } private void initiateHandshake(NextFilter nextFilter, IoSession session) throws SSLException { LOGGER.debug("{} : Starting the first handshake", getSessionInfo(session)); SslHandler handler = getSslSessionHandler(session); synchronized (handler) { handler.handshake(nextFilter); } handler.flushScheduledEvents(); } private WriteFuture initiateClosure(NextFilter nextFilter, IoSession session) throws SSLException { SslHandler handler = getSslSessionHandler(session); // if already shut down if (!handler.closeOutbound()) { return DefaultWriteFuture.newNotWrittenFuture(session, new IllegalStateException( "SSL session is shut down already.")); } // there might be data to write out here? WriteFuture future = handler.writeNetBuffer(nextFilter); if (future == null) { future = DefaultWriteFuture.newWrittenFuture(session); } if (handler.isInboundDone()) { handler.destroy(); } if (session.containsAttribute(USE_NOTIFICATION)) { handler.scheduleMessageReceived(nextFilter, SESSION_UNSECURED); } return future; } // Utilities private void handleSslData(NextFilter nextFilter, SslHandler handler) throws SSLException { if (LOGGER.isDebugEnabled()) { LOGGER.debug("{}: Processing the SSL Data ", getSessionInfo(handler.getSession())); } // Flush any buffered write requests occurred before handshaking. if (handler.isHandshakeComplete()) { handler.flushPreHandshakeEvents(); } // Write encrypted data to be written (if any) handler.writeNetBuffer(nextFilter); // handle app. data read (if any) handleAppDataRead(nextFilter, handler); } private void handleAppDataRead(NextFilter nextFilter, SslHandler handler) { // forward read app data IoBuffer readBuffer = handler.fetchAppBuffer(); if (readBuffer.hasRemaining()) { handler.scheduleMessageReceived(nextFilter, readBuffer); } } private SslHandler getSslSessionHandler(IoSession session) { SslHandler handler = (SslHandler) session.getAttribute(SSL_HANDLER); if (handler == null) { throw new IllegalStateException(); } if (handler.getSslFilter() != this) { throw new IllegalArgumentException("Not managed by this filter."); } return handler; } /** * A message that is sent from {@link SslFilter} when the connection became * secure or is not secure anymore. * * @author Apache MINA Project */ public static class SslFilterMessage { private final String name; private SslFilterMessage(String name) { this.name = name; } @Override public String toString() { return name; } } private static class EncryptedWriteRequest extends WriteRequestWrapper { private final IoBuffer encryptedMessage; private EncryptedWriteRequest(WriteRequest writeRequest, IoBuffer encryptedMessage) { super(writeRequest); this.encryptedMessage = encryptedMessage; } @Override public Object getMessage() { return encryptedMessage; } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/ssl/SslHandler.java0000644000175000017500000006623712032276024030052 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.ssl; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLException; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLEngineResult.Status; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilterEvent; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.future.DefaultWriteFuture; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.session.IoEventType; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.DefaultWriteRequest; import org.apache.mina.core.write.WriteRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A helper class using the SSLEngine API to decrypt/encrypt data. *

* Each connection has a SSLEngine that is used through the lifetime of the connection. * We allocate buffers for use as the outbound and inbound network buffers. * These buffers handle all of the intermediary data for the SSL connection. To make things easy, * we'll require outNetBuffer be completely flushed before trying to wrap any more data. *

* This class is not to be used by any client, it's closely associated with the SSL Filter. * None of its methods are public as they should not be used by any other class but from * the SslFilter class, in the same package * * @author Apache MINA Project */ /** No qualifier*/ class SslHandler { /** A logger for this class */ private final static Logger LOGGER = LoggerFactory.getLogger(SslHandler.class); /** The SSL Filter which has created this handler */ private final SslFilter sslFilter; /** The current session */ private final IoSession session; private final Queue preHandshakeEventQueue = new ConcurrentLinkedQueue(); private final Queue filterWriteEventQueue = new ConcurrentLinkedQueue(); /** A queue used to stack all the incoming data until the SSL session is established */ private final Queue messageReceivedEventQueue = new ConcurrentLinkedQueue(); private SSLEngine sslEngine; /** * Encrypted data from the net */ private IoBuffer inNetBuffer; /** * Encrypted data to be written to the net */ private IoBuffer outNetBuffer; /** * Application cleartext data to be read by application */ private IoBuffer appBuffer; /** * Empty buffer used during initial handshake and close operations */ private final IoBuffer emptyBuffer = IoBuffer.allocate(0); private SSLEngineResult.HandshakeStatus handshakeStatus; /** * A flag set to true when the first SSL handshake has been completed * This is used to avoid sending a notification to the application handler * when we switch to a SECURE or UNSECURE session. */ private boolean firstSSLNegociation; /** A flag set to true when a SSL Handshake has been completed */ private boolean handshakeComplete; /** A flag used to indicate to the SslFilter that the buffer * it will write is already encrypted (this will be the case * for data being produced during the handshake). */ private boolean writingEncryptedData; /** * Create a new SSL Handler, and initialize it. * * @param sslContext * @throws SSLException */ /* no qualifier */SslHandler(SslFilter sslFilter, IoSession session) throws SSLException { this.sslFilter = sslFilter; this.session = session; } /** * Initialize the SSL handshake. * * @throws SSLException If the underlying SSLEngine handshake initialization failed */ /* no qualifier */void init() throws SSLException { if (sslEngine != null) { // We already have a SSL engine created, no need to create a new one return; } LOGGER.debug("{} Initializing the SSL Handler", sslFilter.getSessionInfo(session)); InetSocketAddress peer = (InetSocketAddress) session.getAttribute(SslFilter.PEER_ADDRESS); // Create the SSL engine here if (peer == null) { sslEngine = sslFilter.sslContext.createSSLEngine(); } else { sslEngine = sslFilter.sslContext.createSSLEngine(peer.getHostName(), peer.getPort()); } // Initialize the engine in client mode if necessary sslEngine.setUseClientMode(sslFilter.isUseClientMode()); // Initialize the different SslEngine modes if (!sslEngine.getUseClientMode()) { // Those parameters are only valid when in server mode if (sslFilter.isWantClientAuth()) { sslEngine.setWantClientAuth(true); } if (sslFilter.isNeedClientAuth()) { sslEngine.setNeedClientAuth(true); } } // Set the cipher suite to use by this SslEngine instance if (sslFilter.getEnabledCipherSuites() != null) { sslEngine.setEnabledCipherSuites(sslFilter.getEnabledCipherSuites()); } // Set the list of enabled protocols if (sslFilter.getEnabledProtocols() != null) { sslEngine.setEnabledProtocols(sslFilter.getEnabledProtocols()); } // TODO : we may not need to call this method... // However, if we don't call it here, the tests are failing. Why? sslEngine.beginHandshake(); handshakeStatus = sslEngine.getHandshakeStatus(); // Default value writingEncryptedData = false; // We haven't yet started a SSL negotiation // set the flags accordingly firstSSLNegociation = true; handshakeComplete = false; if (LOGGER.isDebugEnabled()) { LOGGER.debug("{} SSL Handler Initialization done.", sslFilter.getSessionInfo(session)); } } /** * Release allocated buffers. */ /* no qualifier */void destroy() { if (sslEngine == null) { return; } // Close inbound and flush all remaining data if available. try { sslEngine.closeInbound(); } catch (SSLException e) { LOGGER.debug("Unexpected exception from SSLEngine.closeInbound().", e); } if (outNetBuffer != null) { outNetBuffer.capacity(sslEngine.getSession().getPacketBufferSize()); } else { createOutNetBuffer(0); } try { do { outNetBuffer.clear(); } while (sslEngine.wrap(emptyBuffer.buf(), outNetBuffer.buf()).bytesProduced() > 0); } catch (SSLException e) { // Ignore. } finally { destroyOutNetBuffer(); } sslEngine.closeOutbound(); sslEngine = null; preHandshakeEventQueue.clear(); } private void destroyOutNetBuffer() { outNetBuffer.free(); outNetBuffer = null; } /** * @return The SSL filter which has created this handler */ /* no qualifier */SslFilter getSslFilter() { return sslFilter; } /* no qualifier */IoSession getSession() { return session; } /** * Check if we are writing encrypted data. */ /* no qualifier */boolean isWritingEncryptedData() { return writingEncryptedData; } /** * Check if handshake is completed. */ /* no qualifier */boolean isHandshakeComplete() { return handshakeComplete; } /* no qualifier */boolean isInboundDone() { return sslEngine == null || sslEngine.isInboundDone(); } /* no qualifier */boolean isOutboundDone() { return sslEngine == null || sslEngine.isOutboundDone(); } /** * Check if there is any need to complete handshake. */ /* no qualifier */boolean needToCompleteHandshake() { return handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP && !isInboundDone(); } /* no qualifier */void schedulePreHandshakeWriteRequest(NextFilter nextFilter, WriteRequest writeRequest) { preHandshakeEventQueue.add(new IoFilterEvent(nextFilter, IoEventType.WRITE, session, writeRequest)); } /* no qualifier */void flushPreHandshakeEvents() throws SSLException { IoFilterEvent scheduledWrite; while ((scheduledWrite = preHandshakeEventQueue.poll()) != null) { sslFilter .filterWrite(scheduledWrite.getNextFilter(), session, (WriteRequest) scheduledWrite.getParameter()); } } /* no qualifier */void scheduleFilterWrite(NextFilter nextFilter, WriteRequest writeRequest) { filterWriteEventQueue.add(new IoFilterEvent(nextFilter, IoEventType.WRITE, session, writeRequest)); } /** * Push the newly received data into a queue, waiting for the SSL session * to be fully established * * @param nextFilter The next filter to call * @param message The incoming data */ /* no qualifier */void scheduleMessageReceived(NextFilter nextFilter, Object message) { messageReceivedEventQueue.add(new IoFilterEvent(nextFilter, IoEventType.MESSAGE_RECEIVED, session, message)); } /* no qualifier */void flushScheduledEvents() { // Fire events only when no lock is hold for this handler. if (Thread.holdsLock(this)) { return; } IoFilterEvent event; // We need synchronization here inevitably because filterWrite can be // called simultaneously and cause 'bad record MAC' integrity error. synchronized (this) { while ((event = filterWriteEventQueue.poll()) != null) { NextFilter nextFilter = event.getNextFilter(); nextFilter.filterWrite(session, (WriteRequest) event.getParameter()); } } while ((event = messageReceivedEventQueue.poll()) != null) { NextFilter nextFilter = event.getNextFilter(); nextFilter.messageReceived(session, event.getParameter()); } } /** * Call when data are read from net. It will perform the initial hanshake or decrypt * the data if SSL has been initialiaed. * * @param buf buffer to decrypt * @param nextFilter Next filter in chain * @throws SSLException on errors */ /* no qualifier */void messageReceived(NextFilter nextFilter, ByteBuffer buf) throws SSLException { if (LOGGER.isDebugEnabled()) { if (!isOutboundDone()) { LOGGER.debug("{} Processing the received message", sslFilter.getSessionInfo(session)); } else { LOGGER.debug("{} Processing the received message", sslFilter.getSessionInfo(session)); } } // append buf to inNetBuffer if (inNetBuffer == null) { inNetBuffer = IoBuffer.allocate(buf.remaining()).setAutoExpand(true); } inNetBuffer.put(buf); if (!handshakeComplete) { handshake(nextFilter); } else { // Prepare the net data for reading. inNetBuffer.flip(); if (!inNetBuffer.hasRemaining()) { return; } SSLEngineResult res = unwrap(); // prepare to be written again if (inNetBuffer.hasRemaining()) { inNetBuffer.compact(); } else { inNetBuffer = null; } checkStatus(res); renegotiateIfNeeded(nextFilter, res); } if (isInboundDone()) { // Rewind the MINA buffer if not all data is processed and inbound // is finished. int inNetBufferPosition = inNetBuffer == null ? 0 : inNetBuffer.position(); buf.position(buf.position() - inNetBufferPosition); inNetBuffer = null; } } /** * Get decrypted application data. * * @return buffer with data */ /* no qualifier */IoBuffer fetchAppBuffer() { IoBuffer appBuffer = this.appBuffer.flip(); this.appBuffer = null; return appBuffer; } /** * Get encrypted data to be sent. * * @return buffer with data */ /* no qualifier */IoBuffer fetchOutNetBuffer() { IoBuffer answer = outNetBuffer; if (answer == null) { return emptyBuffer; } outNetBuffer = null; return answer.shrink(); } /** * Encrypt provided buffer. Encrypted data returned by getOutNetBuffer(). * * @param src * data to encrypt * @throws SSLException * on errors */ /* no qualifier */void encrypt(ByteBuffer src) throws SSLException { if (!handshakeComplete) { throw new IllegalStateException(); } if (!src.hasRemaining()) { if (outNetBuffer == null) { outNetBuffer = emptyBuffer; } return; } createOutNetBuffer(src.remaining()); // Loop until there is no more data in src while (src.hasRemaining()) { SSLEngineResult result = sslEngine.wrap(src, outNetBuffer.buf()); if (result.getStatus() == SSLEngineResult.Status.OK) { if (result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK) { doTasks(); } } else if (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) { outNetBuffer.capacity(outNetBuffer.capacity() << 1); outNetBuffer.limit(outNetBuffer.capacity()); } else { throw new SSLException("SSLEngine error during encrypt: " + result.getStatus() + " src: " + src + "outNetBuffer: " + outNetBuffer); } } outNetBuffer.flip(); } /** * Start SSL shutdown process. * * @return true if shutdown process is started. false if * shutdown process is already finished. * @throws SSLException * on errors */ /* no qualifier */boolean closeOutbound() throws SSLException { if (sslEngine == null || sslEngine.isOutboundDone()) { return false; } sslEngine.closeOutbound(); createOutNetBuffer(0); SSLEngineResult result; for (;;) { result = sslEngine.wrap(emptyBuffer.buf(), outNetBuffer.buf()); if (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) { outNetBuffer.capacity(outNetBuffer.capacity() << 1); outNetBuffer.limit(outNetBuffer.capacity()); } else { break; } } if (result.getStatus() != SSLEngineResult.Status.CLOSED) { throw new SSLException("Improper close state: " + result); } outNetBuffer.flip(); return true; } /** * @param res * @throws SSLException */ private void checkStatus(SSLEngineResult res) throws SSLException { SSLEngineResult.Status status = res.getStatus(); /* * The status may be: * OK - Normal operation * OVERFLOW - Should never happen since the application buffer is sized to hold the maximum * packet size. * UNDERFLOW - Need to read more data from the socket. It's normal. * CLOSED - The other peer closed the socket. Also normal. */ if (status == SSLEngineResult.Status.BUFFER_OVERFLOW) { throw new SSLException("SSLEngine error during decrypt: " + status + " inNetBuffer: " + inNetBuffer + "appBuffer: " + appBuffer); } } /** * Perform any handshaking processing. */ /* no qualifier */void handshake(NextFilter nextFilter) throws SSLException { for (;;) { switch (handshakeStatus) { case FINISHED: case NOT_HANDSHAKING: if (LOGGER.isDebugEnabled()) { LOGGER.debug("{} processing the FINISHED state", sslFilter.getSessionInfo(session)); } session.setAttribute(SslFilter.SSL_SESSION, sslEngine.getSession()); handshakeComplete = true; // Send the SECURE message only if it's the first SSL handshake if (firstSSLNegociation && session.containsAttribute(SslFilter.USE_NOTIFICATION)) { // SESSION_SECURED is fired only when it's the first handshake firstSSLNegociation = false; scheduleMessageReceived(nextFilter, SslFilter.SESSION_SECURED); } if (LOGGER.isDebugEnabled()) { if (!isOutboundDone()) { LOGGER.debug("{} is now secured", sslFilter.getSessionInfo(session)); } else { LOGGER.debug("{} is not secured yet", sslFilter.getSessionInfo(session)); } } return; case NEED_TASK: if (LOGGER.isDebugEnabled()) { LOGGER.debug("{} processing the NEED_TASK state", sslFilter.getSessionInfo(session)); } handshakeStatus = doTasks(); break; case NEED_UNWRAP: if (LOGGER.isDebugEnabled()) { LOGGER.debug("{} processing the NEED_UNWRAP state", sslFilter.getSessionInfo(session)); } // we need more data read SSLEngineResult.Status status = unwrapHandshake(nextFilter); if (status == SSLEngineResult.Status.BUFFER_UNDERFLOW && handshakeStatus != SSLEngineResult.HandshakeStatus.FINISHED || isInboundDone()) { // We need more data or the session is closed return; } break; case NEED_WRAP: if (LOGGER.isDebugEnabled()) { LOGGER.debug("{} processing the NEED_WRAP state", sslFilter.getSessionInfo(session)); } // First make sure that the out buffer is completely empty. // Since we // cannot call wrap with data left on the buffer if (outNetBuffer != null && outNetBuffer.hasRemaining()) { return; } SSLEngineResult result; createOutNetBuffer(0); for (;;) { result = sslEngine.wrap(emptyBuffer.buf(), outNetBuffer.buf()); if (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) { outNetBuffer.capacity(outNetBuffer.capacity() << 1); outNetBuffer.limit(outNetBuffer.capacity()); } else { break; } } outNetBuffer.flip(); handshakeStatus = result.getHandshakeStatus(); writeNetBuffer(nextFilter); break; default: String msg = "Invalid Handshaking State" + handshakeStatus + " while processing the Handshake for session " + session.getId(); LOGGER.error(msg); throw new IllegalStateException(msg); } } } private void createOutNetBuffer(int expectedRemaining) { // SSLEngine requires us to allocate unnecessarily big buffer // even for small data. *Shrug* int capacity = Math.max(expectedRemaining, sslEngine.getSession().getPacketBufferSize()); if (outNetBuffer != null) { outNetBuffer.capacity(capacity); } else { outNetBuffer = IoBuffer.allocate(capacity).minimumCapacity(0); } } /* no qualifier */WriteFuture writeNetBuffer(NextFilter nextFilter) throws SSLException { // Check if any net data needed to be writen if (outNetBuffer == null || !outNetBuffer.hasRemaining()) { // no; bail out return null; } // set flag that we are writing encrypted data // (used in SSLFilter.filterWrite()) writingEncryptedData = true; // write net data WriteFuture writeFuture = null; try { IoBuffer writeBuffer = fetchOutNetBuffer(); writeFuture = new DefaultWriteFuture(session); sslFilter.filterWrite(nextFilter, session, new DefaultWriteRequest(writeBuffer, writeFuture)); // loop while more writes required to complete handshake while (needToCompleteHandshake()) { try { handshake(nextFilter); } catch (SSLException ssle) { SSLException newSsle = new SSLHandshakeException("SSL handshake failed."); newSsle.initCause(ssle); throw newSsle; } IoBuffer outNetBuffer = fetchOutNetBuffer(); if (outNetBuffer != null && outNetBuffer.hasRemaining()) { writeFuture = new DefaultWriteFuture(session); sslFilter.filterWrite(nextFilter, session, new DefaultWriteRequest(outNetBuffer, writeFuture)); } } } finally { writingEncryptedData = false; } return writeFuture; } private SSLEngineResult.Status unwrapHandshake(NextFilter nextFilter) throws SSLException { // Prepare the net data for reading. if (inNetBuffer != null) { inNetBuffer.flip(); } if (inNetBuffer == null || !inNetBuffer.hasRemaining()) { // Need more data. return SSLEngineResult.Status.BUFFER_UNDERFLOW; } SSLEngineResult res = unwrap(); handshakeStatus = res.getHandshakeStatus(); checkStatus(res); // If handshake finished, no data was produced, and the status is still // ok, try to unwrap more if (handshakeStatus == SSLEngineResult.HandshakeStatus.FINISHED && res.getStatus() == SSLEngineResult.Status.OK && inNetBuffer.hasRemaining()) { res = unwrap(); // prepare to be written again if (inNetBuffer.hasRemaining()) { inNetBuffer.compact(); } else { inNetBuffer = null; } renegotiateIfNeeded(nextFilter, res); } else { // prepare to be written again if (inNetBuffer.hasRemaining()) { inNetBuffer.compact(); } else { inNetBuffer = null; } } return res.getStatus(); } private void renegotiateIfNeeded(NextFilter nextFilter, SSLEngineResult res) throws SSLException { if ((res.getStatus() != SSLEngineResult.Status.CLOSED) && (res.getStatus() != SSLEngineResult.Status.BUFFER_UNDERFLOW) && (res.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)) { // Renegotiation required. handshakeComplete = false; handshakeStatus = res.getHandshakeStatus(); handshake(nextFilter); } } /** * Decrypt the incoming buffer and move the decrypted data to an * application buffer. */ private SSLEngineResult unwrap() throws SSLException { // We first have to create the application buffer if it does not exist if (appBuffer == null) { appBuffer = IoBuffer.allocate(inNetBuffer.remaining()); } else { // We already have one, just add the new data into it appBuffer.expand(inNetBuffer.remaining()); } SSLEngineResult res; Status status = null; HandshakeStatus handshakeStatus = null; do { // Decode the incoming data res = sslEngine.unwrap(inNetBuffer.buf(), appBuffer.buf()); status = res.getStatus(); // We can be processing the Handshake handshakeStatus = res.getHandshakeStatus(); if (status == SSLEngineResult.Status.BUFFER_OVERFLOW) { // We have to grow the target buffer, it's too small. // Then we can call the unwrap method again appBuffer.capacity(appBuffer.capacity() << 1); appBuffer.limit(appBuffer.capacity()); continue; } } while (((status == SSLEngineResult.Status.OK) || (status == SSLEngineResult.Status.BUFFER_OVERFLOW)) && ((handshakeStatus == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) || (handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP))); return res; } /** * Do all the outstanding handshake tasks in the current Thread. */ private SSLEngineResult.HandshakeStatus doTasks() { /* * We could run this in a separate thread, but I don't see the need for * this when used from SSLFilter. Use thread filters in MINA instead? */ Runnable runnable; while ((runnable = sslEngine.getDelegatedTask()) != null) { // TODO : we may have to use a thread pool here to improve the // performances runnable.run(); } return sslEngine.getHandshakeStatus(); } /** * Creates a new MINA buffer that is a deep copy of the remaining bytes in * the given buffer (between index buf.position() and buf.limit()) * * @param src * the buffer to copy * @return the new buffer, ready to read from */ /* no qualifier */static IoBuffer copy(ByteBuffer src) { IoBuffer copy = IoBuffer.allocate(src.remaining()); copy.put(src); copy.flip(); return copy; } public String toString() { StringBuilder sb = new StringBuilder(); sb.append("SSLStatus <"); if (handshakeComplete) { sb.append("SSL established"); } else { sb.append("Processing Handshake").append("; "); sb.append("Status : ").append(handshakeStatus).append("; "); } sb.append(", "); sb.append("HandshakeComplete :").append(handshakeComplete).append(", "); sb.append(">"); return sb.toString(); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/ssl/BogusTrustManagerFactory.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/ssl/BogusTrustManagerFactory.jav0000644000175000017500000000561612032276024032610 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.ssl; import java.security.InvalidAlgorithmParameterException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.Provider; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.ManagerFactoryParameters; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.TrustManagerFactorySpi; import javax.net.ssl.X509TrustManager; /** * Bogus {@link javax.net.ssl.TrustManagerFactory} which creates * {@link javax.net.ssl.X509TrustManager} trusting everything. * * @author Apache MINA Project */ public class BogusTrustManagerFactory extends TrustManagerFactory { public BogusTrustManagerFactory() { super(new BogusTrustManagerFactorySpi(), new Provider("MinaBogus", 1.0, "") { private static final long serialVersionUID = -4024169055312053827L; }, "MinaBogus"); } private static final X509TrustManager X509 = new X509TrustManager() { public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { // Do nothing } public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { // Do nothing } public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }; private static final TrustManager[] X509_MANAGERS = new TrustManager[] { X509 }; private static class BogusTrustManagerFactorySpi extends TrustManagerFactorySpi { @Override protected TrustManager[] engineGetTrustManagers() { return X509_MANAGERS; } @Override protected void engineInit(KeyStore keystore) throws KeyStoreException { // noop } @Override protected void engineInit(ManagerFactoryParameters managerFactoryParameters) throws InvalidAlgorithmParameterException { // noop } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/ssl/SslContextFactory.java0000644000175000017500000003750012032276024031440 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.ssl; import java.security.KeyStore; import java.security.SecureRandom; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.ManagerFactoryParameters; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSessionContext; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; /** * A factory that creates and configures a new {@link SSLContext}. *

* If no properties are set the returned {@link SSLContext} will * be equivalent to what the following creates: *

 *      SSLContext c = SSLContext.getInstance( "TLS" );
 *      c.init(null, null, null);
 * 
*

*

* Use the properties prefixed with keyManagerFactory to control * the creation of the {@link KeyManager} to be used. *

*

* Use the properties prefixed with trustManagerFactory to control * the creation of the {@link TrustManagerFactory} to be used. *

* * @author Apache MINA Project */ public class SslContextFactory { private String provider = null; private String protocol = "TLS"; private SecureRandom secureRandom = null; private KeyStore keyManagerFactoryKeyStore = null; private char[] keyManagerFactoryKeyStorePassword = null; private KeyManagerFactory keyManagerFactory = null; private String keyManagerFactoryAlgorithm = null; private String keyManagerFactoryProvider = null; private boolean keyManagerFactoryAlgorithmUseDefault = true; private KeyStore trustManagerFactoryKeyStore = null; private TrustManagerFactory trustManagerFactory = null; private String trustManagerFactoryAlgorithm = null; private String trustManagerFactoryProvider = null; private boolean trustManagerFactoryAlgorithmUseDefault = true; private ManagerFactoryParameters trustManagerFactoryParameters = null; private int clientSessionCacheSize = -1; private int clientSessionTimeout = -1; private int serverSessionCacheSize = -1; private int serverSessionTimeout = -1; public SSLContext newInstance() throws Exception { KeyManagerFactory kmf = this.keyManagerFactory; TrustManagerFactory tmf = this.trustManagerFactory; if (kmf == null) { String algorithm = keyManagerFactoryAlgorithm; if (algorithm == null && keyManagerFactoryAlgorithmUseDefault) { algorithm = KeyManagerFactory.getDefaultAlgorithm(); } if (algorithm != null) { if (keyManagerFactoryProvider == null) { kmf = KeyManagerFactory.getInstance(algorithm); } else { kmf = KeyManagerFactory.getInstance(algorithm, keyManagerFactoryProvider); } } } if (tmf == null) { String algorithm = trustManagerFactoryAlgorithm; if (algorithm == null && trustManagerFactoryAlgorithmUseDefault) { algorithm = TrustManagerFactory.getDefaultAlgorithm(); } if (algorithm != null) { if (trustManagerFactoryProvider == null) { tmf = TrustManagerFactory.getInstance(algorithm); } else { tmf = TrustManagerFactory.getInstance(algorithm, trustManagerFactoryProvider); } } } KeyManager[] keyManagers = null; if (kmf != null) { kmf.init(keyManagerFactoryKeyStore, keyManagerFactoryKeyStorePassword); keyManagers = kmf.getKeyManagers(); } TrustManager[] trustManagers = null; if (tmf != null) { if (trustManagerFactoryParameters != null) { tmf.init(trustManagerFactoryParameters); } else { tmf.init(trustManagerFactoryKeyStore); } trustManagers = tmf.getTrustManagers(); } SSLContext context = null; if (provider == null) { context = SSLContext.getInstance(protocol); } else { context = SSLContext.getInstance(protocol, provider); } context.init(keyManagers, trustManagers, secureRandom); if (clientSessionCacheSize >= 0) { context.getClientSessionContext().setSessionCacheSize(clientSessionCacheSize); } if (clientSessionTimeout >= 0) { context.getClientSessionContext().setSessionTimeout(clientSessionTimeout); } if (serverSessionCacheSize >= 0) { context.getServerSessionContext().setSessionCacheSize(serverSessionCacheSize); } if (serverSessionTimeout >= 0) { context.getServerSessionContext().setSessionTimeout(serverSessionTimeout); } return context; } /** * Sets the provider of the new {@link SSLContext}. The default value is * null, which means the default provider will be used. * * @param provider the name of the {@link SSLContext} provider */ public void setProvider(String provider) { this.provider = provider; } /** * Sets the protocol to use when creating the {@link SSLContext}. The * default is TLS. * * @param protocol the name of the protocol. */ public void setProtocol(String protocol) { if (protocol == null) { throw new IllegalArgumentException("protocol"); } this.protocol = protocol; } /** * If this is set to true while no {@link KeyManagerFactory} * has been set using {@link #setKeyManagerFactory(KeyManagerFactory)} and * no algorithm has been set using * {@link #setKeyManagerFactoryAlgorithm(String)} the default algorithm * return by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used. * The default value of this property is true. * * @param useDefault * true or false. */ public void setKeyManagerFactoryAlgorithmUseDefault(boolean useDefault) { this.keyManagerFactoryAlgorithmUseDefault = useDefault; } /** * If this is set to true while no {@link TrustManagerFactory} * has been set using {@link #setTrustManagerFactory(TrustManagerFactory)} and * no algorithm has been set using * {@link #setTrustManagerFactoryAlgorithm(String)} the default algorithm * return by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used. * The default value of this property is true. * * @param useDefault true or false. */ public void setTrustManagerFactoryAlgorithmUseDefault(boolean useDefault) { this.trustManagerFactoryAlgorithmUseDefault = useDefault; } /** * Sets the {@link KeyManagerFactory} to use. If this is set the properties * which are used by this factory bean to create a {@link KeyManagerFactory} * will all be ignored. * * @param factory the factory. */ public void setKeyManagerFactory(KeyManagerFactory factory) { this.keyManagerFactory = factory; } /** * Sets the algorithm to use when creating the {@link KeyManagerFactory} * using {@link KeyManagerFactory#getInstance(java.lang.String)} or * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}. *

* This property will be ignored if a {@link KeyManagerFactory} has been * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}. *

*

* If this property isn't set while no {@link KeyManagerFactory} has been * set using {@link #setKeyManagerFactory(KeyManagerFactory)} and * {@link #setKeyManagerFactoryAlgorithmUseDefault(boolean)} has been set to * true the value returned * by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used instead. *

* * @param algorithm the algorithm to use. */ public void setKeyManagerFactoryAlgorithm(String algorithm) { this.keyManagerFactoryAlgorithm = algorithm; } /** * Sets the provider to use when creating the {@link KeyManagerFactory} * using * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}. *

* This property will be ignored if a {@link KeyManagerFactory} has been * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}. *

*

* If this property isn't set and no {@link KeyManagerFactory} has been set * using {@link #setKeyManagerFactory(KeyManagerFactory)} * {@link KeyManagerFactory#getInstance(java.lang.String)} will be used * to create the {@link KeyManagerFactory}. *

* * @param provider the name of the provider. */ public void setKeyManagerFactoryProvider(String provider) { this.keyManagerFactoryProvider = provider; } /** * Sets the {@link KeyStore} which will be used in the call to * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when * the {@link SSLContext} is created. * * @param keyStore the key store. */ public void setKeyManagerFactoryKeyStore(KeyStore keyStore) { this.keyManagerFactoryKeyStore = keyStore; } /** * Sets the password which will be used in the call to * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when * the {@link SSLContext} is created. * * @param password the password. Use null to disable password. */ public void setKeyManagerFactoryKeyStorePassword(String password) { if (password != null) { this.keyManagerFactoryKeyStorePassword = password.toCharArray(); } else { this.keyManagerFactoryKeyStorePassword = null; } } /** * Sets the {@link TrustManagerFactory} to use. If this is set the * properties which are used by this factory bean to create a * {@link TrustManagerFactory} will all be ignored. * * @param factory * the factory. */ public void setTrustManagerFactory(TrustManagerFactory factory) { this.trustManagerFactory = factory; } /** * Sets the algorithm to use when creating the {@link TrustManagerFactory} * using {@link TrustManagerFactory#getInstance(java.lang.String)} or * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}. *

* This property will be ignored if a {@link TrustManagerFactory} has been * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}. *

*

* If this property isn't set while no {@link TrustManagerFactory} has been * set using {@link #setTrustManagerFactory(TrustManagerFactory)} and * {@link #setTrustManagerFactoryAlgorithmUseDefault(boolean)} has been set to * true the value returned * by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used instead. *

* * @param algorithm the algorithm to use. */ public void setTrustManagerFactoryAlgorithm(String algorithm) { this.trustManagerFactoryAlgorithm = algorithm; } /** * Sets the {@link KeyStore} which will be used in the call to * {@link TrustManagerFactory#init(java.security.KeyStore)} when * the {@link SSLContext} is created. *

* This property will be ignored if {@link ManagerFactoryParameters} has been * set directly using {@link #setTrustManagerFactoryParameters(ManagerFactoryParameters)}. *

* * @param keyStore the key store. */ public void setTrustManagerFactoryKeyStore(KeyStore keyStore) { this.trustManagerFactoryKeyStore = keyStore; } /** * Sets the {@link ManagerFactoryParameters} which will be used in the call to * {@link TrustManagerFactory#init(javax.net.ssl.ManagerFactoryParameters)} when * the {@link SSLContext} is created. * * @param parameters describing provider-specific trust material. */ public void setTrustManagerFactoryParameters(ManagerFactoryParameters parameters) { this.trustManagerFactoryParameters = parameters; } /** * Sets the provider to use when creating the {@link TrustManagerFactory} * using * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}. *

* This property will be ignored if a {@link TrustManagerFactory} has been * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}. *

*

* If this property isn't set and no {@link TrustManagerFactory} has been set * using {@link #setTrustManagerFactory(TrustManagerFactory)} * {@link TrustManagerFactory#getInstance(java.lang.String)} will be used * to create the {@link TrustManagerFactory}. *

* * @param provider the name of the provider. */ public void setTrustManagerFactoryProvider(String provider) { this.trustManagerFactoryProvider = provider; } /** * Sets the {@link SecureRandom} to use when initializing the * {@link SSLContext}. The JVM's default will be used if this isn't set. * * @param secureRandom the {@link SecureRandom} or null if the * JVM's default should be used. * @see SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom) */ public void setSecureRandom(SecureRandom secureRandom) { this.secureRandom = secureRandom; } /** * Sets the SSLSession cache size for the {@link SSLSessionContext} for use in client mode. * * @param size the new session cache size limit; zero means there is no limit. * @see SSLSessionContext#setSessionCacheSize(int size) */ public void setClientSessionCacheSize(int size) { this.clientSessionCacheSize = size; } /** * Set the SSLSession timeout limit for the {@link SSLSessionContext} for use in client mode. * * @param seconds the new session timeout limit in seconds; zero means there is no limit. * @see SSLSessionContext#setSessionTimeout(int seconds) */ public void setClientSessionTimeout(int seconds) { this.clientSessionTimeout = seconds; } /** * Sets the SSLSession cache size for the {@link SSLSessionContext} for use in server mode. * * @param serverSessionCacheSize the new session cache size limit; zero means there is no limit. * @see SSLSessionContext#setSessionCacheSize(int) */ public void setServerSessionCacheSize(int serverSessionCacheSize) { this.serverSessionCacheSize = serverSessionCacheSize; } /** * Set the SSLSession timeout limit for the {@link SSLSessionContext} for use in server mode. * * @param serverSessionTimeout the new session timeout limit in seconds; zero means there is no limit. * @see SSLSessionContext#setSessionTimeout(int) */ public void setServerSessionTimeout(int serverSessionTimeout) { this.serverSessionTimeout = serverSessionTimeout; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/ssl/package.html0000644000175000017500000000170712032276024027420 0ustar ebourgebourg Classes that implement IoFilter and provide Secure Sockets Layer functionality. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/firewall/0000755000175000017500000000000012162575507026152 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/firewall/BlacklistFilter.java0000644000175000017500000001646512032276024032073 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.firewall; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A {@link IoFilter} which blocks connections from blacklisted remote * address. * * @author Apache MINA Project * @org.apache.xbean.XBean */ public class BlacklistFilter extends IoFilterAdapter { private final List blacklist = new CopyOnWriteArrayList(); private final static Logger LOGGER = LoggerFactory.getLogger(BlacklistFilter.class); /** * Sets the addresses to be blacklisted. * * NOTE: this call will remove any previously blacklisted addresses. * * @param addresses an array of addresses to be blacklisted. */ public void setBlacklist(InetAddress[] addresses) { if (addresses == null) { throw new IllegalArgumentException("addresses"); } blacklist.clear(); for (int i = 0; i < addresses.length; i++) { InetAddress addr = addresses[i]; block(addr); } } /** * Sets the subnets to be blacklisted. * * NOTE: this call will remove any previously blacklisted subnets. * * @param subnets an array of subnets to be blacklisted. */ public void setSubnetBlacklist(Subnet[] subnets) { if (subnets == null) { throw new IllegalArgumentException("Subnets must not be null"); } blacklist.clear(); for (Subnet subnet : subnets) { block(subnet); } } /** * Sets the addresses to be blacklisted. * * NOTE: this call will remove any previously blacklisted addresses. * * @param addresses a collection of InetAddress objects representing the * addresses to be blacklisted. * @throws IllegalArgumentException if the specified collections contains * non-{@link InetAddress} objects. */ public void setBlacklist(Iterable addresses) { if (addresses == null) { throw new IllegalArgumentException("addresses"); } blacklist.clear(); for (InetAddress address : addresses) { block(address); } } /** * Sets the subnets to be blacklisted. * * NOTE: this call will remove any previously blacklisted subnets. * * @param subnets an array of subnets to be blacklisted. */ public void setSubnetBlacklist(Iterable subnets) { if (subnets == null) { throw new IllegalArgumentException("Subnets must not be null"); } blacklist.clear(); for (Subnet subnet : subnets) { block(subnet); } } /** * Blocks the specified endpoint. */ public void block(InetAddress address) { if (address == null) { throw new IllegalArgumentException("Adress to block can not be null"); } block(new Subnet(address, 32)); } /** * Blocks the specified subnet. */ public void block(Subnet subnet) { if (subnet == null) { throw new IllegalArgumentException("Subnet can not be null"); } blacklist.add(subnet); } /** * Unblocks the specified endpoint. */ public void unblock(InetAddress address) { if (address == null) { throw new IllegalArgumentException("Adress to unblock can not be null"); } unblock(new Subnet(address, 32)); } /** * Unblocks the specified subnet. */ public void unblock(Subnet subnet) { if (subnet == null) { throw new IllegalArgumentException("Subnet can not be null"); } blacklist.remove(subnet); } @Override public void sessionCreated(NextFilter nextFilter, IoSession session) { if (!isBlocked(session)) { // forward if not blocked nextFilter.sessionCreated(session); } else { blockSession(session); } } @Override public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception { if (!isBlocked(session)) { // forward if not blocked nextFilter.sessionOpened(session); } else { blockSession(session); } } @Override public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception { if (!isBlocked(session)) { // forward if not blocked nextFilter.sessionClosed(session); } else { blockSession(session); } } @Override public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception { if (!isBlocked(session)) { // forward if not blocked nextFilter.sessionIdle(session, status); } else { blockSession(session); } } @Override public void messageReceived(NextFilter nextFilter, IoSession session, Object message) { if (!isBlocked(session)) { // forward if not blocked nextFilter.messageReceived(session, message); } else { blockSession(session); } } @Override public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { if (!isBlocked(session)) { // forward if not blocked nextFilter.messageSent(session, writeRequest); } else { blockSession(session); } } private void blockSession(IoSession session) { LOGGER.warn("Remote address in the blacklist; closing."); session.close(true); } private boolean isBlocked(IoSession session) { SocketAddress remoteAddress = session.getRemoteAddress(); if (remoteAddress instanceof InetSocketAddress) { InetAddress address = ((InetSocketAddress) remoteAddress).getAddress(); // check all subnets for (Subnet subnet : blacklist) { if (subnet.inSubnet(address)) { return true; } } } return false; } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/firewall/ConnectionThrottleFilter.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/firewall/ConnectionThrottleFilte0000644000175000017500000001037412032276024032677 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.firewall; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.session.IoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A {@link IoFilter} which blocks connections from connecting * at a rate faster than the specified interval. * * @author Apache MINA Project */ public class ConnectionThrottleFilter extends IoFilterAdapter { private static final long DEFAULT_TIME = 1000; private long allowedInterval; private final Map clients; private final static Logger LOGGER = LoggerFactory.getLogger(ConnectionThrottleFilter.class); /** * Default constructor. Sets the wait time to 1 second */ public ConnectionThrottleFilter() { this(DEFAULT_TIME); } /** * Constructor that takes in a specified wait time. * * @param allowedInterval * The number of milliseconds a client is allowed to wait * before making another successful connection * */ public ConnectionThrottleFilter(long allowedInterval) { this.allowedInterval = allowedInterval; clients = Collections.synchronizedMap(new HashMap()); } /** * Sets the interval between connections from a client. * This value is measured in milliseconds. * * @param allowedInterval * The number of milliseconds a client is allowed to wait * before making another successful connection */ public void setAllowedInterval(long allowedInterval) { this.allowedInterval = allowedInterval; } /** * Method responsible for deciding if a connection is OK * to continue * * @param session * The new session that will be verified * @return * True if the session meets the criteria, otherwise false */ protected boolean isConnectionOk(IoSession session) { SocketAddress remoteAddress = session.getRemoteAddress(); if (remoteAddress instanceof InetSocketAddress) { InetSocketAddress addr = (InetSocketAddress) remoteAddress; long now = System.currentTimeMillis(); if (clients.containsKey(addr.getAddress().getHostAddress())) { LOGGER.debug("This is not a new client"); Long lastConnTime = clients.get(addr.getAddress().getHostAddress()); clients.put(addr.getAddress().getHostAddress(), now); // if the interval between now and the last connection is // less than the allowed interval, return false if (now - lastConnTime < allowedInterval) { LOGGER.warn("Session connection interval too short"); return false; } return true; } clients.put(addr.getAddress().getHostAddress(), now); return true; } return false; } @Override public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception { if (!isConnectionOk(session)) { LOGGER.warn("Connections coming in too fast; closing."); session.close(true); } nextFilter.sessionCreated(session); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/firewall/Subnet.java0000644000175000017500000000703212032276024030243 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.firewall; import java.net.Inet4Address; import java.net.InetAddress; /** * A IP subnet using the CIDR notation. Currently, only IP version 4 * address are supported. * * @author Apache MINA Project */ public class Subnet { private static final int IP_MASK = 0x80000000; private static final int BYTE_MASK = 0xFF; private InetAddress subnet; private int subnetInt; private int subnetMask; private int suffix; /** * Creates a subnet from CIDR notation. For example, the subnet * 192.168.0.0/24 would be created using the {@link InetAddress} * 192.168.0.0 and the mask 24. * @param subnet The {@link InetAddress} of the subnet * @param mask The mask */ public Subnet(InetAddress subnet, int mask) { if (subnet == null) { throw new IllegalArgumentException("Subnet address can not be null"); } if (!(subnet instanceof Inet4Address)) { throw new IllegalArgumentException("Only IPv4 supported"); } if (mask < 0 || mask > 32) { throw new IllegalArgumentException("Mask has to be an integer between 0 and 32"); } this.subnet = subnet; this.subnetInt = toInt(subnet); this.suffix = mask; // binary mask for this subnet this.subnetMask = IP_MASK >> (mask - 1); } /** * Converts an IP address into an integer */ private int toInt(InetAddress inetAddress) { byte[] address = inetAddress.getAddress(); int result = 0; for (int i = 0; i < address.length; i++) { result <<= 8; result |= address[i] & BYTE_MASK; } return result; } /** * Converts an IP address to a subnet using the provided * mask * @param address The address to convert into a subnet * @return The subnet as an integer */ private int toSubnet(InetAddress address) { return toInt(address) & subnetMask; } /** * Checks if the {@link InetAddress} is within this subnet * @param address The {@link InetAddress} to check * @return True if the address is within this subnet, false otherwise */ public boolean inSubnet(InetAddress address) { return toSubnet(address) == subnetInt; } /** * @see Object#toString() */ @Override public String toString() { return subnet.getHostAddress() + "/" + suffix; } @Override public boolean equals(Object obj) { if (!(obj instanceof Subnet)) { return false; } Subnet other = (Subnet) obj; return other.subnetInt == subnetInt && other.suffix == suffix; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/firewall/package.html0000644000175000017500000000170112032276024030416 0ustar ebourgebourg Classes that implement IoFilter and provide host blocking and throttling. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/buffer/0000755000175000017500000000000012162575507025616 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/buffer/BufferedWriteFilter.java0000644000175000017500000002047012032276024032353 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.buffer; import java.io.BufferedOutputStream; import java.util.concurrent.ConcurrentHashMap; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.DefaultWriteRequest; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.util.LazyInitializedCacheMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An {@link IoFilter} implementation used to buffer outgoing {@link WriteRequest} almost * like what {@link BufferedOutputStream} does. Using this filter allows to be less dependent * from network latency. It is also useful when a session is generating very small messages * too frequently and consequently generating unnecessary traffic overhead. * * Please note that it should always be placed before the {@link ProtocolCodecFilter} * as it only handles {@link WriteRequest}'s carrying {@link IoBuffer} objects. * * @author Apache MINA Project * @since MINA 2.0.0-M2 * @org.apache.xbean.XBean */ public final class BufferedWriteFilter extends IoFilterAdapter { private final Logger logger = LoggerFactory.getLogger(BufferedWriteFilter.class); /** * Default buffer size value in bytes. */ public final static int DEFAULT_BUFFER_SIZE = 8192; /** * The buffer size allocated for each new session's buffer. */ private int bufferSize = DEFAULT_BUFFER_SIZE; /** * The map that matches an {@link IoSession} and it's {@link IoBuffer} * buffer. */ private final LazyInitializedCacheMap buffersMap; /** * Default constructor. Sets buffer size to {@link #DEFAULT_BUFFER_SIZE} * bytes. Uses a default instance of {@link ConcurrentHashMap}. */ public BufferedWriteFilter() { this(DEFAULT_BUFFER_SIZE, null); } /** * Constructor which sets buffer size to bufferSize.Uses a default * instance of {@link ConcurrentHashMap}. * * @param bufferSize the new buffer size */ public BufferedWriteFilter(int bufferSize) { this(bufferSize, null); } /** * Constructor which sets buffer size to bufferSize. If * buffersMap is null then a default instance of {@link ConcurrentHashMap} * is created else the provided instance is used. * * @param bufferSize the new buffer size * @param buffersMap the map to use for storing each session buffer */ public BufferedWriteFilter(int bufferSize, LazyInitializedCacheMap buffersMap) { super(); this.bufferSize = bufferSize; if (buffersMap == null) { this.buffersMap = new LazyInitializedCacheMap(); } else { this.buffersMap = buffersMap; } } /** * Returns buffer size. */ public int getBufferSize() { return bufferSize; } /** * Sets the buffer size but only for the newly created buffers. * * @param bufferSize the new buffer size */ public void setBufferSize(int bufferSize) { this.bufferSize = bufferSize; } /** * {@inheritDoc} * * @throws Exception if writeRequest.message isn't an * {@link IoBuffer} instance. */ @Override public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { Object data = writeRequest.getMessage(); if (data instanceof IoBuffer) { write(session, (IoBuffer) data); } else { throw new IllegalArgumentException("This filter should only buffer IoBuffer objects"); } } /** * Writes an {@link IoBuffer} to the session's buffer. * * @param session the session to which a write is requested * @param data the data to buffer */ private void write(IoSession session, IoBuffer data) { IoBuffer dest = buffersMap.putIfAbsent(session, new IoBufferLazyInitializer(bufferSize)); write(session, data, dest); } /** * Writes data {@link IoBuffer} to the buf * {@link IoBuffer} which buffers write requests for the * session {@ link IoSession} until buffer is full * or manually flushed. * * @param session the session where buffer will be written * @param data the data to buffer * @param buf the buffer where data will be temporarily written */ private void write(IoSession session, IoBuffer data, IoBuffer buf) { try { int len = data.remaining(); if (len >= buf.capacity()) { /* * If the request length exceeds the size of the output buffer, * flush the output buffer and then write the data directly. */ NextFilter nextFilter = session.getFilterChain().getNextFilter(this); internalFlush(nextFilter, session, buf); nextFilter.filterWrite(session, new DefaultWriteRequest(data)); return; } if (len > (buf.limit() - buf.position())) { internalFlush(session.getFilterChain().getNextFilter(this), session, buf); } synchronized (buf) { buf.put(data); } } catch (Throwable e) { session.getFilterChain().fireExceptionCaught(e); } } /** * Internal method that actually flushes the buffered data. * * @param nextFilter the {@link NextFilter} of this filter * @param session the session where buffer will be written * @param buf the data to write * @throws Exception if a write operation fails */ private void internalFlush(NextFilter nextFilter, IoSession session, IoBuffer buf) throws Exception { IoBuffer tmp = null; synchronized (buf) { buf.flip(); tmp = buf.duplicate(); buf.clear(); } logger.debug("Flushing buffer: {}", tmp); nextFilter.filterWrite(session, new DefaultWriteRequest(tmp)); } /** * Flushes the buffered data. * * @param session the session where buffer will be written */ public void flush(IoSession session) { try { internalFlush(session.getFilterChain().getNextFilter(this), session, buffersMap.get(session)); } catch (Throwable e) { session.getFilterChain().fireExceptionCaught(e); } } /** * Internal method that actually frees the {@link IoBuffer} that contains * the buffered data that has not been flushed. * * @param session the session we operate on */ private void free(IoSession session) { IoBuffer buf = buffersMap.remove(session); if (buf != null) { buf.free(); } } /** * {@inheritDoc} */ @Override public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) throws Exception { free(session); nextFilter.exceptionCaught(session, cause); } /** * {@inheritDoc} */ @Override public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception { free(session); nextFilter.sessionClosed(session); } }././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/buffer/IoBufferLazyInitializer.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/buffer/IoBufferLazyInitializer.j0000644000175000017500000000326112032276024032524 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.buffer; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.util.LazyInitializer; /** * An {@link LazyInitializer} implementation that initializes an * {@link IoBuffer} only when needed. * * @author Apache MINA Project * @since MINA 2.0.0-M2 */ public class IoBufferLazyInitializer extends LazyInitializer { /** * The buffer size allocated for each new session's buffer. */ private int bufferSize; /** * Constructor which sets allocated buffer size to bufferSize. * * @param bufferSize the new buffer size */ public IoBufferLazyInitializer(int bufferSize) { this.bufferSize = bufferSize; } /** * {@inheritDoc} */ public IoBuffer init() { return IoBuffer.allocate(bufferSize); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/statistic/0000755000175000017500000000000012162575507026354 5ustar ebourgebourg././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/statistic/ProfilerTimerFilter.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/statistic/ProfilerTimerFilter.ja0000644000175000017500000006306112032276024032613 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.statistic; import java.util.HashSet; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoEventType; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; /** * This class will measure the time it takes for a * method in the {@link IoFilterAdapter} class to execute. The basic * premise of the logic in this class is to get the current time * at the beginning of the method, call method on nextFilter, and * then get the current time again. An example of how to use * the filter is: * *
 * ProfilerTimerFilter profiler = new ProfilerTimerFilter(
 *         TimeUnit.MILLISECOND, IoEventType.MESSAGE_RECEIVED);
 * chain.addFirst("Profiler", profiler);
 * 
* * The profiled {@link IoEventType} are : *
    *
  • IoEventType.MESSAGE_RECEIVED
  • *
  • IoEventType.MESSAGE_SENT
  • *
  • IoEventType.SESSION_CREATED
  • *
  • IoEventType.SESSION_OPENED
  • *
  • IoEventType.SESSION_IDLE
  • *
  • IoEventType.SESSION_CLOSED
  • *
* * @author Apache MINA Project * @org.apache.xbean.XBean */ public class ProfilerTimerFilter extends IoFilterAdapter { /** TRhe selected time unit */ private volatile TimeUnit timeUnit; /** A TimerWorker for the MessageReceived events */ private TimerWorker messageReceivedTimerWorker; /** A flag to tell the filter that the MessageReceived must be profiled */ private boolean profileMessageReceived = false; /** A TimerWorker for the MessageSent events */ private TimerWorker messageSentTimerWorker; /** A flag to tell the filter that the MessageSent must be profiled */ private boolean profileMessageSent = false; /** A TimerWorker for the SessionCreated events */ private TimerWorker sessionCreatedTimerWorker; /** A flag to tell the filter that the SessionCreated must be profiled */ private boolean profileSessionCreated = false; /** A TimerWorker for the SessionOpened events */ private TimerWorker sessionOpenedTimerWorker; /** A flag to tell the filter that the SessionOpened must be profiled */ private boolean profileSessionOpened = false; /** A TimerWorker for the SessionIdle events */ private TimerWorker sessionIdleTimerWorker; /** A flag to tell the filter that the SessionIdle must be profiled */ private boolean profileSessionIdle = false; /** A TimerWorker for the SessionClosed events */ private TimerWorker sessionClosedTimerWorker; /** A flag to tell the filter that the SessionClosed must be profiled */ private boolean profileSessionClosed = false; /** * Creates a new instance of ProfilerFilter. This is the * default constructor and will print out timings for * messageReceived and messageSent and the time increment * will be in milliseconds. */ public ProfilerTimerFilter() { this(TimeUnit.MILLISECONDS, IoEventType.MESSAGE_RECEIVED, IoEventType.MESSAGE_SENT); } /** * Creates a new instance of ProfilerFilter. This is the * default constructor and will print out timings for * messageReceived and messageSent. * * @param timeUnit the time increment to set */ public ProfilerTimerFilter(TimeUnit timeUnit) { this(timeUnit, IoEventType.MESSAGE_RECEIVED, IoEventType.MESSAGE_SENT); } /** * Creates a new instance of ProfilerFilter. An example * of this call would be: * *
     * new ProfilerTimerFilter(
     *         TimeUnit.MILLISECONDS,
     *         IoEventType.MESSAGE_RECEIVED, IoEventType.MESSAGE_SENT);
     * 
* * Note : you can add as many {@link IoEventType} as you want. The method accepts * a variable number of arguments. * * @param timeUnit Used to determine the level of precision you need in your timing. * @param eventTypes A list of {@link IoEventType} representation of the methods to profile */ public ProfilerTimerFilter(TimeUnit timeUnit, IoEventType... eventTypes) { this.timeUnit = timeUnit; setProfilers(eventTypes); } /** * Create the profilers for a list of {@link IoEventType}. * * @param eventTypes the list of {@link IoEventType} to profile */ private void setProfilers(IoEventType... eventTypes) { for (IoEventType type : eventTypes) { switch (type) { case MESSAGE_RECEIVED: messageReceivedTimerWorker = new TimerWorker(); profileMessageReceived = true; break; case MESSAGE_SENT: messageSentTimerWorker = new TimerWorker(); profileMessageSent = true; break; case SESSION_CREATED: sessionCreatedTimerWorker = new TimerWorker(); profileSessionCreated = true; break; case SESSION_OPENED: sessionOpenedTimerWorker = new TimerWorker(); profileSessionOpened = true; break; case SESSION_IDLE: sessionIdleTimerWorker = new TimerWorker(); profileSessionIdle = true; break; case SESSION_CLOSED: sessionClosedTimerWorker = new TimerWorker(); profileSessionClosed = true; break; } } } /** * Sets the {@link TimeUnit} being used. * * @param timeUnit the new {@link TimeUnit} to be used. */ public void setTimeUnit(TimeUnit timeUnit) { this.timeUnit = timeUnit; } /** * Set the {@link IoEventType} to be profiled * * @param type The {@link IoEventType} to profile */ public void profile(IoEventType type) { switch (type) { case MESSAGE_RECEIVED: profileMessageReceived = true; if (messageReceivedTimerWorker == null) { messageReceivedTimerWorker = new TimerWorker(); } return; case MESSAGE_SENT: profileMessageSent = true; if (messageSentTimerWorker == null) { messageSentTimerWorker = new TimerWorker(); } return; case SESSION_CREATED: profileSessionCreated = true; if (sessionCreatedTimerWorker == null) { sessionCreatedTimerWorker = new TimerWorker(); } return; case SESSION_OPENED: profileSessionOpened = true; if (sessionOpenedTimerWorker == null) { sessionOpenedTimerWorker = new TimerWorker(); } return; case SESSION_IDLE: profileSessionIdle = true; if (sessionIdleTimerWorker == null) { sessionIdleTimerWorker = new TimerWorker(); } return; case SESSION_CLOSED: profileSessionClosed = true; if (sessionClosedTimerWorker == null) { sessionClosedTimerWorker = new TimerWorker(); } return; } } /** * Stop profiling an {@link IoEventType} * * @param type The {@link IoEventType} to stop profiling */ public void stopProfile(IoEventType type) { switch (type) { case MESSAGE_RECEIVED: profileMessageReceived = false; return; case MESSAGE_SENT: profileMessageSent = false; return; case SESSION_CREATED: profileSessionCreated = false; return; case SESSION_OPENED: profileSessionOpened = false; return; case SESSION_IDLE: profileSessionIdle = false; return; case SESSION_CLOSED: profileSessionClosed = false; return; } } /** * Return the set of {@link IoEventType} which are profiled. * * @return a Set containing all the profiled {@link IoEventType} */ public Set getEventsToProfile() { Set set = new HashSet(); if (profileMessageReceived) { set.add(IoEventType.MESSAGE_RECEIVED); } if (profileMessageSent) { set.add(IoEventType.MESSAGE_SENT); } if (profileSessionCreated) { set.add(IoEventType.SESSION_CREATED); } if (profileSessionOpened) { set.add(IoEventType.SESSION_OPENED); } if (profileSessionIdle) { set.add(IoEventType.SESSION_IDLE); } if (profileSessionClosed) { set.add(IoEventType.SESSION_CLOSED); } return set; } /** * Set the profilers for a list of {@link IoEventType} * * @param eventTypes the list of {@link IoEventType} to profile */ public void setEventsToProfile(IoEventType... eventTypes) { setProfilers(eventTypes); } /** * Profile a MessageReceived event. This method will gather the following * informations : * - the method duration * - the shortest execution time * - the slowest execution time * - the average execution time * - the global number of calls * * @param nextFilter The filter to call next * @param session The associated session * @param message the received message */ @Override public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception { if (profileMessageReceived) { long start = timeNow(); nextFilter.messageReceived(session, message); long end = timeNow(); messageReceivedTimerWorker.addNewDuration(end - start); } else { nextFilter.messageReceived(session, message); } } /** * Profile a MessageSent event. This method will gather the following * informations : * - the method duration * - the shortest execution time * - the slowest execution time * - the average execution time * - the global number of calls * * @param nextFilter The filter to call next * @param session The associated session * @param writeRequest the sent message */ @Override public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { if (profileMessageSent) { long start = timeNow(); nextFilter.messageSent(session, writeRequest); long end = timeNow(); messageSentTimerWorker.addNewDuration(end - start); } else { nextFilter.messageSent(session, writeRequest); } } /** * Profile a SessionCreated event. This method will gather the following * informations : * - the method duration * - the shortest execution time * - the slowest execution time * - the average execution time * - the global number of calls * * @param nextFilter The filter to call next * @param session The associated session */ @Override public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception { if (profileSessionCreated) { long start = timeNow(); nextFilter.sessionCreated(session); long end = timeNow(); sessionCreatedTimerWorker.addNewDuration(end - start); } else { nextFilter.sessionCreated(session); } } /** * Profile a SessionOpened event. This method will gather the following * informations : * - the method duration * - the shortest execution time * - the slowest execution time * - the average execution time * - the global number of calls * * @param nextFilter The filter to call next * @param session The associated session */ @Override public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception { if (profileSessionOpened) { long start = timeNow(); nextFilter.sessionOpened(session); long end = timeNow(); sessionOpenedTimerWorker.addNewDuration(end - start); } else { nextFilter.sessionOpened(session); } } /** * Profile a SessionIdle event. This method will gather the following * informations : * - the method duration * - the shortest execution time * - the slowest execution time * - the average execution time * - the global number of calls * * @param nextFilter The filter to call next * @param session The associated session * @param status The session's status */ @Override public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception { if (profileSessionIdle) { long start = timeNow(); nextFilter.sessionIdle(session, status); long end = timeNow(); sessionIdleTimerWorker.addNewDuration(end - start); } else { nextFilter.sessionIdle(session, status); } } /** * Profile a SessionClosed event. This method will gather the following * informations : * - the method duration * - the shortest execution time * - the slowest execution time * - the average execution time * - the global number of calls * * @param nextFilter The filter to call next * @param session The associated session */ @Override public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception { if (profileSessionClosed) { long start = timeNow(); nextFilter.sessionClosed(session); long end = timeNow(); sessionClosedTimerWorker.addNewDuration(end - start); } else { nextFilter.sessionClosed(session); } } /** * Get the average time for the specified method represented by the {@link IoEventType} * * @param type * The {@link IoEventType} that the user wants to get the average method call time * @return * The average time it took to execute the method represented by the {@link IoEventType} */ public double getAverageTime(IoEventType type) { switch (type) { case MESSAGE_RECEIVED: if (profileMessageReceived) { return messageReceivedTimerWorker.getAverage(); } break; case MESSAGE_SENT: if (profileMessageSent) { return messageSentTimerWorker.getAverage(); } break; case SESSION_CREATED: if (profileSessionCreated) { return sessionCreatedTimerWorker.getAverage(); } break; case SESSION_OPENED: if (profileSessionOpened) { return sessionOpenedTimerWorker.getAverage(); } break; case SESSION_IDLE: if (profileSessionIdle) { return sessionIdleTimerWorker.getAverage(); } break; case SESSION_CLOSED: if (profileSessionClosed) { return sessionClosedTimerWorker.getAverage(); } break; } throw new IllegalArgumentException("You are not monitoring this event. Please add this event first."); } /** * Gets the total number of times the method has been called that is represented by the * {@link IoEventType} * * @param type * The {@link IoEventType} that the user wants to get the total number of method calls * @return * The total number of method calls for the method represented by the {@link IoEventType} */ public long getTotalCalls(IoEventType type) { switch (type) { case MESSAGE_RECEIVED: if (profileMessageReceived) { return messageReceivedTimerWorker.getCallsNumber(); } break; case MESSAGE_SENT: if (profileMessageSent) { return messageSentTimerWorker.getCallsNumber(); } break; case SESSION_CREATED: if (profileSessionCreated) { return sessionCreatedTimerWorker.getCallsNumber(); } break; case SESSION_OPENED: if (profileSessionOpened) { return sessionOpenedTimerWorker.getCallsNumber(); } break; case SESSION_IDLE: if (profileSessionIdle) { return sessionIdleTimerWorker.getCallsNumber(); } break; case SESSION_CLOSED: if (profileSessionClosed) { return sessionClosedTimerWorker.getCallsNumber(); } break; } throw new IllegalArgumentException("You are not monitoring this event. Please add this event first."); } /** * The total time this method has been executing * * @param type * The {@link IoEventType} that the user wants to get the total time this method has * been executing * @return * The total time for the method represented by the {@link IoEventType} */ public long getTotalTime(IoEventType type) { switch (type) { case MESSAGE_RECEIVED: if (profileMessageReceived) { return messageReceivedTimerWorker.getTotal(); } break; case MESSAGE_SENT: if (profileMessageSent) { return messageSentTimerWorker.getTotal(); } break; case SESSION_CREATED: if (profileSessionCreated) { return sessionCreatedTimerWorker.getTotal(); } break; case SESSION_OPENED: if (profileSessionOpened) { return sessionOpenedTimerWorker.getTotal(); } break; case SESSION_IDLE: if (profileSessionIdle) { return sessionIdleTimerWorker.getTotal(); } break; case SESSION_CLOSED: if (profileSessionClosed) { return sessionClosedTimerWorker.getTotal(); } break; } throw new IllegalArgumentException("You are not monitoring this event. Please add this event first."); } /** * The minimum time the method represented by {@link IoEventType} has executed * * @param type * The {@link IoEventType} that the user wants to get the minimum time this method has * executed * @return * The minimum time this method has executed represented by the {@link IoEventType} */ public long getMinimumTime(IoEventType type) { switch (type) { case MESSAGE_RECEIVED: if (profileMessageReceived) { return messageReceivedTimerWorker.getMinimum(); } break; case MESSAGE_SENT: if (profileMessageSent) { return messageSentTimerWorker.getMinimum(); } break; case SESSION_CREATED: if (profileSessionCreated) { return sessionCreatedTimerWorker.getMinimum(); } break; case SESSION_OPENED: if (profileSessionOpened) { return sessionOpenedTimerWorker.getMinimum(); } break; case SESSION_IDLE: if (profileSessionIdle) { return sessionIdleTimerWorker.getMinimum(); } break; case SESSION_CLOSED: if (profileSessionClosed) { return sessionClosedTimerWorker.getMinimum(); } break; } throw new IllegalArgumentException("You are not monitoring this event. Please add this event first."); } /** * The maximum time the method represented by {@link IoEventType} has executed * * @param type * The {@link IoEventType} that the user wants to get the maximum time this method has * executed * @return * The maximum time this method has executed represented by the {@link IoEventType} */ public long getMaximumTime(IoEventType type) { switch (type) { case MESSAGE_RECEIVED: if (profileMessageReceived) { return messageReceivedTimerWorker.getMaximum(); } break; case MESSAGE_SENT: if (profileMessageSent) { return messageSentTimerWorker.getMaximum(); } break; case SESSION_CREATED: if (profileSessionCreated) { return sessionCreatedTimerWorker.getMaximum(); } break; case SESSION_OPENED: if (profileSessionOpened) { return sessionOpenedTimerWorker.getMaximum(); } break; case SESSION_IDLE: if (profileSessionIdle) { return sessionIdleTimerWorker.getMaximum(); } break; case SESSION_CLOSED: if (profileSessionClosed) { return sessionClosedTimerWorker.getMaximum(); } break; } throw new IllegalArgumentException("You are not monitoring this event. Please add this event first."); } /** * Class that will track the time each method takes and be able to provide information * for each method. * */ private class TimerWorker { /** The sum of all operation durations */ private final AtomicLong total; /** The number of calls */ private final AtomicLong callsNumber; /** The fastest operation */ private final AtomicLong minimum; /** The slowest operation */ private final AtomicLong maximum; /** A lock for synchinized blocks */ private final Object lock = new Object(); /** * Creates a new instance of TimerWorker. * */ public TimerWorker() { total = new AtomicLong(); callsNumber = new AtomicLong(); minimum = new AtomicLong(); maximum = new AtomicLong(); } /** * Add a new operation duration to this class. Total is updated * and calls is incremented * * @param duration * The new operation duration */ public void addNewDuration(long duration) { callsNumber.incrementAndGet(); total.addAndGet(duration); synchronized (lock) { // this is not entirely thread-safe, must lock if (duration < minimum.longValue()) { minimum.set(duration); } // this is not entirely thread-safe, must lock if (duration > maximum.longValue()) { maximum.set(duration); } } } /** * Gets the average reading for this event * * @return the average reading for this event */ public double getAverage() { synchronized (lock) { // There are two operations, we need to synchronize the block return total.longValue() / callsNumber.longValue(); } } /** * Returns the total number of profiled operations * * @return The total number of profiled operation */ public long getCallsNumber() { return callsNumber.longValue(); } /** * Returns the total time * * @return the total time */ public long getTotal() { return total.longValue(); } /** * Returns the lowest execution time * * @return the lowest execution time */ public long getMinimum() { return minimum.longValue(); } /** * Returns the longest execution time * * @return the longest execution time */ public long getMaximum() { return maximum.longValue(); } } /** * @return the current time, expressed using the fixed TimeUnit. */ private long timeNow() { switch (timeUnit) { case SECONDS: return System.currentTimeMillis() / 1000; case MICROSECONDS: return System.nanoTime() / 1000; case NANOSECONDS: return System.nanoTime(); default: return System.currentTimeMillis(); } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/statistic/package.html0000644000175000017500000000173512032276024030627 0ustar ebourgebourg Classes that implement IoFilter and provide the ability for filters to be timed on their performance. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/stream/0000755000175000017500000000000012162575507025640 5ustar ebourgebourg././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/stream/FileRegionWriteFilter.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/stream/FileRegionWriteFilter.jav0000644000175000017500000000647312032276024032544 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.stream; import java.io.IOException; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.file.FileRegion; /** * Filter implementation that converts a {@link FileRegion} to {@link IoBuffer} * objects and writes those buffers to the next filter. When end of the * {@code FileRegion} has been reached this filter will call * {@link IoFilter.NextFilter#messageSent(IoSession,WriteRequest)} using the * original {@link FileRegion} written to the session and notifies * {@link org.apache.mina.core.future.WriteFuture} on the original * {@link org.apache.mina.core.write.WriteRequest}. *

Normall {@code FileRegion} objects should be handled by the * {@link org.apache.mina.core.service.IoProcessor} but this is not always possible * if a filter is being used that needs to modify the contents of the file * before sending over the network (i.e. the * {@link org.apache.mina.filter.ssl.SslFilter} or a data compression filter.) *

*

This filter will ignore written messages which aren't {@link FileRegion} * instances. Such messages will be passed to the next filter directly. *

*

NOTE: this filter does not close the file channel in * {@link FileRegion#getFileChannel()} after the data from the file has been * written. The {@code FileChannel} should be closed in either * {@link org.apache.mina.core.service.IoHandler#messageSent(IoSession,Object)} * or in an {@link org.apache.mina.core.future.IoFutureListener} associated with the * {@code WriteFuture}. *

* * @author Apache MINA Project * @org.apache.xbean.XBean */ public class FileRegionWriteFilter extends AbstractStreamWriteFilter { @Override protected Class getMessageClass() { return FileRegion.class; } @Override protected IoBuffer getNextBuffer(FileRegion fileRegion) throws IOException { // If there are no more bytes to read, return null if (fileRegion.getRemainingBytes() <= 0) { return null; } // Allocate the buffer for reading from the file final int bufferSize = (int) Math.min(getWriteBufferSize(), fileRegion.getRemainingBytes()); IoBuffer buffer = IoBuffer.allocate(bufferSize); // Read from the file int bytesRead = fileRegion.getFileChannel().read(buffer.buf(), fileRegion.getPosition()); fileRegion.update(bytesRead); // return the buffer buffer.flip(); return buffer; } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/stream/AbstractStreamWriteFilter.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/stream/AbstractStreamWriteFilter0000644000175000017500000001435612032276024032660 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.stream; import java.io.IOException; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.DefaultWriteRequest; import org.apache.mina.core.write.WriteRequest; /** * TODO Add documentation * * @author Apache MINA Project */ public abstract class AbstractStreamWriteFilter extends IoFilterAdapter { /** * The default buffer size this filter uses for writing. */ public static final int DEFAULT_STREAM_BUFFER_SIZE = 4096; /** * The attribute name used when binding the streaming object to the session. */ protected final AttributeKey CURRENT_STREAM = new AttributeKey(getClass(), "stream"); protected final AttributeKey WRITE_REQUEST_QUEUE = new AttributeKey(getClass(), "queue"); protected final AttributeKey CURRENT_WRITE_REQUEST = new AttributeKey(getClass(), "writeRequest"); private int writeBufferSize = DEFAULT_STREAM_BUFFER_SIZE; @Override public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { Class clazz = getClass(); if (parent.contains(clazz)) { throw new IllegalStateException("Only one " + clazz.getName() + " is permitted."); } } @Override public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { // If we're already processing a stream we need to queue the WriteRequest. if (session.getAttribute(CURRENT_STREAM) != null) { Queue queue = getWriteRequestQueue(session); if (queue == null) { queue = new ConcurrentLinkedQueue(); session.setAttribute(WRITE_REQUEST_QUEUE, queue); } queue.add(writeRequest); return; } Object message = writeRequest.getMessage(); if (getMessageClass().isInstance(message)) { T stream = getMessageClass().cast(message); IoBuffer buffer = getNextBuffer(stream); if (buffer == null) { // End of stream reached. writeRequest.getFuture().setWritten(); nextFilter.messageSent(session, writeRequest); } else { session.setAttribute(CURRENT_STREAM, message); session.setAttribute(CURRENT_WRITE_REQUEST, writeRequest); nextFilter.filterWrite(session, new DefaultWriteRequest(buffer)); } } else { nextFilter.filterWrite(session, writeRequest); } } abstract protected Class getMessageClass(); @SuppressWarnings("unchecked") private Queue getWriteRequestQueue(IoSession session) { return (Queue) session.getAttribute(WRITE_REQUEST_QUEUE); } @SuppressWarnings("unchecked") private Queue removeWriteRequestQueue(IoSession session) { return (Queue) session.removeAttribute(WRITE_REQUEST_QUEUE); } @Override public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { T stream = getMessageClass().cast(session.getAttribute(CURRENT_STREAM)); if (stream == null) { nextFilter.messageSent(session, writeRequest); } else { IoBuffer buffer = getNextBuffer(stream); if (buffer == null) { // End of stream reached. session.removeAttribute(CURRENT_STREAM); WriteRequest currentWriteRequest = (WriteRequest) session.removeAttribute(CURRENT_WRITE_REQUEST); // Write queued WriteRequests. Queue queue = removeWriteRequestQueue(session); if (queue != null) { WriteRequest wr = queue.poll(); while (wr != null) { filterWrite(nextFilter, session, wr); wr = queue.poll(); } } currentWriteRequest.getFuture().setWritten(); nextFilter.messageSent(session, currentWriteRequest); } else { nextFilter.filterWrite(session, new DefaultWriteRequest(buffer)); } } } /** * Returns the size of the write buffer in bytes. Data will be read from the * stream in chunks of this size and then written to the next filter. * * @return the write buffer size. */ public int getWriteBufferSize() { return writeBufferSize; } /** * Sets the size of the write buffer in bytes. Data will be read from the * stream in chunks of this size and then written to the next filter. * * @throws IllegalArgumentException if the specified size is < 1. */ public void setWriteBufferSize(int writeBufferSize) { if (writeBufferSize < 1) { throw new IllegalArgumentException("writeBufferSize must be at least 1"); } this.writeBufferSize = writeBufferSize; } abstract protected IoBuffer getNextBuffer(T message) throws IOException; } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/stream/StreamWriteFilter.java0000644000175000017500000000547712032276024032120 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.stream; import java.io.IOException; import java.io.InputStream; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter; /** * Filter implementation which makes it possible to write {@link InputStream} * objects directly using {@link IoSession#write(Object)}. When an * {@link InputStream} is written to a session this filter will read the bytes * from the stream into {@link IoBuffer} objects and write those buffers * to the next filter. When end of stream has been reached this filter will * call {@link IoFilter.NextFilter#messageSent(IoSession,WriteRequest)} using the original * {@link InputStream} written to the session and notifies * {@link org.apache.mina.core.future.WriteFuture} on the * original {@link org.apache.mina.core.write.WriteRequest}. *

* This filter will ignore written messages which aren't {@link InputStream} * instances. Such messages will be passed to the next filter directly. *

*

* NOTE: this filter does not close the stream after all data from stream * has been written. The {@link org.apache.mina.core.service.IoHandler} should take * care of that in its * {@link org.apache.mina.core.service.IoHandler#messageSent(IoSession,Object)} * callback. *

* * @author Apache MINA Project * @org.apache.xbean.XBean */ public class StreamWriteFilter extends AbstractStreamWriteFilter { @Override protected IoBuffer getNextBuffer(InputStream is) throws IOException { byte[] bytes = new byte[getWriteBufferSize()]; int off = 0; int n = 0; while (off < bytes.length && (n = is.read(bytes, off, bytes.length - off)) != -1) { off += n; } if (n == -1 && off == 0) { return null; } IoBuffer buffer = IoBuffer.wrap(bytes, 0, off); return buffer; } @Override protected Class getMessageClass() { return InputStream.class; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/stream/package.html0000644000175000017500000000163512032276024030112 0ustar ebourgebourg Stream based IoFilter implementation. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/0000755000175000017500000000000012162575507025422 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolCodecFactory.java0000644000175000017500000000345112032276025032344 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import org.apache.mina.core.session.IoSession; /** * Provides {@link ProtocolEncoder} and {@link ProtocolDecoder} which translates * binary or protocol specific data into message object and vice versa. *

* Please refer to * ReverserProtocolProvider * example. * * @author Apache MINA Project */ public interface ProtocolCodecFactory { /** * Returns a new (or reusable) instance of {@link ProtocolEncoder} which * encodes message objects into binary or protocol-specific data. */ ProtocolEncoder getEncoder(IoSession session) throws Exception; /** * Returns a new (or reusable) instance of {@link ProtocolDecoder} which * decodes binary or protocol-specific data into message objects. */ ProtocolDecoder getDecoder(IoSession session) throws Exception; }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolEncoderOutput.java0000644000175000017500000000476512032276025032610 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.file.FileRegion; import org.apache.mina.core.future.WriteFuture; /** * Callback for {@link ProtocolEncoder} to generate encoded messages such as * {@link IoBuffer}s. {@link ProtocolEncoder} must call {@link #write(Object)} * for each encoded message. * * @author Apache MINA Project */ public interface ProtocolEncoderOutput { /** * Callback for {@link ProtocolEncoder} to generate an encoded message such * as an {@link IoBuffer}. {@link ProtocolEncoder} must call * {@link #write(Object)} for each encoded message. * * @param encodedMessage the encoded message, typically an {@link IoBuffer} * or a {@link FileRegion}. */ void write(Object encodedMessage); /** * Merges all buffers you wrote via {@link #write(Object)} into * one {@link IoBuffer} and replaces the old fragmented ones with it. * This method is useful when you want to control the way MINA generates * network packets. Please note that this method only works when you * called {@link #write(Object)} method with only {@link IoBuffer}s. * * @throws IllegalStateException if you wrote something else than {@link IoBuffer} */ void mergeAll(); /** * Flushes all buffers you wrote via {@link #write(Object)} to * the session. This operation is asynchronous; please wait for * the returned {@link WriteFuture} if you want to wait for * the buffers flushed. * * @return null if there is nothing to flush at all. */ WriteFuture flush(); }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolDecoder.java0000644000175000017500000000550312032276025031344 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; /** * Decodes binary or protocol-specific data into higher-level message objects. * MINA invokes {@link #decode(IoSession, IoBuffer, ProtocolDecoderOutput)} * method with read data, and then the decoder implementation puts decoded * messages into {@link ProtocolDecoderOutput} by calling * {@link ProtocolDecoderOutput#write(Object)}. *

* Please refer to * TextLineDecoder * example. * * @author Apache MINA Project * * @see ProtocolDecoderException */ public interface ProtocolDecoder { /** * Decodes binary or protocol-specific content into higher-level message objects. * MINA invokes {@link #decode(IoSession, IoBuffer, ProtocolDecoderOutput)} * method with read data, and then the decoder implementation puts decoded * messages into {@link ProtocolDecoderOutput}. * * @throws Exception if the read data violated protocol specification */ void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception; /** * Invoked when the specified session is closed. This method is useful * when you deal with the protocol which doesn't specify the length of a message * such as HTTP response without content-length header. Implement this * method to process the remaining data that {@link #decode(IoSession, IoBuffer, ProtocolDecoderOutput)} * method didn't process completely. * * @throws Exception if the read data violated protocol specification */ void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception; /** * Releases all resources related with this decoder. * * @throws Exception if failed to dispose all resources */ void dispose(IoSession session) throws Exception; }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/prefixedstring/0000755000175000017500000000000012162575507030457 5ustar ebourgebourg././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringCodecFactory.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStr0000644000175000017500000001227612032276025032636 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.prefixedstring; import org.apache.mina.core.buffer.BufferDataException; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFactory; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolEncoder; import java.nio.charset.Charset; /** * A {@link ProtocolCodecFactory} that performs encoding and decoding * of a Java String object using a fixed-length length prefix. * * @author Apache MINA Project */ public class PrefixedStringCodecFactory implements ProtocolCodecFactory { private final PrefixedStringEncoder encoder; private final PrefixedStringDecoder decoder; public PrefixedStringCodecFactory(Charset charset) { encoder = new PrefixedStringEncoder(charset); decoder = new PrefixedStringDecoder(charset); } public PrefixedStringCodecFactory() { this(Charset.defaultCharset()); } /** * Returns the allowed maximum size of an encoded string. * If the size of the encoded String exceeds this value, the encoder * will throw a {@link IllegalArgumentException}. * The default value is {@link PrefixedStringEncoder#DEFAULT_MAX_DATA_LENGTH}. *

* This method does the same job as {@link PrefixedStringEncoder#setMaxDataLength(int)}. * * @return the allowed maximum size of an encoded string. */ public int getEncoderMaxDataLength() { return encoder.getMaxDataLength(); } /** * Sets the allowed maximum size of an encoded String. * If the size of the encoded String exceeds this value, the encoder * will throw a {@link IllegalArgumentException}. * The default value is {@link PrefixedStringEncoder#DEFAULT_MAX_DATA_LENGTH}. *

* This method does the same job as {@link PrefixedStringEncoder#getMaxDataLength()}. * * @param maxDataLength allowed maximum size of an encoded String. */ public void setEncoderMaxDataLength(int maxDataLength) { encoder.setMaxDataLength(maxDataLength); } /** * Returns the allowed maximum size of a decoded string. *

* This method does the same job as {@link PrefixedStringEncoder#setMaxDataLength(int)}. *

* * @return the allowed maximum size of an encoded string. * @see #setDecoderMaxDataLength(int) */ public int getDecoderMaxDataLength() { return decoder.getMaxDataLength(); } /** * Sets the maximum allowed value specified as data length in the decoded data *

* Useful for preventing an OutOfMemory attack by the peer. * The decoder will throw a {@link BufferDataException} when data length * specified in the incoming data is greater than maxDataLength * The default value is {@link PrefixedStringDecoder#DEFAULT_MAX_DATA_LENGTH}. * * This method does the same job as {@link PrefixedStringDecoder#setMaxDataLength(int)}. *

* * @param maxDataLength maximum allowed value specified as data length in the incoming data */ public void setDecoderMaxDataLength(int maxDataLength) { decoder.setMaxDataLength(maxDataLength); } /** * Sets the length of the prefix used by the decoder * * @param prefixLength the length of the length prefix (1, 2, or 4) */ public void setDecoderPrefixLength(int prefixLength) { decoder.setPrefixLength(prefixLength); } /** * Gets the length of the length prefix (1, 2, or 4) used by the decoder * * @return length of the length prefix */ public int getDecoderPrefixLength() { return decoder.getPrefixLength(); } /** * Sets the length of the prefix used by the encoder * * @param prefixLength the length of the length prefix (1, 2, or 4) */ public void setEncoderPrefixLength(int prefixLength) { encoder.setPrefixLength(prefixLength); } /** * Gets the length of the length prefix (1, 2, or 4) used by the encoder * * @return length of the length prefix */ public int getEncoderPrefixLength() { return encoder.getPrefixLength(); } public ProtocolEncoder getEncoder(IoSession session) throws Exception { return encoder; } public ProtocolDecoder getDecoder(IoSession session) throws Exception { return decoder; } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringDecoder.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStr0000644000175000017500000000774212032276025032640 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.prefixedstring; import org.apache.mina.core.buffer.BufferDataException; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.CumulativeProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import java.nio.charset.Charset; /** * A {@link ProtocolDecoder} which decodes a String using a fixed-length length prefix. * * @author Apache MINA Project */ public class PrefixedStringDecoder extends CumulativeProtocolDecoder { public final static int DEFAULT_PREFIX_LENGTH = 4; public final static int DEFAULT_MAX_DATA_LENGTH = 2048; private final Charset charset; private int prefixLength = DEFAULT_PREFIX_LENGTH; private int maxDataLength = DEFAULT_MAX_DATA_LENGTH; /** * @param charset the charset to use for encoding * @param prefixLength the length of the prefix * @param maxDataLength maximum number of bytes allowed for a single String */ public PrefixedStringDecoder(Charset charset, int prefixLength, int maxDataLength) { this.charset = charset; this.prefixLength = prefixLength; this.maxDataLength = maxDataLength; } public PrefixedStringDecoder(Charset charset, int prefixLength) { this(charset, prefixLength, DEFAULT_MAX_DATA_LENGTH); } public PrefixedStringDecoder(Charset charset) { this(charset, DEFAULT_PREFIX_LENGTH); } /** * Sets the number of bytes used by the length prefix * * @param prefixLength the length of the length prefix (1, 2, or 4) */ public void setPrefixLength(int prefixLength) { this.prefixLength = prefixLength; } /** * Gets the length of the length prefix (1, 2, or 4) * * @return length of the length prefix */ public int getPrefixLength() { return prefixLength; } /** * Sets the maximum allowed value specified as data length in the incoming data *

* Useful for preventing an OutOfMemory attack by the peer. * The decoder will throw a {@link BufferDataException} when data length * specified in the incoming data is greater than maxDataLength * The default value is {@link PrefixedStringDecoder#DEFAULT_MAX_DATA_LENGTH}. *

* * @param maxDataLength maximum allowed value specified as data length in the incoming data */ public void setMaxDataLength(int maxDataLength) { this.maxDataLength = maxDataLength; } /** * Gets the maximum number of bytes allowed for a single String * * @return maximum number of bytes allowed for a single String */ public int getMaxDataLength() { return maxDataLength; } protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { if (in.prefixedDataAvailable(prefixLength, maxDataLength)) { String msg = in.getPrefixedString(prefixLength, charset.newDecoder()); out.write(msg); return true; } return false; } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringEncoder.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStr0000644000175000017500000001011412032276025032623 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.prefixedstring; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolEncoderAdapter; import org.apache.mina.filter.codec.ProtocolEncoderOutput; import org.apache.mina.filter.codec.ProtocolEncoder; import java.nio.charset.Charset; /** * A {@link ProtocolEncoder} which encodes a string * using a fixed-length length prefix. * * @author Apache MINA Project */ public class PrefixedStringEncoder extends ProtocolEncoderAdapter { public final static int DEFAULT_PREFIX_LENGTH = 4; public final static int DEFAULT_MAX_DATA_LENGTH = 2048; private final Charset charset; private int prefixLength = DEFAULT_PREFIX_LENGTH; private int maxDataLength = DEFAULT_MAX_DATA_LENGTH; public PrefixedStringEncoder(Charset charset, int prefixLength, int maxDataLength) { this.charset = charset; this.prefixLength = prefixLength; this.maxDataLength = maxDataLength; } public PrefixedStringEncoder(Charset charset, int prefixLength) { this(charset, prefixLength, DEFAULT_MAX_DATA_LENGTH); } public PrefixedStringEncoder(Charset charset) { this(charset, DEFAULT_PREFIX_LENGTH); } public PrefixedStringEncoder() { this(Charset.defaultCharset()); } /** * Sets the number of bytes used by the length prefix * * @param prefixLength the length of the length prefix (1, 2, or 4) */ public void setPrefixLength(int prefixLength) { if (prefixLength != 1 && prefixLength != 2 && prefixLength != 4) { throw new IllegalArgumentException("prefixLength: " + prefixLength); } this.prefixLength = prefixLength; } /** * Gets the length of the length prefix (1, 2, or 4) * * @return length of the length prefix */ public int getPrefixLength() { return prefixLength; } /** * Sets the maximum number of bytes allowed for encoding a single String * (including the prefix) *

* The encoder will throw a {@link IllegalArgumentException} when more bytes * are needed to encode a String value. * The default value is {@link PrefixedStringEncoder#DEFAULT_MAX_DATA_LENGTH}. *

* * @param maxDataLength maximum number of bytes allowed for encoding a single String */ public void setMaxDataLength(int maxDataLength) { this.maxDataLength = maxDataLength; } /** * Gets the maximum number of bytes allowed for encoding a single String * * * @return maximum number of bytes allowed for encoding a single String (prefix included) */ public int getMaxDataLength() { return maxDataLength; } public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { String value = (String) message; IoBuffer buffer = IoBuffer.allocate(value.length()).setAutoExpand(true); buffer.putPrefixedString(value, prefixLength, charset.newEncoder()); if (buffer.position() > maxDataLength) { throw new IllegalArgumentException("Data length: " + buffer.position()); } buffer.flip(); out.write(buffer); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/0000755000175000017500000000000012162575507026544 5ustar ebourgebourg././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoderResult.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoderResult0000644000175000017500000000437012032276025032531 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.demux; /** * Represents results from {@link MessageDecoder}. * * @author Apache MINA Project * * @see MessageDecoder */ public class MessageDecoderResult { /** * Represents a result from {@link MessageDecoder#decodable(IoSession, IoBuffer)} * and {@link MessageDecoder#decode(IoSession, IoBuffer, ProtocolDecoderOutput)}. * Please refer to each method's documentation for detailed explanation. */ public static MessageDecoderResult OK = new MessageDecoderResult("OK"); /** * Represents a result from {@link MessageDecoder#decodable(IoSession, IoBuffer)} * and {@link MessageDecoder#decode(IoSession, IoBuffer, ProtocolDecoderOutput)}. * Please refer to each method's documentation for detailed explanation. */ public static MessageDecoderResult NEED_DATA = new MessageDecoderResult("NEED_DATA"); /** * Represents a result from {@link MessageDecoder#decodable(IoSession, IoBuffer)} * and {@link MessageDecoder#decode(IoSession, IoBuffer, ProtocolDecoderOutput)}. * Please refer to each method's documentation for detailed explanation. */ public static MessageDecoderResult NOT_OK = new MessageDecoderResult("NOT_OK"); private final String name; private MessageDecoderResult(String name) { this.name = name; } @Override public String toString() { return name; } }././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolEncoder.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolEnco0000644000175000017500000002340712032276025032571 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.demux; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.UnknownMessageTypeException; import org.apache.mina.filter.codec.ProtocolEncoder; import org.apache.mina.filter.codec.ProtocolEncoderOutput; import org.apache.mina.util.CopyOnWriteMap; import org.apache.mina.util.IdentityHashSet; /** * A composite {@link ProtocolEncoder} that demultiplexes incoming message * encoding requests into an appropriate {@link MessageEncoder}. * *

Disposing resources acquired by {@link MessageEncoder}

*

* Override {@link #dispose(IoSession)} method. Please don't forget to call * super.dispose(). * * @author Apache MINA Project * * @see MessageEncoderFactory * @see MessageEncoder */ public class DemuxingProtocolEncoder implements ProtocolEncoder { private final AttributeKey STATE = new AttributeKey(getClass(), "state"); @SuppressWarnings("rawtypes") private final Map, MessageEncoderFactory> type2encoderFactory = new CopyOnWriteMap, MessageEncoderFactory>(); private static final Class[] EMPTY_PARAMS = new Class[0]; public DemuxingProtocolEncoder() { // Do nothing } @SuppressWarnings({ "rawtypes", "unchecked" }) public void addMessageEncoder(Class messageType, Class encoderClass) { if (encoderClass == null) { throw new IllegalArgumentException("encoderClass"); } try { encoderClass.getConstructor(EMPTY_PARAMS); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("The specified class doesn't have a public default constructor."); } boolean registered = false; if (MessageEncoder.class.isAssignableFrom(encoderClass)) { addMessageEncoder(messageType, new DefaultConstructorMessageEncoderFactory(encoderClass)); registered = true; } if (!registered) { throw new IllegalArgumentException("Unregisterable type: " + encoderClass); } } @SuppressWarnings({ "unchecked", "rawtypes" }) public void addMessageEncoder(Class messageType, MessageEncoder encoder) { addMessageEncoder(messageType, new SingletonMessageEncoderFactory(encoder)); } public void addMessageEncoder(Class messageType, MessageEncoderFactory factory) { if (messageType == null) { throw new IllegalArgumentException("messageType"); } if (factory == null) { throw new IllegalArgumentException("factory"); } synchronized (type2encoderFactory) { if (type2encoderFactory.containsKey(messageType)) { throw new IllegalStateException("The specified message type (" + messageType.getName() + ") is registered already."); } type2encoderFactory.put(messageType, factory); } } @SuppressWarnings("rawtypes") public void addMessageEncoder(Iterable> messageTypes, Class encoderClass) { for (Class messageType : messageTypes) { addMessageEncoder(messageType, encoderClass); } } public void addMessageEncoder(Iterable> messageTypes, MessageEncoder encoder) { for (Class messageType : messageTypes) { addMessageEncoder(messageType, encoder); } } public void addMessageEncoder(Iterable> messageTypes, MessageEncoderFactory factory) { for (Class messageType : messageTypes) { addMessageEncoder(messageType, factory); } } /** * {@inheritDoc} */ public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { State state = getState(session); MessageEncoder encoder = findEncoder(state, message.getClass()); if (encoder != null) { encoder.encode(session, message, out); } else { throw new UnknownMessageTypeException("No message encoder found for message: " + message); } } protected MessageEncoder findEncoder(State state, Class type) { return findEncoder(state, type, null); } @SuppressWarnings("unchecked") private MessageEncoder findEncoder(State state, Class type, Set> triedClasses) { @SuppressWarnings("rawtypes") MessageEncoder encoder = null; if (triedClasses != null && triedClasses.contains(type)) { return null; } /* * Try the cache first. */ encoder = state.findEncoderCache.get(type); if (encoder != null) { return encoder; } /* * Try the registered encoders for an immediate match. */ encoder = state.type2encoder.get(type); if (encoder == null) { /* * No immediate match could be found. Search the type's interfaces. */ if (triedClasses == null) { triedClasses = new IdentityHashSet>(); } triedClasses.add(type); Class[] interfaces = type.getInterfaces(); for (Class element : interfaces) { encoder = findEncoder(state, element, triedClasses); if (encoder != null) { break; } } } if (encoder == null) { /* * No match in type's interfaces could be found. Search the * superclass. */ Class superclass = type.getSuperclass(); if (superclass != null) { encoder = findEncoder(state, superclass); } } /* * Make sure the encoder is added to the cache. By updating the cache * here all the types (superclasses and interfaces) in the path which * led to a match will be cached along with the immediate message type. */ if (encoder != null) { state.findEncoderCache.put(type, encoder); MessageEncoder tmpEncoder = state.findEncoderCache.putIfAbsent(type, encoder); if (tmpEncoder != null) { encoder = tmpEncoder; } } return encoder; } /** * {@inheritDoc} */ public void dispose(IoSession session) throws Exception { session.removeAttribute(STATE); } private State getState(IoSession session) throws Exception { State state = (State) session.getAttribute(STATE); if (state == null) { state = new State(); State oldState = (State) session.setAttributeIfAbsent(STATE, state); if (oldState != null) { state = oldState; } } return state; } private class State { @SuppressWarnings("rawtypes") private final ConcurrentHashMap, MessageEncoder> findEncoderCache = new ConcurrentHashMap, MessageEncoder>(); @SuppressWarnings("rawtypes") private final Map, MessageEncoder> type2encoder = new ConcurrentHashMap, MessageEncoder>(); @SuppressWarnings("rawtypes") private State() throws Exception { for (Map.Entry, MessageEncoderFactory> e : type2encoderFactory.entrySet()) { type2encoder.put(e.getKey(), e.getValue().getEncoder()); } } } private static class SingletonMessageEncoderFactory implements MessageEncoderFactory { private final MessageEncoder encoder; private SingletonMessageEncoderFactory(MessageEncoder encoder) { if (encoder == null) { throw new IllegalArgumentException("encoder"); } this.encoder = encoder; } public MessageEncoder getEncoder() { return encoder; } } private static class DefaultConstructorMessageEncoderFactory implements MessageEncoderFactory { private final Class> encoderClass; private DefaultConstructorMessageEncoderFactory(Class> encoderClass) { if (encoderClass == null) { throw new IllegalArgumentException("encoderClass"); } if (!MessageEncoder.class.isAssignableFrom(encoderClass)) { throw new IllegalArgumentException("encoderClass is not assignable to MessageEncoder"); } this.encoderClass = encoderClass; } public MessageEncoder getEncoder() throws Exception { return encoderClass.newInstance(); } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/MessageEncoder.java0000644000175000017500000000365712032276025032273 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.demux; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolEncoderOutput; /** * Encodes a certain type of messages. *

* We didn't provide any dispose method for {@link MessageEncoder} * because it can give you performance penalty in case you have a lot of * message types to handle. * * @author Apache MINA Project * * @see DemuxingProtocolEncoder * @see MessageEncoderFactory */ public interface MessageEncoder { /** * Encodes higher-level message objects into binary or protocol-specific data. * MINA invokes {@link #encode(IoSession, Object, ProtocolEncoderOutput)} * method with message which is popped from the session write queue, and then * the encoder implementation puts encoded {@link IoBuffer}s into * {@link ProtocolEncoderOutput}. * * @throws Exception if the message violated protocol specification */ void encode(IoSession session, T message, ProtocolEncoderOutput out) throws Exception; } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/MessageEncoderFactory.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/MessageEncoderFactor0000644000175000017500000000226512032276025032504 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.demux; /** * A factory that creates a new instance of {@link MessageEncoder}. * * @author Apache MINA Project * * @see DemuxingProtocolEncoder */ public interface MessageEncoderFactory { /** * Creates a new message encoder. */ MessageEncoder getEncoder() throws Exception; } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoder.java0000644000175000017500000001026312032276025032250 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.demux; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * Decodes a certain type of messages. *

* We didn't provide any dispose method for {@link MessageDecoder} * because it can give you performance penalty in case you have a lot of * message types to handle. * * @author Apache MINA Project * * @see DemuxingProtocolDecoder * @see MessageDecoderFactory */ public interface MessageDecoder { /** * Represents a result from {@link #decodable(IoSession, IoBuffer)} and * {@link #decode(IoSession, IoBuffer, ProtocolDecoderOutput)}. Please * refer to each method's documentation for detailed explanation. */ static MessageDecoderResult OK = MessageDecoderResult.OK; /** * Represents a result from {@link #decodable(IoSession, IoBuffer)} and * {@link #decode(IoSession, IoBuffer, ProtocolDecoderOutput)}. Please * refer to each method's documentation for detailed explanation. */ static MessageDecoderResult NEED_DATA = MessageDecoderResult.NEED_DATA; /** * Represents a result from {@link #decodable(IoSession, IoBuffer)} and * {@link #decode(IoSession, IoBuffer, ProtocolDecoderOutput)}. Please * refer to each method's documentation for detailed explanation. */ static MessageDecoderResult NOT_OK = MessageDecoderResult.NOT_OK; /** * Checks the specified buffer is decodable by this decoder. * * @return {@link #OK} if this decoder can decode the specified buffer. * {@link #NOT_OK} if this decoder cannot decode the specified buffer. * {@link #NEED_DATA} if more data is required to determine if the * specified buffer is decodable ({@link #OK}) or not decodable * {@link #NOT_OK}. */ MessageDecoderResult decodable(IoSession session, IoBuffer in); /** * Decodes binary or protocol-specific content into higher-level message objects. * MINA invokes {@link #decode(IoSession, IoBuffer, ProtocolDecoderOutput)} * method with read data, and then the decoder implementation puts decoded * messages into {@link ProtocolDecoderOutput}. * * @return {@link #OK} if you finished decoding messages successfully. * {@link #NEED_DATA} if you need more data to finish decoding current message. * {@link #NOT_OK} if you cannot decode current message due to protocol specification violation. * * @throws Exception if the read data violated protocol specification */ MessageDecoderResult decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception; /** * Invoked when the specified session is closed while this decoder was * parsing the data. This method is useful when you deal with the protocol which doesn't * specify the length of a message such as HTTP response without content-length * header. Implement this method to process the remaining data that * {@link #decode(IoSession, IoBuffer, ProtocolDecoderOutput)} method didn't process * completely. * * @throws Exception if the read data violated protocol specification */ void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception; } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoderFactory.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoderFactor0000644000175000017500000000225712032276025032473 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.demux; /** * A factory that creates a new instance of {@link MessageDecoder}. * * @author Apache MINA Project * * @see DemuxingProtocolDecoder */ public interface MessageDecoderFactory { /** * Creates a new message decoder. */ MessageDecoder getDecoder() throws Exception; } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolDecoder.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolDeco0000644000175000017500000002510512032276025032554 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.demux; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.CumulativeProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoderException; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * A composite {@link ProtocolDecoder} that demultiplexes incoming {@link IoBuffer} * decoding requests into an appropriate {@link MessageDecoder}. * *

Internal mechanism of {@link MessageDecoder} selection

*

*

    *
  1. {@link DemuxingProtocolDecoder} iterates the list of candidate * {@link MessageDecoder}s and calls {@link MessageDecoder#decodable(IoSession, IoBuffer)}. * Initially, all registered {@link MessageDecoder}s are candidates.
  2. *
  3. If {@link MessageDecoderResult#NOT_OK} is returned, it is removed from the candidate * list.
  4. *
  5. If {@link MessageDecoderResult#NEED_DATA} is returned, it is retained in the candidate * list, and its {@link MessageDecoder#decodable(IoSession, IoBuffer)} will be invoked * again when more data is received.
  6. *
  7. If {@link MessageDecoderResult#OK} is returned, {@link DemuxingProtocolDecoder} * found the right {@link MessageDecoder}.
  8. *
  9. If there's no candidate left, an exception is raised. Otherwise, * {@link DemuxingProtocolDecoder} will keep iterating the candidate list. *
* * Please note that any change of position and limit of the specified {@link IoBuffer} * in {@link MessageDecoder#decodable(IoSession, IoBuffer)} will be reverted back to its * original value. *

* Once a {@link MessageDecoder} is selected, {@link DemuxingProtocolDecoder} calls * {@link MessageDecoder#decode(IoSession, IoBuffer, ProtocolDecoderOutput)} continuously * reading its return value: *

    *
  • {@link MessageDecoderResult#NOT_OK} - protocol violation; {@link ProtocolDecoderException} * is raised automatically.
  • *
  • {@link MessageDecoderResult#NEED_DATA} - needs more data to read the whole message; * {@link MessageDecoder#decode(IoSession, IoBuffer, ProtocolDecoderOutput)} * will be invoked again when more data is received.
  • *
  • {@link MessageDecoderResult#OK} - successfully decoded a message; the candidate list will * be reset and the selection process will start over.
  • *
* * @author Apache MINA Project * * @see MessageDecoderFactory * @see MessageDecoder */ public class DemuxingProtocolDecoder extends CumulativeProtocolDecoder { private final AttributeKey STATE = new AttributeKey(getClass(), "state"); private MessageDecoderFactory[] decoderFactories = new MessageDecoderFactory[0]; private static final Class[] EMPTY_PARAMS = new Class[0]; public DemuxingProtocolDecoder() { // Do nothing } public void addMessageDecoder(Class decoderClass) { if (decoderClass == null) { throw new IllegalArgumentException("decoderClass"); } try { decoderClass.getConstructor(EMPTY_PARAMS); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("The specified class doesn't have a public default constructor."); } boolean registered = false; if (MessageDecoder.class.isAssignableFrom(decoderClass)) { addMessageDecoder(new DefaultConstructorMessageDecoderFactory(decoderClass)); registered = true; } if (!registered) { throw new IllegalArgumentException("Unregisterable type: " + decoderClass); } } public void addMessageDecoder(MessageDecoder decoder) { addMessageDecoder(new SingletonMessageDecoderFactory(decoder)); } public void addMessageDecoder(MessageDecoderFactory factory) { if (factory == null) { throw new IllegalArgumentException("factory"); } MessageDecoderFactory[] decoderFactories = this.decoderFactories; MessageDecoderFactory[] newDecoderFactories = new MessageDecoderFactory[decoderFactories.length + 1]; System.arraycopy(decoderFactories, 0, newDecoderFactories, 0, decoderFactories.length); newDecoderFactories[decoderFactories.length] = factory; this.decoderFactories = newDecoderFactories; } /** * {@inheritDoc} */ @Override protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { State state = getState(session); if (state.currentDecoder == null) { MessageDecoder[] decoders = state.decoders; int undecodables = 0; for (int i = decoders.length - 1; i >= 0; i--) { MessageDecoder decoder = decoders[i]; int limit = in.limit(); int pos = in.position(); MessageDecoderResult result; try { result = decoder.decodable(session, in); } finally { in.position(pos); in.limit(limit); } if (result == MessageDecoder.OK) { state.currentDecoder = decoder; break; } else if (result == MessageDecoder.NOT_OK) { undecodables++; } else if (result != MessageDecoder.NEED_DATA) { throw new IllegalStateException("Unexpected decode result (see your decodable()): " + result); } } if (undecodables == decoders.length) { // Throw an exception if all decoders cannot decode data. String dump = in.getHexDump(); in.position(in.limit()); // Skip data ProtocolDecoderException e = new ProtocolDecoderException("No appropriate message decoder: " + dump); e.setHexdump(dump); throw e; } if (state.currentDecoder == null) { // Decoder is not determined yet (i.e. we need more data) return false; } } try { MessageDecoderResult result = state.currentDecoder.decode(session, in, out); if (result == MessageDecoder.OK) { state.currentDecoder = null; return true; } else if (result == MessageDecoder.NEED_DATA) { return false; } else if (result == MessageDecoder.NOT_OK) { state.currentDecoder = null; throw new ProtocolDecoderException("Message decoder returned NOT_OK."); } else { state.currentDecoder = null; throw new IllegalStateException("Unexpected decode result (see your decode()): " + result); } } catch (Exception e) { state.currentDecoder = null; throw e; } } /** * {@inheritDoc} */ @Override public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception { super.finishDecode(session, out); State state = getState(session); MessageDecoder currentDecoder = state.currentDecoder; if (currentDecoder == null) { return; } currentDecoder.finishDecode(session, out); } /** * {@inheritDoc} */ @Override public void dispose(IoSession session) throws Exception { super.dispose(session); session.removeAttribute(STATE); } private State getState(IoSession session) throws Exception { State state = (State) session.getAttribute(STATE); if (state == null) { state = new State(); State oldState = (State) session.setAttributeIfAbsent(STATE, state); if (oldState != null) { state = oldState; } } return state; } private class State { private final MessageDecoder[] decoders; private MessageDecoder currentDecoder; private State() throws Exception { MessageDecoderFactory[] decoderFactories = DemuxingProtocolDecoder.this.decoderFactories; decoders = new MessageDecoder[decoderFactories.length]; for (int i = decoderFactories.length - 1; i >= 0; i--) { decoders[i] = decoderFactories[i].getDecoder(); } } } private static class SingletonMessageDecoderFactory implements MessageDecoderFactory { private final MessageDecoder decoder; private SingletonMessageDecoderFactory(MessageDecoder decoder) { if (decoder == null) { throw new IllegalArgumentException("decoder"); } this.decoder = decoder; } public MessageDecoder getDecoder() { return decoder; } } private static class DefaultConstructorMessageDecoderFactory implements MessageDecoderFactory { private final Class decoderClass; private DefaultConstructorMessageDecoderFactory(Class decoderClass) { if (decoderClass == null) { throw new IllegalArgumentException("decoderClass"); } if (!MessageDecoder.class.isAssignableFrom(decoderClass)) { throw new IllegalArgumentException("decoderClass is not assignable to MessageDecoder"); } this.decoderClass = decoderClass; } public MessageDecoder getDecoder() throws Exception { return (MessageDecoder) decoderClass.newInstance(); } } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolCodecFactory.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolCode0000644000175000017500000000737312032276025032563 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.demux; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFactory; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolEncoder; /** * A convenience {@link ProtocolCodecFactory} that provides {@link DemuxingProtocolEncoder} * and {@link DemuxingProtocolDecoder} as a pair. *

* {@link DemuxingProtocolEncoder} and {@link DemuxingProtocolDecoder} demultiplex * incoming messages and buffers to appropriate {@link MessageEncoder}s and * {@link MessageDecoder}s. * * @author Apache MINA Project */ public class DemuxingProtocolCodecFactory implements ProtocolCodecFactory { private final DemuxingProtocolEncoder encoder = new DemuxingProtocolEncoder(); private final DemuxingProtocolDecoder decoder = new DemuxingProtocolDecoder(); public DemuxingProtocolCodecFactory() { // Do nothing } /** * {@inheritDoc} */ public ProtocolEncoder getEncoder(IoSession session) throws Exception { return encoder; } /** * {@inheritDoc} */ public ProtocolDecoder getDecoder(IoSession session) throws Exception { return decoder; } @SuppressWarnings("unchecked") public void addMessageEncoder(Class messageType, Class encoderClass) { this.encoder.addMessageEncoder(messageType, encoderClass); } public void addMessageEncoder(Class messageType, MessageEncoder encoder) { this.encoder.addMessageEncoder(messageType, encoder); } public void addMessageEncoder(Class messageType, MessageEncoderFactory factory) { this.encoder.addMessageEncoder(messageType, factory); } @SuppressWarnings("unchecked") public void addMessageEncoder(Iterable> messageTypes, Class encoderClass) { for (Class messageType : messageTypes) { addMessageEncoder(messageType, encoderClass); } } public void addMessageEncoder(Iterable> messageTypes, MessageEncoder encoder) { for (Class messageType : messageTypes) { addMessageEncoder(messageType, encoder); } } public void addMessageEncoder(Iterable> messageTypes, MessageEncoderFactory factory) { for (Class messageType : messageTypes) { addMessageEncoder(messageType, factory); } } public void addMessageDecoder(Class decoderClass) { this.decoder.addMessageDecoder(decoderClass); } public void addMessageDecoder(MessageDecoder decoder) { this.decoder.addMessageDecoder(decoder); } public void addMessageDecoder(MessageDecoderFactory factory) { this.decoder.addMessageDecoder(factory); } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoderAdapter.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoderAdapte0000644000175000017500000000302312032276025032443 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.demux; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * An abstract {@link MessageDecoder} implementation for those who don't need to * implement {@link MessageDecoder#finishDecode(IoSession, ProtocolDecoderOutput)} * method. * * @author Apache MINA Project */ public abstract class MessageDecoderAdapter implements MessageDecoder { /** * Override this method to deal with the closed connection. * The default implementation does nothing. */ public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception { // Do nothing } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/demux/package.html0000644000175000017500000000174512032276025031021 0ustar ebourgebourg Protocol codecs that helps you to implement even more complex protocols by splitting a codec into multiple sub-codecs. ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolDecoderException.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolDecoderException.j0000644000175000017500000000535212032276025032535 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import org.apache.mina.core.buffer.IoBuffer; /** * An exception that is thrown when {@link ProtocolDecoder} * cannot understand or failed to validate the specified {@link IoBuffer} * content. * * @author Apache MINA Project */ public class ProtocolDecoderException extends ProtocolCodecException { private static final long serialVersionUID = 3545799879533408565L; private String hexdump; /** * Constructs a new instance. */ public ProtocolDecoderException() { // Do nothing } /** * Constructs a new instance with the specified message. */ public ProtocolDecoderException(String message) { super(message); } /** * Constructs a new instance with the specified cause. */ public ProtocolDecoderException(Throwable cause) { super(cause); } /** * Constructs a new instance with the specified message and the specified * cause. */ public ProtocolDecoderException(String message, Throwable cause) { super(message, cause); } /** * Returns the message and the hexdump of the unknown part. */ @Override public String getMessage() { String message = super.getMessage(); if (message == null) { message = ""; } if (hexdump != null) { return message + (message.length() > 0 ? " " : "") + "(Hexdump: " + hexdump + ')'; } return message; } /** * Returns the hexdump of the unknown message part. */ public String getHexdump() { return hexdump; } /** * Sets the hexdump of the unknown message part. */ public void setHexdump(String hexdump) { if (this.hexdump != null) { throw new IllegalStateException("Hexdump cannot be set more than once."); } this.hexdump = hexdump; } }././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/AbstractProtocolEncoderOutput.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/AbstractProtocolEncoderOut0000644000175000017500000000543012032276025032611 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import org.apache.mina.core.buffer.IoBuffer; /** * A {@link ProtocolEncoderOutput} based on queue. * * @author Apache MINA Project */ public abstract class AbstractProtocolEncoderOutput implements ProtocolEncoderOutput { private final Queue messageQueue = new ConcurrentLinkedQueue(); private boolean buffersOnly = true; public AbstractProtocolEncoderOutput() { // Do nothing } public Queue getMessageQueue() { return messageQueue; } public void write(Object encodedMessage) { if (encodedMessage instanceof IoBuffer) { IoBuffer buf = (IoBuffer) encodedMessage; if (buf.hasRemaining()) { messageQueue.offer(buf); } else { throw new IllegalArgumentException("buf is empty. Forgot to call flip()?"); } } else { messageQueue.offer(encodedMessage); buffersOnly = false; } } public void mergeAll() { if (!buffersOnly) { throw new IllegalStateException("the encoded message list contains a non-buffer."); } final int size = messageQueue.size(); if (size < 2) { // no need to merge! return; } // Get the size of merged BB int sum = 0; for (Object b : messageQueue) { sum += ((IoBuffer) b).remaining(); } // Allocate a new BB that will contain all fragments IoBuffer newBuf = IoBuffer.allocate(sum); // and merge all. for (;;) { IoBuffer buf = (IoBuffer) messageQueue.poll(); if (buf == null) { break; } newBuf.put(buf); } // Push the new buffer finally. newBuf.flip(); messageQueue.add(newBuf); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolCodecFilter.java0000644000175000017500000004672212032276025032172 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import java.net.SocketAddress; import java.util.Queue; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.file.FileRegion; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.future.DefaultWriteFuture; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.DefaultWriteRequest; import org.apache.mina.core.write.NothingWrittenException; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.core.write.WriteRequestWrapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An {@link IoFilter} which translates binary or protocol specific data into * message objects and vice versa using {@link ProtocolCodecFactory}, * {@link ProtocolEncoder}, or {@link ProtocolDecoder}. * * @author Apache MINA Project * @org.apache.xbean.XBean */ public class ProtocolCodecFilter extends IoFilterAdapter { /** A logger for this class */ private static final Logger LOGGER = LoggerFactory.getLogger(ProtocolCodecFilter.class); private static final Class[] EMPTY_PARAMS = new Class[0]; private static final IoBuffer EMPTY_BUFFER = IoBuffer.wrap(new byte[0]); private final AttributeKey ENCODER = new AttributeKey(ProtocolCodecFilter.class, "encoder"); private final AttributeKey DECODER = new AttributeKey(ProtocolCodecFilter.class, "decoder"); private final AttributeKey DECODER_OUT = new AttributeKey(ProtocolCodecFilter.class, "decoderOut"); private final AttributeKey ENCODER_OUT = new AttributeKey(ProtocolCodecFilter.class, "encoderOut"); /** The factory responsible for creating the encoder and decoder */ private final ProtocolCodecFactory factory; /** * * Creates a new instance of ProtocolCodecFilter, associating a factory * for the creation of the encoder and decoder. * * @param factory The associated factory */ public ProtocolCodecFilter(ProtocolCodecFactory factory) { if (factory == null) { throw new IllegalArgumentException("factory"); } this.factory = factory; } /** * Creates a new instance of ProtocolCodecFilter, without any factory. * The encoder/decoder factory will be created as an inner class, using * the two parameters (encoder and decoder). * * @param encoder The class responsible for encoding the message * @param decoder The class responsible for decoding the message */ public ProtocolCodecFilter(final ProtocolEncoder encoder, final ProtocolDecoder decoder) { if (encoder == null) { throw new IllegalArgumentException("encoder"); } if (decoder == null) { throw new IllegalArgumentException("decoder"); } // Create the inner Factory based on the two parameters this.factory = new ProtocolCodecFactory() { public ProtocolEncoder getEncoder(IoSession session) { return encoder; } public ProtocolDecoder getDecoder(IoSession session) { return decoder; } }; } /** * Creates a new instance of ProtocolCodecFilter, without any factory. * The encoder/decoder factory will be created as an inner class, using * the two parameters (encoder and decoder), which are class names. Instances * for those classes will be created in this constructor. * * @param encoder The class responsible for encoding the message * @param decoder The class responsible for decoding the message */ public ProtocolCodecFilter(final Class encoderClass, final Class decoderClass) { if (encoderClass == null) { throw new IllegalArgumentException("encoderClass"); } if (decoderClass == null) { throw new IllegalArgumentException("decoderClass"); } if (!ProtocolEncoder.class.isAssignableFrom(encoderClass)) { throw new IllegalArgumentException("encoderClass: " + encoderClass.getName()); } if (!ProtocolDecoder.class.isAssignableFrom(decoderClass)) { throw new IllegalArgumentException("decoderClass: " + decoderClass.getName()); } try { encoderClass.getConstructor(EMPTY_PARAMS); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("encoderClass doesn't have a public default constructor."); } try { decoderClass.getConstructor(EMPTY_PARAMS); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("decoderClass doesn't have a public default constructor."); } final ProtocolEncoder encoder; try { encoder = encoderClass.newInstance(); } catch (Exception e) { throw new IllegalArgumentException("encoderClass cannot be initialized"); } final ProtocolDecoder decoder; try { decoder = decoderClass.newInstance(); } catch (Exception e) { throw new IllegalArgumentException("decoderClass cannot be initialized"); } // Create the inner factory based on the two parameters. this.factory = new ProtocolCodecFactory() { public ProtocolEncoder getEncoder(IoSession session) throws Exception { return encoder; } public ProtocolDecoder getDecoder(IoSession session) throws Exception { return decoder; } }; } /** * Get the encoder instance from a given session. * * @param session The associated session we will get the encoder from * @return The encoder instance, if any */ public ProtocolEncoder getEncoder(IoSession session) { return (ProtocolEncoder) session.getAttribute(ENCODER); } @Override public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { if (parent.contains(this)) { throw new IllegalArgumentException( "You can't add the same filter instance more than once. Create another instance and add it."); } } @Override public void onPostRemove(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { // Clean everything disposeCodec(parent.getSession()); } /** * Process the incoming message, calling the session decoder. As the incoming * buffer might contains more than one messages, we have to loop until the decoder * throws an exception. * * while ( buffer not empty ) * try * decode ( buffer ) * catch * break; * */ @Override public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception { LOGGER.debug("Processing a MESSAGE_RECEIVED for session {}", session.getId()); if (!(message instanceof IoBuffer)) { nextFilter.messageReceived(session, message); return; } IoBuffer in = (IoBuffer) message; ProtocolDecoder decoder = factory.getDecoder(session); ProtocolDecoderOutput decoderOut = getDecoderOut(session, nextFilter); // Loop until we don't have anymore byte in the buffer, // or until the decoder throws an unrecoverable exception or // can't decoder a message, because there are not enough // data in the buffer while (in.hasRemaining()) { int oldPos = in.position(); try { synchronized (decoderOut) { // Call the decoder with the read bytes decoder.decode(session, in, decoderOut); } // Finish decoding if no exception was thrown. decoderOut.flush(nextFilter, session); } catch (Throwable t) { ProtocolDecoderException pde; if (t instanceof ProtocolDecoderException) { pde = (ProtocolDecoderException) t; } else { pde = new ProtocolDecoderException(t); } if (pde.getHexdump() == null) { // Generate a message hex dump int curPos = in.position(); in.position(oldPos); pde.setHexdump(in.getHexDump()); in.position(curPos); } // Fire the exceptionCaught event. decoderOut.flush(nextFilter, session); nextFilter.exceptionCaught(session, pde); // Retry only if the type of the caught exception is // recoverable and the buffer position has changed. // We check buffer position additionally to prevent an // infinite loop. if (!(t instanceof RecoverableProtocolDecoderException) || (in.position() == oldPos)) { break; } } } } @Override public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { if (writeRequest instanceof EncodedWriteRequest) { return; } if (writeRequest instanceof MessageWriteRequest) { MessageWriteRequest wrappedRequest = (MessageWriteRequest) writeRequest; nextFilter.messageSent(session, wrappedRequest.getParentRequest()); } else { nextFilter.messageSent(session, writeRequest); } } @Override public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { Object message = writeRequest.getMessage(); // Bypass the encoding if the message is contained in a IoBuffer, // as it has already been encoded before if ((message instanceof IoBuffer) || (message instanceof FileRegion)) { nextFilter.filterWrite(session, writeRequest); return; } // Get the encoder in the session ProtocolEncoder encoder = factory.getEncoder(session); ProtocolEncoderOutput encoderOut = getEncoderOut(session, nextFilter, writeRequest); if (encoder == null) { throw new ProtocolEncoderException("The encoder is null for the session " + session); } if (encoderOut == null) { throw new ProtocolEncoderException("The encoderOut is null for the session " + session); } try { // Now we can try to encode the response encoder.encode(session, message, encoderOut); // Send it directly Queue bufferQueue = ((AbstractProtocolEncoderOutput) encoderOut).getMessageQueue(); // Write all the encoded messages now while (!bufferQueue.isEmpty()) { Object encodedMessage = bufferQueue.poll(); if (encodedMessage == null) { break; } // Flush only when the buffer has remaining. if (!(encodedMessage instanceof IoBuffer) || ((IoBuffer) encodedMessage).hasRemaining()) { SocketAddress destination = writeRequest.getDestination(); WriteRequest encodedWriteRequest = new EncodedWriteRequest(encodedMessage, null, destination); nextFilter.filterWrite(session, encodedWriteRequest); } } // Call the next filter nextFilter.filterWrite(session, new MessageWriteRequest(writeRequest)); } catch (Throwable t) { ProtocolEncoderException pee; // Generate the correct exception if (t instanceof ProtocolEncoderException) { pee = (ProtocolEncoderException) t; } else { pee = new ProtocolEncoderException(t); } throw pee; } } @Override public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception { // Call finishDecode() first when a connection is closed. ProtocolDecoder decoder = factory.getDecoder(session); ProtocolDecoderOutput decoderOut = getDecoderOut(session, nextFilter); try { decoder.finishDecode(session, decoderOut); } catch (Throwable t) { ProtocolDecoderException pde; if (t instanceof ProtocolDecoderException) { pde = (ProtocolDecoderException) t; } else { pde = new ProtocolDecoderException(t); } throw pde; } finally { // Dispose everything disposeCodec(session); decoderOut.flush(nextFilter, session); } // Call the next filter nextFilter.sessionClosed(session); } private static class EncodedWriteRequest extends DefaultWriteRequest { public EncodedWriteRequest(Object encodedMessage, WriteFuture future, SocketAddress destination) { super(encodedMessage, future, destination); } public boolean isEncoded() { return true; } } private static class MessageWriteRequest extends WriteRequestWrapper { public MessageWriteRequest(WriteRequest writeRequest) { super(writeRequest); } @Override public Object getMessage() { return EMPTY_BUFFER; } @Override public String toString() { return "MessageWriteRequest, parent : " + super.toString(); } } private static class ProtocolDecoderOutputImpl extends AbstractProtocolDecoderOutput { public ProtocolDecoderOutputImpl() { // Do nothing } public void flush(NextFilter nextFilter, IoSession session) { Queue messageQueue = getMessageQueue(); while (!messageQueue.isEmpty()) { nextFilter.messageReceived(session, messageQueue.poll()); } } } private static class ProtocolEncoderOutputImpl extends AbstractProtocolEncoderOutput { private final IoSession session; private final NextFilter nextFilter; /** The WriteRequest destination */ private final SocketAddress destination; public ProtocolEncoderOutputImpl(IoSession session, NextFilter nextFilter, WriteRequest writeRequest) { this.session = session; this.nextFilter = nextFilter; // Only store the destination, not the full WriteRequest. destination = writeRequest.getDestination(); } public WriteFuture flush() { Queue bufferQueue = getMessageQueue(); WriteFuture future = null; while (!bufferQueue.isEmpty()) { Object encodedMessage = bufferQueue.poll(); if (encodedMessage == null) { break; } // Flush only when the buffer has remaining. if (!(encodedMessage instanceof IoBuffer) || ((IoBuffer) encodedMessage).hasRemaining()) { future = new DefaultWriteFuture(session); nextFilter.filterWrite(session, new EncodedWriteRequest(encodedMessage, future, destination)); } } if (future == null) { // Creates an empty writeRequest containing the destination WriteRequest writeRequest = new DefaultWriteRequest(null, null, destination); future = DefaultWriteFuture.newNotWrittenFuture(session, new NothingWrittenException(writeRequest)); } return future; } } //----------- Helper methods --------------------------------------------- /** * Dispose the encoder, decoder, and the callback for the decoded * messages. */ private void disposeCodec(IoSession session) { // We just remove the two instances of encoder/decoder to release resources // from the session disposeEncoder(session); disposeDecoder(session); // We also remove the callback disposeDecoderOut(session); } /** * Dispose the encoder, removing its instance from the * session's attributes, and calling the associated * dispose method. */ private void disposeEncoder(IoSession session) { ProtocolEncoder encoder = (ProtocolEncoder) session.removeAttribute(ENCODER); if (encoder == null) { return; } try { encoder.dispose(session); } catch (Throwable t) { LOGGER.warn("Failed to dispose: " + encoder.getClass().getName() + " (" + encoder + ')'); } } /** * Dispose the decoder, removing its instance from the * session's attributes, and calling the associated * dispose method. */ private void disposeDecoder(IoSession session) { ProtocolDecoder decoder = (ProtocolDecoder) session.removeAttribute(DECODER); if (decoder == null) { return; } try { decoder.dispose(session); } catch (Throwable t) { LOGGER.warn("Failed to dispose: " + decoder.getClass().getName() + " (" + decoder + ')'); } } /** * Return a reference to the decoder callback. If it's not already created * and stored into the session, we create a new instance. */ private ProtocolDecoderOutput getDecoderOut(IoSession session, NextFilter nextFilter) { ProtocolDecoderOutput out = (ProtocolDecoderOutput) session.getAttribute(DECODER_OUT); if (out == null) { // Create a new instance, and stores it into the session out = new ProtocolDecoderOutputImpl(); session.setAttribute(DECODER_OUT, out); } return out; } private ProtocolEncoderOutput getEncoderOut(IoSession session, NextFilter nextFilter, WriteRequest writeRequest) { ProtocolEncoderOutput out = (ProtocolEncoderOutput) session.getAttribute(ENCODER_OUT); if (out == null) { // Create a new instance, and stores it into the session out = new ProtocolEncoderOutputImpl(session, nextFilter, writeRequest); session.setAttribute(ENCODER_OUT, out); } return out; } /** * Remove the decoder callback from the session's attributes. */ private void disposeDecoderOut(IoSession session) { session.removeAttribute(DECODER_OUT); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolDecoderAdapter.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolDecoderAdapter.jav0000644000175000017500000000334412032276025032505 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import org.apache.mina.core.session.IoSession; /** * An abstract {@link ProtocolDecoder} implementation for those who don't need * {@link ProtocolDecoder#finishDecode(IoSession, ProtocolDecoderOutput)} nor * {@link ProtocolDecoder#dispose(IoSession)} method. * * @author Apache MINA Project */ public abstract class ProtocolDecoderAdapter implements ProtocolDecoder { /** * Override this method to deal with the closed connection. * The default implementation does nothing. */ public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception { // Do nothing } /** * Override this method to dispose all resources related with this decoder. * The default implementation does nothing. */ public void dispose(IoSession session) throws Exception { // Do nothing } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/SynchronizedProtocolDecoder.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/SynchronizedProtocolDecode0000644000175000017500000000505612032276025032645 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; /** * A {@link ProtocolDecoder} implementation which decorates an existing decoder * to be thread-safe. Please be careful if you're going to use this decorator * because it can be a root of performance degradation in a multi-thread * environment. Also, by default, appropriate synchronization is done * on a per-session basis by {@link ProtocolCodecFilter}. Please use this * decorator only when you need to synchronize on a per-decoder basis, which * is not common. * * @author Apache MINA Project */ public class SynchronizedProtocolDecoder implements ProtocolDecoder { private final ProtocolDecoder decoder; /** * Creates a new instance which decorates the specified decoder. */ public SynchronizedProtocolDecoder(ProtocolDecoder decoder) { if (decoder == null) { throw new IllegalArgumentException("decoder"); } this.decoder = decoder; } /** * Returns the decoder this decoder is decorating. */ public ProtocolDecoder getDecoder() { return decoder; } public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { synchronized (decoder) { decoder.decode(session, in, out); } } public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception { synchronized (decoder) { decoder.finishDecode(session, out); } } public void dispose(IoSession session) throws Exception { synchronized (decoder) { decoder.dispose(session); } } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolEncoderException.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolEncoderException.j0000644000175000017500000000352412032276025032546 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; /** * An exception that is thrown when {@link ProtocolEncoder} * cannot understand or failed to validate the specified message object. * * @author Apache MINA Project */ public class ProtocolEncoderException extends ProtocolCodecException { private static final long serialVersionUID = 8752989973624459604L; /** * Constructs a new instance. */ public ProtocolEncoderException() { // Do nothing } /** * Constructs a new instance with the specified message. */ public ProtocolEncoderException(String message) { super(message); } /** * Constructs a new instance with the specified cause. */ public ProtocolEncoderException(Throwable cause) { super(cause); } /** * Constructs a new instance with the specified message and the specified * cause. */ public ProtocolEncoderException(String message, Throwable cause) { super(message, cause); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/textline/0000755000175000017500000000000012162575507027256 5ustar ebourgebourg././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/textline/TextLineCodecFactory.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/textline/TextLineCodecFact0000644000175000017500000001266712032276025032472 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.textline; import java.nio.charset.Charset; import org.apache.mina.core.buffer.BufferDataException; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFactory; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolEncoder; /** * A {@link ProtocolCodecFactory} that performs encoding and decoding between * a text line data and a Java string object. This codec is useful especially * when you work with a text-based protocols such as SMTP and IMAP. * * @author Apache MINA Project */ public class TextLineCodecFactory implements ProtocolCodecFactory { private final TextLineEncoder encoder; private final TextLineDecoder decoder; /** * Creates a new instance with the current default {@link Charset}. */ public TextLineCodecFactory() { this(Charset.defaultCharset()); } /** * Creates a new instance with the specified {@link Charset}. The * encoder uses a UNIX {@link LineDelimiter} and the decoder uses * the AUTO {@link LineDelimiter}. * * @param charset * The charset to use in the encoding and decoding */ public TextLineCodecFactory(Charset charset) { encoder = new TextLineEncoder(charset, LineDelimiter.UNIX); decoder = new TextLineDecoder(charset, LineDelimiter.AUTO); } /** * Creates a new instance of TextLineCodecFactory. This constructor * provides more flexibility for the developer. * * @param charset * The charset to use in the encoding and decoding * @param encodingDelimiter * The line delimeter for the encoder * @param decodingDelimiter * The line delimeter for the decoder */ public TextLineCodecFactory(Charset charset, String encodingDelimiter, String decodingDelimiter) { encoder = new TextLineEncoder(charset, encodingDelimiter); decoder = new TextLineDecoder(charset, decodingDelimiter); } /** * Creates a new instance of TextLineCodecFactory. This constructor * provides more flexibility for the developer. * * @param charset * The charset to use in the encoding and decoding * @param encodingDelimiter * The line delimeter for the encoder * @param decodingDelimiter * The line delimeter for the decoder */ public TextLineCodecFactory(Charset charset, LineDelimiter encodingDelimiter, LineDelimiter decodingDelimiter) { encoder = new TextLineEncoder(charset, encodingDelimiter); decoder = new TextLineDecoder(charset, decodingDelimiter); } public ProtocolEncoder getEncoder(IoSession session) { return encoder; } public ProtocolDecoder getDecoder(IoSession session) { return decoder; } /** * Returns the allowed maximum size of the encoded line. * If the size of the encoded line exceeds this value, the encoder * will throw a {@link IllegalArgumentException}. The default value * is {@link Integer#MAX_VALUE}. *

* This method does the same job with {@link TextLineEncoder#getMaxLineLength()}. */ public int getEncoderMaxLineLength() { return encoder.getMaxLineLength(); } /** * Sets the allowed maximum size of the encoded line. * If the size of the encoded line exceeds this value, the encoder * will throw a {@link IllegalArgumentException}. The default value * is {@link Integer#MAX_VALUE}. *

* This method does the same job with {@link TextLineEncoder#setMaxLineLength(int)}. */ public void setEncoderMaxLineLength(int maxLineLength) { encoder.setMaxLineLength(maxLineLength); } /** * Returns the allowed maximum size of the line to be decoded. * If the size of the line to be decoded exceeds this value, the * decoder will throw a {@link BufferDataException}. The default * value is 1024 (1KB). *

* This method does the same job with {@link TextLineDecoder#getMaxLineLength()}. */ public int getDecoderMaxLineLength() { return decoder.getMaxLineLength(); } /** * Sets the allowed maximum size of the line to be decoded. * If the size of the line to be decoded exceeds this value, the * decoder will throw a {@link BufferDataException}. The default * value is 1024 (1KB). *

* This method does the same job with {@link TextLineDecoder#setMaxLineLength(int)}. */ public void setDecoderMaxLineLength(int maxLineLength) { decoder.setMaxLineLength(maxLineLength); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/textline/LineDelimiter.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/textline/LineDelimiter.jav0000644000175000017500000001027312032276025032476 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.textline; import java.io.ByteArrayOutputStream; import java.io.PrintWriter; /** * A delimiter which is appended to the end of a text line, such as * CR/LF. This class defines default delimiters for various * OS : *

    *
  • Unix/Linux : LineDelimiter.UNIX ("\n")
  • *
  • Windows : LineDelimiter.WINDOWS ("\r\n")
  • *
  • MAC : LineDelimiter.MAC ("\r")
  • *
* * @author Apache MINA Project */ public class LineDelimiter { /** the line delimiter constant of the current O/S. */ public static final LineDelimiter DEFAULT; /** Compute the default delimiter on he current OS */ static { ByteArrayOutputStream bout = new ByteArrayOutputStream(); PrintWriter out = new PrintWriter(bout, true); out.println(); DEFAULT = new LineDelimiter(new String(bout.toByteArray())); } /** * A special line delimiter which is used for auto-detection of * EOL in {@link TextLineDecoder}. If this delimiter is used, * {@link TextLineDecoder} will consider both '\r' and * '\n' as a delimiter. */ public static final LineDelimiter AUTO = new LineDelimiter(""); /** * The CRLF line delimiter constant ("\r\n") */ public static final LineDelimiter CRLF = new LineDelimiter("\r\n"); /** * The line delimiter constant of UNIX ("\n") */ public static final LineDelimiter UNIX = new LineDelimiter("\n"); /** * The line delimiter constant of MS Windows/DOS ("\r\n") */ public static final LineDelimiter WINDOWS = CRLF; /** * The line delimiter constant of Mac OS ("\r") */ public static final LineDelimiter MAC = new LineDelimiter("\r"); /** * The line delimiter constant for NUL-terminated text protocols * such as Flash XML socket ("\0") */ public static final LineDelimiter NUL = new LineDelimiter("\0"); /** Stores the selected Line delimiter */ private final String value; /** * Creates a new line delimiter with the specified value. */ public LineDelimiter(String value) { if (value == null) { throw new IllegalArgumentException("delimiter"); } this.value = value; } /** * Return the delimiter string. */ public String getValue() { return value; } /** * {@inheritDoc} */ @Override public int hashCode() { return value.hashCode(); } /** * {@inheritDoc} */ @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof LineDelimiter)) { return false; } LineDelimiter that = (LineDelimiter) o; return this.value.equals(that.value); } /** * {@inheritDoc} */ @Override public String toString() { if (value.length() == 0) { return "delimiter: auto"; } else { StringBuilder buf = new StringBuilder(); buf.append("delimiter:"); for (int i = 0; i < value.length(); i++) { buf.append(" 0x"); buf.append(Integer.toHexString(value.charAt(i))); } return buf.toString(); } } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.j0000644000175000017500000003330412032276025032443 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.textline; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import org.apache.mina.core.buffer.BufferDataException; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoderException; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import org.apache.mina.filter.codec.RecoverableProtocolDecoderException; /** * A {@link ProtocolDecoder} which decodes a text line into a string. * * @author Apache MINA Project */ public class TextLineDecoder implements ProtocolDecoder { private final AttributeKey CONTEXT = new AttributeKey(getClass(), "context"); private final Charset charset; /** The delimiter used to determinate when a line has been fully decoded */ private final LineDelimiter delimiter; /** An IoBuffer containing the delimiter */ private IoBuffer delimBuf; /** The default maximum Line length. Default to 1024. */ private int maxLineLength = 1024; /** The default maximum buffer length. Default to 128 chars. */ private int bufferLength = 128; /** * Creates a new instance with the current default {@link Charset} * and {@link LineDelimiter#AUTO} delimiter. */ public TextLineDecoder() { this(LineDelimiter.AUTO); } /** * Creates a new instance with the current default {@link Charset} * and the specified delimiter. */ public TextLineDecoder(String delimiter) { this(new LineDelimiter(delimiter)); } /** * Creates a new instance with the current default {@link Charset} * and the specified delimiter. */ public TextLineDecoder(LineDelimiter delimiter) { this(Charset.defaultCharset(), delimiter); } /** * Creates a new instance with the spcified charset * and {@link LineDelimiter#AUTO} delimiter. */ public TextLineDecoder(Charset charset) { this(charset, LineDelimiter.AUTO); } /** * Creates a new instance with the spcified charset * and the specified delimiter. */ public TextLineDecoder(Charset charset, String delimiter) { this(charset, new LineDelimiter(delimiter)); } /** * Creates a new instance with the specified charset * and the specified delimiter. */ public TextLineDecoder(Charset charset, LineDelimiter delimiter) { if (charset == null) { throw new IllegalArgumentException("charset parameter shuld not be null"); } if (delimiter == null) { throw new IllegalArgumentException("delimiter parameter should not be null"); } this.charset = charset; this.delimiter = delimiter; // Convert delimiter to ByteBuffer if not done yet. if (delimBuf == null) { IoBuffer tmp = IoBuffer.allocate(2).setAutoExpand(true); try { tmp.putString(delimiter.getValue(), charset.newEncoder()); } catch (CharacterCodingException cce) { } tmp.flip(); delimBuf = tmp; } } /** * Returns the allowed maximum size of the line to be decoded. * If the size of the line to be decoded exceeds this value, the * decoder will throw a {@link BufferDataException}. The default * value is 1024 (1KB). */ public int getMaxLineLength() { return maxLineLength; } /** * Sets the allowed maximum size of the line to be decoded. * If the size of the line to be decoded exceeds this value, the * decoder will throw a {@link BufferDataException}. The default * value is 1024 (1KB). */ public void setMaxLineLength(int maxLineLength) { if (maxLineLength <= 0) { throw new IllegalArgumentException("maxLineLength (" + maxLineLength + ") should be a positive value"); } this.maxLineLength = maxLineLength; } /** * Sets the default buffer size. This buffer is used in the Context * to store the decoded line. * * @param bufferLength The default bufer size */ public void setBufferLength(int bufferLength) { if (bufferLength <= 0) { throw new IllegalArgumentException("bufferLength (" + maxLineLength + ") should be a positive value"); } this.bufferLength = bufferLength; } /** * Returns the allowed buffer size used to store the decoded line * in the Context instance. */ public int getBufferLength() { return bufferLength; } /** * {@inheritDoc} */ public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { Context ctx = getContext(session); if (LineDelimiter.AUTO.equals(delimiter)) { decodeAuto(ctx, session, in, out); } else { decodeNormal(ctx, session, in, out); } } /** * Return the context for this session */ private Context getContext(IoSession session) { Context ctx; ctx = (Context) session.getAttribute(CONTEXT); if (ctx == null) { ctx = new Context(bufferLength); session.setAttribute(CONTEXT, ctx); } return ctx; } /** * {@inheritDoc} */ public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception { // Do nothing } /** * {@inheritDoc} */ public void dispose(IoSession session) throws Exception { Context ctx = (Context) session.getAttribute(CONTEXT); if (ctx != null) { session.removeAttribute(CONTEXT); } } /** * Decode a line using the default delimiter on the current system */ private void decodeAuto(Context ctx, IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws CharacterCodingException, ProtocolDecoderException { int matchCount = ctx.getMatchCount(); // Try to find a match int oldPos = in.position(); int oldLimit = in.limit(); while (in.hasRemaining()) { byte b = in.get(); boolean matched = false; switch (b) { case '\r': // Might be Mac, but we don't auto-detect Mac EOL // to avoid confusion. matchCount++; break; case '\n': // UNIX matchCount++; matched = true; break; default: matchCount = 0; } if (matched) { // Found a match. int pos = in.position(); in.limit(pos); in.position(oldPos); ctx.append(in); in.limit(oldLimit); in.position(pos); if (ctx.getOverflowPosition() == 0) { IoBuffer buf = ctx.getBuffer(); buf.flip(); buf.limit(buf.limit() - matchCount); try { byte[] data = new byte[buf.limit()]; buf.get(data); CharsetDecoder decoder = ctx.getDecoder(); CharBuffer buffer = decoder.decode(ByteBuffer.wrap(data)); String str = new String(buffer.array()); writeText(session, str, out); } finally { buf.clear(); } } else { int overflowPosition = ctx.getOverflowPosition(); ctx.reset(); throw new RecoverableProtocolDecoderException("Line is too long: " + overflowPosition); } oldPos = pos; matchCount = 0; } } // Put remainder to buf. in.position(oldPos); ctx.append(in); ctx.setMatchCount(matchCount); } /** * Decode a line using the delimiter defined by the caller */ private void decodeNormal(Context ctx, IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws CharacterCodingException, ProtocolDecoderException { int matchCount = ctx.getMatchCount(); // Try to find a match int oldPos = in.position(); int oldLimit = in.limit(); while (in.hasRemaining()) { byte b = in.get(); if (delimBuf.get(matchCount) == b) { matchCount++; if (matchCount == delimBuf.limit()) { // Found a match. int pos = in.position(); in.limit(pos); in.position(oldPos); ctx.append(in); in.limit(oldLimit); in.position(pos); if (ctx.getOverflowPosition() == 0) { IoBuffer buf = ctx.getBuffer(); buf.flip(); buf.limit(buf.limit() - matchCount); try { writeText(session, buf.getString(ctx.getDecoder()), out); } finally { buf.clear(); } } else { int overflowPosition = ctx.getOverflowPosition(); ctx.reset(); throw new RecoverableProtocolDecoderException("Line is too long: " + overflowPosition); } oldPos = pos; matchCount = 0; } } else { // fix for DIRMINA-506 & DIRMINA-536 in.position(Math.max(0, in.position() - matchCount)); matchCount = 0; } } // Put remainder to buf. in.position(oldPos); ctx.append(in); ctx.setMatchCount(matchCount); } /** * By default, this method propagates the decoded line of text to * {@code ProtocolDecoderOutput#write(Object)}. You may override this method to modify * the default behavior. * * @param session the {@code IoSession} the received data. * @param text the decoded text * @param out the upstream {@code ProtocolDecoderOutput}. */ protected void writeText(IoSession session, String text, ProtocolDecoderOutput out) { out.write(text); } /** * A Context used during the decoding of a lin. It stores the decoder, * the temporary buffer containing the decoded line, and other status flags. * * @author Apache Directory Project * @version $Rev: 1387401 $, $Date: 2012-09-19 00:51:04 +0200 (Wed, 19 Sep 2012) $ */ private class Context { /** The decoder */ private final CharsetDecoder decoder; /** The temporary buffer containing the decoded line */ private final IoBuffer buf; /** The number of lines found so far */ private int matchCount = 0; /** A counter to signal that the line is too long */ private int overflowPosition = 0; /** Create a new Context object with a default buffer */ private Context(int bufferLength) { decoder = charset.newDecoder(); buf = IoBuffer.allocate(bufferLength).setAutoExpand(true); } public CharsetDecoder getDecoder() { return decoder; } public IoBuffer getBuffer() { return buf; } public int getOverflowPosition() { return overflowPosition; } public int getMatchCount() { return matchCount; } public void setMatchCount(int matchCount) { this.matchCount = matchCount; } public void reset() { overflowPosition = 0; matchCount = 0; decoder.reset(); } public void append(IoBuffer in) { if (overflowPosition != 0) { discard(in); } else if (buf.position() > maxLineLength - in.remaining()) { overflowPosition = buf.position(); buf.clear(); discard(in); } else { getBuffer().put(in); } } private void discard(IoBuffer in) { if (Integer.MAX_VALUE - in.remaining() < overflowPosition) { overflowPosition = Integer.MAX_VALUE; } else { overflowPosition += in.remaining(); } in.position(in.limit()); } } }././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/textline/TextLineEncoder.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/textline/TextLineEncoder.j0000644000175000017500000001210112032276025032445 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.textline; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolEncoder; import org.apache.mina.filter.codec.ProtocolEncoderAdapter; import org.apache.mina.filter.codec.ProtocolEncoderOutput; /** * A {@link ProtocolEncoder} which encodes a string into a text line * which ends with the delimiter. * * @author Apache MINA Project */ public class TextLineEncoder extends ProtocolEncoderAdapter { private final AttributeKey ENCODER = new AttributeKey(getClass(), "encoder"); private final Charset charset; private final LineDelimiter delimiter; private int maxLineLength = Integer.MAX_VALUE; /** * Creates a new instance with the current default {@link Charset} * and {@link LineDelimiter#UNIX} delimiter. */ public TextLineEncoder() { this(Charset.defaultCharset(), LineDelimiter.UNIX); } /** * Creates a new instance with the current default {@link Charset} * and the specified delimiter. */ public TextLineEncoder(String delimiter) { this(new LineDelimiter(delimiter)); } /** * Creates a new instance with the current default {@link Charset} * and the specified delimiter. */ public TextLineEncoder(LineDelimiter delimiter) { this(Charset.defaultCharset(), delimiter); } /** * Creates a new instance with the spcified charset * and {@link LineDelimiter#UNIX} delimiter. */ public TextLineEncoder(Charset charset) { this(charset, LineDelimiter.UNIX); } /** * Creates a new instance with the spcified charset * and the specified delimiter. */ public TextLineEncoder(Charset charset, String delimiter) { this(charset, new LineDelimiter(delimiter)); } /** * Creates a new instance with the spcified charset * and the specified delimiter. */ public TextLineEncoder(Charset charset, LineDelimiter delimiter) { if (charset == null) { throw new IllegalArgumentException("charset"); } if (delimiter == null) { throw new IllegalArgumentException("delimiter"); } if (LineDelimiter.AUTO.equals(delimiter)) { throw new IllegalArgumentException("AUTO delimiter is not allowed for encoder."); } this.charset = charset; this.delimiter = delimiter; } /** * Returns the allowed maximum size of the encoded line. * If the size of the encoded line exceeds this value, the encoder * will throw a {@link IllegalArgumentException}. The default value * is {@link Integer#MAX_VALUE}. */ public int getMaxLineLength() { return maxLineLength; } /** * Sets the allowed maximum size of the encoded line. * If the size of the encoded line exceeds this value, the encoder * will throw a {@link IllegalArgumentException}. The default value * is {@link Integer#MAX_VALUE}. */ public void setMaxLineLength(int maxLineLength) { if (maxLineLength <= 0) { throw new IllegalArgumentException("maxLineLength: " + maxLineLength); } this.maxLineLength = maxLineLength; } public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { CharsetEncoder encoder = (CharsetEncoder) session.getAttribute(ENCODER); if (encoder == null) { encoder = charset.newEncoder(); session.setAttribute(ENCODER, encoder); } String value = (message == null ? "" : message.toString()); IoBuffer buf = IoBuffer.allocate(value.length()).setAutoExpand(true); buf.putString(value, encoder); if (buf.position() > maxLineLength) { throw new IllegalArgumentException("Line length: " + buf.position()); } buf.putString(delimiter.getValue(), encoder); buf.flip(); out.write(buf); } public void dispose() throws Exception { // Do nothing } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/textline/package.html0000644000175000017500000000163112032276025031525 0ustar ebourgebourg A protocol codec for text-based protocols. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolDecoderOutput.java0000644000175000017500000000323312032276025032563 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.session.IoSession; /** * Callback for {@link ProtocolDecoder} to generate decoded messages. * {@link ProtocolDecoder} must call {@link #write(Object)} for each decoded * messages. * * @author Apache MINA Project */ public interface ProtocolDecoderOutput { /** * Callback for {@link ProtocolDecoder} to generate decoded messages. * {@link ProtocolDecoder} must call {@link #write(Object)} for each * decoded messages. * * @param message the decoded message */ void write(Object message); /** * Flushes all messages you wrote via {@link #write(Object)} to * the next filter. */ void flush(NextFilter nextFilter, IoSession session); } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolCodecException.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolCodecException.jav0000644000175000017500000000351612032276025032534 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; /** * An exception that is thrown when {@link ProtocolEncoder} or * {@link ProtocolDecoder} cannot understand or failed to validate * data to process. * * @author Apache MINA Project */ public class ProtocolCodecException extends Exception { private static final long serialVersionUID = 5939878548186330695L; /** * Constructs a new instance. */ public ProtocolCodecException() { // Do nothing } /** * Constructs a new instance with the specified message. */ public ProtocolCodecException(String message) { super(message); } /** * Constructs a new instance with the specified cause. */ public ProtocolCodecException(Throwable cause) { super(cause); } /** * Constructs a new instance with the specified message and the specified * cause. */ public ProtocolCodecException(String message, Throwable cause) { super(message, cause); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolCodecSession.java0000644000175000017500000000710212032276025032355 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import java.util.Queue; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.future.DefaultWriteFuture; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.session.DummySession; import org.apache.mina.core.session.IoSession; /** * A virtual {@link IoSession} that provides {@link ProtocolEncoderOutput} * and {@link ProtocolDecoderOutput}. It is useful for unit-testing * codec and reusing codec for non-network-use (e.g. serialization). * *

Encoding

*
 * ProtocolCodecSession session = new ProtocolCodecSession();
 * ProtocolEncoder encoder = ...;
 * MessageX in = ...;
 *
 * encoder.encode(session, in, session.getProtocolEncoderOutput());
 *
 * IoBuffer buffer = session.getProtocolDecoderOutputQueue().poll();
 * 
* *

Decoding

*
 * ProtocolCodecSession session = new ProtocolCodecSession();
 * ProtocolDecoder decoder = ...;
 * IoBuffer in = ...;
 *
 * decoder.decode(session, in, session.getProtocolDecoderOutput());
 *
 * Object message = session.getProtocolDecoderOutputQueue().poll();
 * 
* * @author Apache MINA Project */ public class ProtocolCodecSession extends DummySession { private final WriteFuture notWrittenFuture = DefaultWriteFuture.newNotWrittenFuture(this, new UnsupportedOperationException()); private final AbstractProtocolEncoderOutput encoderOutput = new AbstractProtocolEncoderOutput() { public WriteFuture flush() { return notWrittenFuture; } }; private final AbstractProtocolDecoderOutput decoderOutput = new AbstractProtocolDecoderOutput() { public void flush(NextFilter nextFilter, IoSession session) { // Do nothing } }; /** * Creates a new instance. */ public ProtocolCodecSession() { // Do nothing } /** * Returns the {@link ProtocolEncoderOutput} that buffers * {@link IoBuffer}s generated by {@link ProtocolEncoder}. */ public ProtocolEncoderOutput getEncoderOutput() { return encoderOutput; } /** * Returns the {@link Queue} of the buffered encoder output. */ public Queue getEncoderOutputQueue() { return encoderOutput.getMessageQueue(); } /** * Returns the {@link ProtocolEncoderOutput} that buffers * messages generated by {@link ProtocolDecoder}. */ public ProtocolDecoderOutput getDecoderOutput() { return decoderOutput; } /** * Returns the {@link Queue} of the buffered decoder output. */ public Queue getDecoderOutputQueue() { return decoderOutput.getMessageQueue(); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/CumulativeProtocolDecoder.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/CumulativeProtocolDecoder.0000644000175000017500000002154512032276025032545 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IoSession; /** * A {@link ProtocolDecoder} that cumulates the content of received * buffers to a cumulative buffer to help users implement decoders. *

* If the received {@link IoBuffer} is only a part of a message. * decoders should cumulate received buffers to make a message complete or * to postpone decoding until more buffers arrive. *

* Here is an example decoder that decodes CRLF terminated lines into * Command objects: *

 * public class CrLfTerminatedCommandLineDecoder
 *         extends CumulativeProtocolDecoder {
 *
 *     private Command parseCommand(IoBuffer in) {
 *         // Convert the bytes in the specified buffer to a
 *         // Command object.
 *         ...
 *     }
 *
 *     protected boolean doDecode(
 *             IoSession session, IoBuffer in, ProtocolDecoderOutput out)
 *             throws Exception {
 *
 *         // Remember the initial position.
 *         int start = in.position();
 *
 *         // Now find the first CRLF in the buffer.
 *         byte previous = 0;
 *         while (in.hasRemaining()) {
 *             byte current = in.get();
 *
 *             if (previous == '\r' && current == '\n') {
 *                 // Remember the current position and limit.
 *                 int position = in.position();
 *                 int limit = in.limit();
 *                 try {
 *                     in.position(start);
 *                     in.limit(position);
 *                     // The bytes between in.position() and in.limit()
 *                     // now contain a full CRLF terminated line.
 *                     out.write(parseCommand(in.slice()));
 *                 } finally {
 *                     // Set the position to point right after the
 *                     // detected line and set the limit to the old
 *                     // one.
 *                     in.position(position);
 *                     in.limit(limit);
 *                 }
 *                 // Decoded one line; CumulativeProtocolDecoder will
 *                 // call me again until I return false. So just
 *                 // return true until there are no more lines in the
 *                 // buffer.
 *                 return true;
 *             }
 *
 *             previous = current;
 *         }
 *
 *         // Could not find CRLF in the buffer. Reset the initial
 *         // position to the one we recorded above.
 *         in.position(start);
 *
 *         return false;
 *     }
 * }
 * 
*

* Please note that this decoder simply forward the call to * {@link #doDecode(IoSession, IoBuffer, ProtocolDecoderOutput)} if the * underlying transport doesn't have a packet fragmentation. Whether the * transport has fragmentation or not is determined by querying * {@link TransportMetadata}. * * @author Apache MINA Project */ public abstract class CumulativeProtocolDecoder extends ProtocolDecoderAdapter { private final AttributeKey BUFFER = new AttributeKey(getClass(), "buffer"); /** * Creates a new instance. */ protected CumulativeProtocolDecoder() { // Do nothing } /** * Cumulates content of in into internal buffer and forwards * decoding request to {@link #doDecode(IoSession, IoBuffer, ProtocolDecoderOutput)}. * doDecode() is invoked repeatedly until it returns false * and the cumulative buffer is compacted after decoding ends. * * @throws IllegalStateException if your doDecode() returned * true not consuming the cumulative buffer. */ public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { if (!session.getTransportMetadata().hasFragmentation()) { while (in.hasRemaining()) { if (!doDecode(session, in, out)) { break; } } return; } boolean usingSessionBuffer = true; IoBuffer buf = (IoBuffer) session.getAttribute(BUFFER); // If we have a session buffer, append data to that; otherwise // use the buffer read from the network directly. if (buf != null) { boolean appended = false; // Make sure that the buffer is auto-expanded. if (buf.isAutoExpand()) { try { buf.put(in); appended = true; } catch (IllegalStateException e) { // A user called derivation method (e.g. slice()), // which disables auto-expansion of the parent buffer. } catch (IndexOutOfBoundsException e) { // A user disabled auto-expansion. } } if (appended) { buf.flip(); } else { // Reallocate the buffer if append operation failed due to // derivation or disabled auto-expansion. buf.flip(); IoBuffer newBuf = IoBuffer.allocate(buf.remaining() + in.remaining()).setAutoExpand(true); newBuf.order(buf.order()); newBuf.put(buf); newBuf.put(in); newBuf.flip(); buf = newBuf; // Update the session attribute. session.setAttribute(BUFFER, buf); } } else { buf = in; usingSessionBuffer = false; } for (;;) { int oldPos = buf.position(); boolean decoded = doDecode(session, buf, out); if (decoded) { if (buf.position() == oldPos) { throw new IllegalStateException("doDecode() can't return true when buffer is not consumed."); } if (!buf.hasRemaining()) { break; } } else { break; } } // if there is any data left that cannot be decoded, we store // it in a buffer in the session and next time this decoder is // invoked the session buffer gets appended to if (buf.hasRemaining()) { if (usingSessionBuffer && buf.isAutoExpand()) { buf.compact(); } else { storeRemainingInSession(buf, session); } } else { if (usingSessionBuffer) { removeSessionBuffer(session); } } } /** * Implement this method to consume the specified cumulative buffer and * decode its content into message(s). * * @param in the cumulative buffer * @return true if and only if there's more to decode in the buffer * and you want to have doDecode method invoked again. * Return false if remaining data is not enough to decode, * then this method will be invoked again when more data is cumulated. * @throws Exception if cannot decode in. */ protected abstract boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception; /** * Releases the cumulative buffer used by the specified session. * Please don't forget to call super.dispose( session ) when * you override this method. */ @Override public void dispose(IoSession session) throws Exception { removeSessionBuffer(session); } private void removeSessionBuffer(IoSession session) { session.removeAttribute(BUFFER); } private void storeRemainingInSession(IoBuffer buf, IoSession session) { final IoBuffer remainingBuf = IoBuffer.allocate(buf.capacity()).setAutoExpand(true); remainingBuf.order(buf.order()); remainingBuf.put(buf); session.setAttribute(BUFFER, remainingBuf); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolEncoderAdapter.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolEncoderAdapter.jav0000644000175000017500000000257612032276025032525 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import org.apache.mina.core.session.IoSession; /** * An abstract {@link ProtocolEncoder} implementation for those who don't have any * resources to dispose. * * @author Apache MINA Project */ public abstract class ProtocolEncoderAdapter implements ProtocolEncoder { /** * Override this method dispose all resources related with this encoder. * The default implementation does nothing. */ public void dispose(IoSession session) throws Exception { // Do nothing } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/0000755000175000017500000000000012162575507030067 5ustar ebourgebourg././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/DecodingStateProtocolDecoder.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/DecodingState0000644000175000017500000000703512032276025032521 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.statemachine; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * {@link ProtocolDecoder} which uses a {@link DecodingState} to decode data. * Use a {@link DecodingStateMachine} as {@link DecodingState} to create * a state machine which can decode your protocol. *

* NOTE: This is a stateful decoder. You should create one instance per session. *

* * @author Apache MINA Project */ public class DecodingStateProtocolDecoder implements ProtocolDecoder { private final DecodingState state; private final Queue undecodedBuffers = new ConcurrentLinkedQueue(); private IoSession session; /** * Creates a new instance using the specified {@link DecodingState} * instance. * * @param state the {@link DecodingState}. * @throws IllegalArgumentException if the specified state is null. */ public DecodingStateProtocolDecoder(DecodingState state) { if (state == null) { throw new IllegalArgumentException("state"); } this.state = state; } /** * {@inheritDoc} */ public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { if (this.session == null) { this.session = session; } else if (this.session != session) { throw new IllegalStateException(getClass().getSimpleName() + " is a stateful decoder. " + "You have to create one per session."); } undecodedBuffers.offer(in); for (;;) { IoBuffer b = undecodedBuffers.peek(); if (b == null) { break; } int oldRemaining = b.remaining(); state.decode(b, out); int newRemaining = b.remaining(); if (newRemaining != 0) { if (oldRemaining == newRemaining) { throw new IllegalStateException(DecodingState.class.getSimpleName() + " must " + "consume at least one byte per decode()."); } } else { undecodedBuffers.poll(); } } } /** * {@inheritDoc} */ public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception { state.finishDecode(out); } /** * {@inheritDoc} */ public void dispose(IoSession session) throws Exception { // Do nothing } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/SkippingState.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/SkippingState0000644000175000017500000000530512032276025032567 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.statemachine; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * {@link DecodingState} which skips data until {@link #canSkip(byte)} returns * false. * * @author Apache MINA Project */ public abstract class SkippingState implements DecodingState { private int skippedBytes; /** * {@inheritDoc} */ public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception { int beginPos = in.position(); int limit = in.limit(); for (int i = beginPos; i < limit; i++) { byte b = in.get(i); if (!canSkip(b)) { in.position(i); int answer = this.skippedBytes; this.skippedBytes = 0; return finishDecode(answer); } skippedBytes++; } in.position(limit); return this; } /** * {@inheritDoc} */ public DecodingState finishDecode(ProtocolDecoderOutput out) throws Exception { return finishDecode(skippedBytes); } /** * Called to determine whether the specified byte can be skipped. * * @param b the byte to check. * @return true if the byte can be skipped. */ protected abstract boolean canSkip(byte b); /** * Invoked when this state cannot skip any more bytes. * * @param skippedBytes the number of bytes skipped. * @return the next state if a state transition was triggered (use * this for loop transitions) or null if * the state machine has reached its end. * @throws Exception if the read data violated protocol specification. */ protected abstract DecodingState finishDecode(int skippedBytes) throws Exception; } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/ConsumeToEndOfSessionDecodingState.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/ConsumeToEndO0000644000175000017500000000630712032276025032467 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.statemachine; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.filter.codec.ProtocolDecoderException; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * {@link DecodingState} which consumes all received bytes until the session is * closed. * * @author Apache MINA Project */ public abstract class ConsumeToEndOfSessionDecodingState implements DecodingState { private IoBuffer buffer; private final int maxLength; /** * Creates a new instance using the specified maximum length. * * @param maxLength the maximum number of bytes which will be consumed. If * this max is reached a {@link ProtocolDecoderException} will be * thrown by {@link #decode(IoBuffer, ProtocolDecoderOutput)}. */ public ConsumeToEndOfSessionDecodingState(int maxLength) { this.maxLength = maxLength; } /** * {@inheritDoc} */ public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception { if (buffer == null) { buffer = IoBuffer.allocate(256).setAutoExpand(true); } if (buffer.position() + in.remaining() > maxLength) { throw new ProtocolDecoderException("Received data exceeds " + maxLength + " byte(s)."); } buffer.put(in); return this; } /** * {@inheritDoc} */ public DecodingState finishDecode(ProtocolDecoderOutput out) throws Exception { try { if (buffer == null) { buffer = IoBuffer.allocate(0); } buffer.flip(); return finishDecode(buffer, out); } finally { buffer = null; } } /** * Invoked when this state has consumed all bytes until the session is * closed. * * @param product the bytes read. * @param out the current {@link ProtocolDecoderOutput} used to write * decoded messages. * @return the next state if a state transition was triggered (use * this for loop transitions) or null if * the state machine has reached its end. * @throws Exception if the read data violated protocol specification. */ protected abstract DecodingState finishDecode(IoBuffer product, ProtocolDecoderOutput out) throws Exception; } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/ConsumeToLinearWhitespaceDecodingState.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/ConsumeToLine0000644000175000017500000000257312032276025032532 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.statemachine; /** * {@link DecodingState} which consumes all bytes until a space (0x20) or tab * (0x09) character is reached. The terminator is skipped. * * @author Apache MINA Project */ public abstract class ConsumeToLinearWhitespaceDecodingState extends ConsumeToDynamicTerminatorDecodingState { /** * @return true if the given byte is a space or a tab */ @Override protected boolean isTerminator(byte b) { return (b == ' ') || (b == '\t'); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/DecodingState.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/DecodingState0000644000175000017500000000504712032276025032522 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.statemachine; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * Represents a state in a decoder state machine used by * {@link DecodingStateMachine}. * * @author Apache MINA Project */ public interface DecodingState { /** * Invoked when data is available for this state. * * @param in the data to be decoded. * @param out used to write decoded objects. * @return the next state if a state transition was triggered (use * this for loop transitions) or null if * the state machine has reached its end. * @throws Exception if the read data violated protocol specification. */ DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception; /** * Invoked when the associated {@link IoSession} is closed. This method is * useful when you deal with protocols which don't specify the length of a * message (e.g. HTTP responses without content-length header). * Implement this method to process the remaining data that * {@link #decode(IoBuffer, ProtocolDecoderOutput)} method didn't process * completely. * * @param out used to write decoded objects. * @return the next state if a state transition was triggered (use * this for loop transitions) or null if * the state machine has reached its end. * @throws Exception if the read data violated protocol specification. */ DecodingState finishDecode(ProtocolDecoderOutput out) throws Exception; } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/SingleByteDecodingState.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/SingleByteDec0000644000175000017500000000442512032276025032465 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.statemachine; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.filter.codec.ProtocolDecoderException; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * {@link DecodingState} which decodes byte values. * * @author Apache MINA Project */ public abstract class SingleByteDecodingState implements DecodingState { public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception { if (in.hasRemaining()) { return finishDecode(in.get(), out); } return this; } /** * {@inheritDoc} */ public DecodingState finishDecode(ProtocolDecoderOutput out) throws Exception { throw new ProtocolDecoderException("Unexpected end of session while waiting for a single byte."); } /** * Invoked when this state has consumed a complete byte. * * @param b the byte. * @param out the current {@link ProtocolDecoderOutput} used to write * decoded messages. * @return the next state if a state transition was triggered (use * this for loop transitions) or null if * the state machine has reached its end. * @throws Exception if the read data violated protocol specification. */ protected abstract DecodingState finishDecode(byte b, ProtocolDecoderOutput out) throws Exception; } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/FixedLengthDecodingState.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/FixedLengthDe0000644000175000017500000000720312032276025032453 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.statemachine; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * {@link DecodingState} which consumes all received bytes until a configured * number of read bytes has been reached. Please note that this state can * produce a buffer with less data than the configured length if the associated * session has been closed unexpectedly. * * @author Apache MINA Project */ public abstract class FixedLengthDecodingState implements DecodingState { private final int length; private IoBuffer buffer; /** * Constructs a new instance using the specified decode length. * * @param length the number of bytes to read. */ public FixedLengthDecodingState(int length) { this.length = length; } /** * {@inheritDoc} */ public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception { if (buffer == null) { if (in.remaining() >= length) { int limit = in.limit(); in.limit(in.position() + length); IoBuffer product = in.slice(); in.position(in.position() + length); in.limit(limit); return finishDecode(product, out); } buffer = IoBuffer.allocate(length); buffer.put(in); return this; } if (in.remaining() >= length - buffer.position()) { int limit = in.limit(); in.limit(in.position() + length - buffer.position()); buffer.put(in); in.limit(limit); IoBuffer product = this.buffer; this.buffer = null; return finishDecode(product.flip(), out); } buffer.put(in); return this; } /** * {@inheritDoc} */ public DecodingState finishDecode(ProtocolDecoderOutput out) throws Exception { IoBuffer readData; if (buffer == null) { readData = IoBuffer.allocate(0); } else { readData = buffer.flip(); buffer = null; } return finishDecode(readData, out); } /** * Invoked when this state has consumed the configured number of bytes. * * @param product the data. * @param out the current {@link ProtocolDecoderOutput} used to write * decoded messages. * @return the next state if a state transition was triggered (use * this for loop transitions) or null if * the state machine has reached its end. * @throws Exception if the read data violated protocol specification. */ protected abstract DecodingState finishDecode(IoBuffer product, ProtocolDecoderOutput out) throws Exception; } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/ShortIntegerDecodingState.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/ShortIntegerD0000644000175000017500000000535012032276025032523 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.statemachine; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.filter.codec.ProtocolDecoderException; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * {@link DecodingState} which decodes short values in big-endian * order (high bytes come first). * * @author Apache MINA Project */ public abstract class ShortIntegerDecodingState implements DecodingState { private int highByte; private int counter; /** * {@inheritDoc} */ public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception { while (in.hasRemaining()) { switch (counter) { case 0: highByte = in.getUnsigned(); break; case 1: counter = 0; return finishDecode((short) ((highByte << 8) | in.getUnsigned()), out); default: throw new InternalError(); } counter++; } return this; } /** * {@inheritDoc} */ public DecodingState finishDecode(ProtocolDecoderOutput out) throws Exception { throw new ProtocolDecoderException("Unexpected end of session while waiting for a short integer."); } /** * Invoked when this state has consumed a complete short. * * @param value the short. * @param out the current {@link ProtocolDecoderOutput} used to write * decoded messages. * @return the next state if a state transition was triggered (use * this for loop transitions) or null if * the state machine has reached its end. * @throws Exception if the read data violated protocol specification. */ protected abstract DecodingState finishDecode(short value, ProtocolDecoderOutput out) throws Exception; } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/CrLfDecodingState.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/CrLfDecodingS0000644000175000017500000000714312032276025032412 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.statemachine; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.filter.codec.ProtocolDecoderException; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * {@link DecodingState} which decodes a single CRLF. * If it is found, the bytes are consumed and true * is provided as the product. Otherwise, read bytes are pushed back * to the stream, and false is provided as the * product. * Note that if we find a CR but do not find a following LF, we raise * an error. * * @author Apache MINA Project */ public abstract class CrLfDecodingState implements DecodingState { /** * Carriage return character */ private static final byte CR = 13; /** * Line feed character */ private static final byte LF = 10; private boolean hasCR; /** * {@inheritDoc} */ public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception { boolean found = false; boolean finished = false; while (in.hasRemaining()) { byte b = in.get(); if (!hasCR) { if (b == CR) { hasCR = true; } else { if (b == LF) { found = true; } else { in.position(in.position() - 1); found = false; } finished = true; break; } } else { if (b == LF) { found = true; finished = true; break; } throw new ProtocolDecoderException("Expected LF after CR but was: " + (b & 0xff)); } } if (finished) { hasCR = false; return finishDecode(found, out); } return this; } /** * {@inheritDoc} */ public DecodingState finishDecode(ProtocolDecoderOutput out) throws Exception { return finishDecode(false, out); } /** * Invoked when this state has found a CRLF. * * @param foundCRLF true if CRLF was found. * @param out the current {@link ProtocolDecoderOutput} used to write * decoded messages. * @return the next state if a state transition was triggered (use * this for loop transitions) or null if * the state machine has reached its end. * @throws Exception if the read data violated protocol specification. */ protected abstract DecodingState finishDecode(boolean foundCRLF, ProtocolDecoderOutput out) throws Exception; } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/ConsumeToCrLfDecodingState.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/ConsumeToCrLf0000644000175000017500000001051112032276025032460 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.statemachine; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * {@link DecodingState} which consumes all bytes until a CRLF * has been encountered. * * @author Apache MINA Project */ public abstract class ConsumeToCrLfDecodingState implements DecodingState { /** * Carriage return character */ private static final byte CR = 13; /** * Line feed character */ private static final byte LF = 10; private boolean lastIsCR; private IoBuffer buffer; /** * Creates a new instance. */ public ConsumeToCrLfDecodingState() { // Do nothing } public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception { int beginPos = in.position(); int limit = in.limit(); int terminatorPos = -1; for (int i = beginPos; i < limit; i++) { byte b = in.get(i); if (b == CR) { lastIsCR = true; } else { if (b == LF && lastIsCR) { terminatorPos = i; break; } lastIsCR = false; } } if (terminatorPos >= 0) { IoBuffer product; int endPos = terminatorPos - 1; if (beginPos < endPos) { in.limit(endPos); if (buffer == null) { product = in.slice(); } else { buffer.put(in); product = buffer.flip(); buffer = null; } in.limit(limit); } else { // When input contained only CR or LF rather than actual data... if (buffer == null) { product = IoBuffer.allocate(0); } else { product = buffer.flip(); buffer = null; } } in.position(terminatorPos + 1); return finishDecode(product, out); } in.position(beginPos); if (buffer == null) { buffer = IoBuffer.allocate(in.remaining()); buffer.setAutoExpand(true); } buffer.put(in); if (lastIsCR) { buffer.position(buffer.position() - 1); } return this; } /** * {@inheritDoc} */ public DecodingState finishDecode(ProtocolDecoderOutput out) throws Exception { IoBuffer product; // When input contained only CR or LF rather than actual data... if (buffer == null) { product = IoBuffer.allocate(0); } else { product = buffer.flip(); buffer = null; } return finishDecode(product, out); } /** * Invoked when this state has reached a CRLF. * * @param product the read bytes including the CRLF. * @param out the current {@link ProtocolDecoderOutput} used to write * decoded messages. * @return the next state if a state transition was triggered (use * this for loop transitions) or null if * the state machine has reached its end. * @throws Exception if the read data violated protocol specification. */ protected abstract DecodingState finishDecode(IoBuffer product, ProtocolDecoderOutput out) throws Exception; } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/ConsumeToTerminatorDecodingState.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/ConsumeToTerm0000644000175000017500000000756112032276025032554 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.statemachine; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * {@link DecodingState} which consumes all bytes until a fixed (ASCII) * character is reached. The terminator is skipped. * * @author Apache MINA Project */ public abstract class ConsumeToTerminatorDecodingState implements DecodingState { private final byte terminator; private IoBuffer buffer; /** * Creates a new instance using the specified terminator character. * * @param terminator the terminator character. */ public ConsumeToTerminatorDecodingState(byte terminator) { this.terminator = terminator; } /** * {@inheritDoc} */ public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception { int terminatorPos = in.indexOf(terminator); if (terminatorPos >= 0) { int limit = in.limit(); IoBuffer product; if (in.position() < terminatorPos) { in.limit(terminatorPos); if (buffer == null) { product = in.slice(); } else { buffer.put(in); product = buffer.flip(); buffer = null; } in.limit(limit); } else { // When input contained only terminator rather than actual data... if (buffer == null) { product = IoBuffer.allocate(0); } else { product = buffer.flip(); buffer = null; } } in.position(terminatorPos + 1); return finishDecode(product, out); } if (buffer == null) { buffer = IoBuffer.allocate(in.remaining()); buffer.setAutoExpand(true); } buffer.put(in); return this; } /** * {@inheritDoc} */ public DecodingState finishDecode(ProtocolDecoderOutput out) throws Exception { IoBuffer product; // When input contained only terminator rather than actual data... if (buffer == null) { product = IoBuffer.allocate(0); } else { product = buffer.flip(); buffer = null; } return finishDecode(product, out); } /** * Invoked when this state has reached the terminator byte. * * @param product the read bytes not including the terminator. * @param out the current {@link ProtocolDecoderOutput} used to write * decoded messages. * @return the next state if a state transition was triggered (use * this for loop transitions) or null if * the state machine has reached its end. * @throws Exception if the read data violated protocol specification. */ protected abstract DecodingState finishDecode(IoBuffer product, ProtocolDecoderOutput out) throws Exception; } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/IntegerDecodingState.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/IntegerDecodi0000644000175000017500000000574712032276025032521 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.statemachine; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.filter.codec.ProtocolDecoderException; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * {@link DecodingState} which decodes int values in big-endian * order (high bytes come first). * * @author Apache MINA Project */ public abstract class IntegerDecodingState implements DecodingState { private int firstByte; private int secondByte; private int thirdByte; private int counter; /** * {@inheritDoc} */ public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception { while (in.hasRemaining()) { switch (counter) { case 0: firstByte = in.getUnsigned(); break; case 1: secondByte = in.getUnsigned(); break; case 2: thirdByte = in.getUnsigned(); break; case 3: counter = 0; return finishDecode((firstByte << 24) | (secondByte << 16) | (thirdByte << 8) | in.getUnsigned(), out); default: throw new InternalError(); } counter++; } return this; } /** * {@inheritDoc} */ public DecodingState finishDecode(ProtocolDecoderOutput out) throws Exception { throw new ProtocolDecoderException("Unexpected end of session while waiting for an integer."); } /** * Invoked when this state has consumed a complete int. * * @param value the integer. * @param out the current {@link ProtocolDecoderOutput} used to write * decoded messages. * @return the next state if a state transition was triggered (use * this for loop transitions) or null if * the state machine has reached its end. * @throws Exception if the read data violated protocol specification. */ protected abstract DecodingState finishDecode(int value, ProtocolDecoderOutput out) throws Exception; } ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/ConsumeToDynamicTerminatorDecodingState.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/ConsumeToDyna0000644000175000017500000001013712032276025032531 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.statemachine; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * {@link DecodingState} which consumes all bytes until a fixed (ASCII) * character is reached. The terminator is skipped. * * @author Apache MINA Project */ public abstract class ConsumeToDynamicTerminatorDecodingState implements DecodingState { private IoBuffer buffer; /** * {@inheritDoc} */ public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception { int beginPos = in.position(); int terminatorPos = -1; int limit = in.limit(); for (int i = beginPos; i < limit; i++) { byte b = in.get(i); if (isTerminator(b)) { terminatorPos = i; break; } } if (terminatorPos >= 0) { IoBuffer product; if (beginPos < terminatorPos) { in.limit(terminatorPos); if (buffer == null) { product = in.slice(); } else { buffer.put(in); product = buffer.flip(); buffer = null; } in.limit(limit); } else { // When input contained only terminator rather than actual data... if (buffer == null) { product = IoBuffer.allocate(0); } else { product = buffer.flip(); buffer = null; } } in.position(terminatorPos + 1); return finishDecode(product, out); } if (buffer == null) { buffer = IoBuffer.allocate(in.remaining()); buffer.setAutoExpand(true); } buffer.put(in); return this; } /** * {@inheritDoc} */ public DecodingState finishDecode(ProtocolDecoderOutput out) throws Exception { IoBuffer product; // When input contained only terminator rather than actual data... if (buffer == null) { product = IoBuffer.allocate(0); } else { product = buffer.flip(); buffer = null; } return finishDecode(product, out); } /** * Determines whether the specified byte is a terminator. * * @param b the byte to check. * @return true if b is a terminator, * false otherwise. */ protected abstract boolean isTerminator(byte b); /** * Invoked when this state has reached the terminator byte. * * @param product the read bytes not including the terminator. * @param out the current {@link ProtocolDecoderOutput} used to write * decoded messages. * @return the next state if a state transition was triggered (use * this for loop transitions) or null if * the state machine has reached its end. * @throws Exception if the read data violated protocol specification. */ protected abstract DecodingState finishDecode(IoBuffer product, ProtocolDecoderOutput out) throws Exception; } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/LinearWhitespaceSkippingState.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/LinearWhitesp0000644000175000017500000000233412032276025032557 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.statemachine; /** * {@link DecodingState} which skips space (0x20) and tab (0x09) characters. * * @author Apache MINA Project */ public abstract class LinearWhitespaceSkippingState extends SkippingState { /** * {@inheritDoc} */ @Override protected boolean canSkip(byte b) { return b == 32 || b == 9; } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/DecodingStateMachine.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/statemachine/DecodingState0000644000175000017500000001457612032276025032531 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.statemachine; import java.util.ArrayList; import java.util.List; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Abstract base class for decoder state machines. Calls {@link #init()} to * get the start {@link DecodingState} of the state machine. Calls * {@link #destroy()} when the state machine has reached its end state or when * the session is closed. *

* NOTE: The {@link ProtocolDecoderOutput} used by this class when calling * {@link DecodingState#decode(IoBuffer, ProtocolDecoderOutput)} buffers decoded * messages in a {@link List}. Once the state machine has reached its end state * this class will call {@link #finishDecode(List, ProtocolDecoderOutput)}. The * implementation will have to take care of writing the decoded messages to the * real {@link ProtocolDecoderOutput} used by the configured * {@link ProtocolCodecFilter}. *

* * @author Apache MINA Project */ public abstract class DecodingStateMachine implements DecodingState { private final Logger log = LoggerFactory.getLogger(DecodingStateMachine.class); private final List childProducts = new ArrayList(); private final ProtocolDecoderOutput childOutput = new ProtocolDecoderOutput() { public void flush(NextFilter nextFilter, IoSession session) { // Do nothing } public void write(Object message) { childProducts.add(message); } }; private DecodingState currentState; private boolean initialized; /** * Invoked to initialize this state machine. * * @return the start {@link DecodingState}. */ protected abstract DecodingState init() throws Exception; /** * Called once the state machine has reached its end. * * @param childProducts contains the messages generated by each of the * {@link DecodingState}s which were exposed to the received data * during the life time of this state machine. * @param out the real {@link ProtocolDecoderOutput} used by the * {@link ProtocolCodecFilter}. * @return the next state if the state machine should resume. */ protected abstract DecodingState finishDecode(List childProducts, ProtocolDecoderOutput out) throws Exception; /** * Invoked to destroy this state machine once the end state has been reached * or the session has been closed. */ protected abstract void destroy() throws Exception; /** * {@inheritDoc} */ public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception { DecodingState state = getCurrentState(); final int limit = in.limit(); int pos = in.position(); try { for (;;) { // Wait for more data if all data is consumed. if (pos == limit) { break; } DecodingState oldState = state; state = state.decode(in, childOutput); // If finished, call finishDecode if (state == null) { return finishDecode(childProducts, out); } int newPos = in.position(); // Wait for more data if nothing is consumed and state didn't change. if (newPos == pos && oldState == state) { break; } pos = newPos; } return this; } catch (Exception e) { state = null; throw e; } finally { this.currentState = state; // Destroy if decoding is finished or failed. if (state == null) { cleanup(); } } } /** * {@inheritDoc} */ public DecodingState finishDecode(ProtocolDecoderOutput out) throws Exception { DecodingState nextState; DecodingState state = getCurrentState(); try { for (;;) { DecodingState oldState = state; state = state.finishDecode(childOutput); if (state == null) { // Finished break; } // Exit if state didn't change. if (oldState == state) { break; } } } catch (Exception e) { state = null; log.debug("Ignoring the exception caused by a closed session.", e); } finally { this.currentState = state; nextState = finishDecode(childProducts, out); if (state == null) { cleanup(); } } return nextState; } private void cleanup() { if (!initialized) { throw new IllegalStateException(); } initialized = false; childProducts.clear(); try { destroy(); } catch (Exception e2) { log.warn("Failed to destroy a decoding state machine.", e2); } } private DecodingState getCurrentState() throws Exception { DecodingState state = this.currentState; if (state == null) { state = init(); initialized = true; } return state; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/serialization/0000755000175000017500000000000012162575507030277 5ustar ebourgebourg././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/serialization/ObjectSerializationOutputStream.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/serialization/ObjectSerial0000644000175000017500000001075612032276025032566 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.serialization; import java.io.DataOutputStream; import java.io.IOException; import java.io.ObjectOutput; import java.io.OutputStream; import org.apache.mina.core.buffer.IoBuffer; /** * An {@link ObjectOutput} and {@link OutputStream} that can write the objects as * the serialized form that {@link ObjectSerializationDecoder} can decode. * * @author Apache MINA Project */ public class ObjectSerializationOutputStream extends OutputStream implements ObjectOutput { private final DataOutputStream out; private int maxObjectSize = Integer.MAX_VALUE; public ObjectSerializationOutputStream(OutputStream out) { if (out == null) { throw new IllegalArgumentException("out"); } if (out instanceof DataOutputStream) { this.out = (DataOutputStream) out; } else { this.out = new DataOutputStream(out); } } /** * Returns the allowed maximum size of the encoded object. * If the size of the encoded object exceeds this value, this encoder * will throw a {@link IllegalArgumentException}. The default value * is {@link Integer#MAX_VALUE}. */ public int getMaxObjectSize() { return maxObjectSize; } /** * Sets the allowed maximum size of the encoded object. * If the size of the encoded object exceeds this value, this encoder * will throw a {@link IllegalArgumentException}. The default value * is {@link Integer#MAX_VALUE}. */ public void setMaxObjectSize(int maxObjectSize) { if (maxObjectSize <= 0) { throw new IllegalArgumentException("maxObjectSize: " + maxObjectSize); } this.maxObjectSize = maxObjectSize; } @Override public void close() throws IOException { out.close(); } @Override public void flush() throws IOException { out.flush(); } @Override public void write(int b) throws IOException { out.write(b); } @Override public void write(byte[] b) throws IOException { out.write(b); } @Override public void write(byte[] b, int off, int len) throws IOException { out.write(b, off, len); } public void writeObject(Object obj) throws IOException { IoBuffer buf = IoBuffer.allocate(64, false); buf.setAutoExpand(true); buf.putObject(obj); int objectSize = buf.position() - 4; if (objectSize > maxObjectSize) { throw new IllegalArgumentException("The encoded object is too big: " + objectSize + " (> " + maxObjectSize + ')'); } out.write(buf.array(), 0, buf.position()); } public void writeBoolean(boolean v) throws IOException { out.writeBoolean(v); } public void writeByte(int v) throws IOException { out.writeByte(v); } public void writeBytes(String s) throws IOException { out.writeBytes(s); } public void writeChar(int v) throws IOException { out.writeChar(v); } public void writeChars(String s) throws IOException { out.writeChars(s); } public void writeDouble(double v) throws IOException { out.writeDouble(v); } public void writeFloat(float v) throws IOException { out.writeFloat(v); } public void writeInt(int v) throws IOException { out.writeInt(v); } public void writeLong(long v) throws IOException { out.writeLong(v); } public void writeShort(int v) throws IOException { out.writeShort(v); } public void writeUTF(String str) throws IOException { out.writeUTF(str); } } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/serialization/ObjectSerializationInputStream.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/serialization/ObjectSerial0000644000175000017500000001221612032276025032557 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.serialization; import java.io.DataInput; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInput; import java.io.StreamCorruptedException; import org.apache.mina.core.buffer.BufferDataException; import org.apache.mina.core.buffer.IoBuffer; /** * An {@link ObjectInput} and {@link InputStream} that can read the objects encoded * by {@link ObjectSerializationEncoder}. * * @author Apache MINA Project */ public class ObjectSerializationInputStream extends InputStream implements ObjectInput { private final DataInputStream in; private final ClassLoader classLoader; private int maxObjectSize = 1048576; public ObjectSerializationInputStream(InputStream in) { this(in, null); } public ObjectSerializationInputStream(InputStream in, ClassLoader classLoader) { if (in == null) { throw new IllegalArgumentException("in"); } if (classLoader == null) { classLoader = Thread.currentThread().getContextClassLoader(); } if (in instanceof DataInputStream) { this.in = (DataInputStream) in; } else { this.in = new DataInputStream(in); } this.classLoader = classLoader; } /** * Returns the allowed maximum size of the object to be decoded. * If the size of the object to be decoded exceeds this value, this * decoder will throw a {@link BufferDataException}. The default * value is 1048576 (1MB). */ public int getMaxObjectSize() { return maxObjectSize; } /** * Sets the allowed maximum size of the object to be decoded. * If the size of the object to be decoded exceeds this value, this * decoder will throw a {@link BufferDataException}. The default * value is 1048576 (1MB). */ public void setMaxObjectSize(int maxObjectSize) { if (maxObjectSize <= 0) { throw new IllegalArgumentException("maxObjectSize: " + maxObjectSize); } this.maxObjectSize = maxObjectSize; } @Override public int read() throws IOException { return in.read(); } public Object readObject() throws ClassNotFoundException, IOException { int objectSize = in.readInt(); if (objectSize <= 0) { throw new StreamCorruptedException("Invalid objectSize: " + objectSize); } if (objectSize > maxObjectSize) { throw new StreamCorruptedException("ObjectSize too big: " + objectSize + " (expected: <= " + maxObjectSize + ')'); } IoBuffer buf = IoBuffer.allocate(objectSize + 4, false); buf.putInt(objectSize); in.readFully(buf.array(), 4, objectSize); buf.position(0); buf.limit(objectSize + 4); return buf.getObject(classLoader); } public boolean readBoolean() throws IOException { return in.readBoolean(); } public byte readByte() throws IOException { return in.readByte(); } public char readChar() throws IOException { return in.readChar(); } public double readDouble() throws IOException { return in.readDouble(); } public float readFloat() throws IOException { return in.readFloat(); } public void readFully(byte[] b) throws IOException { in.readFully(b); } public void readFully(byte[] b, int off, int len) throws IOException { in.readFully(b, off, len); } public int readInt() throws IOException { return in.readInt(); } /** * @see DataInput#readLine() * @deprecated */ @Deprecated public String readLine() throws IOException { return in.readLine(); } public long readLong() throws IOException { return in.readLong(); } public short readShort() throws IOException { return in.readShort(); } public String readUTF() throws IOException { return in.readUTF(); } public int readUnsignedByte() throws IOException { return in.readUnsignedByte(); } public int readUnsignedShort() throws IOException { return in.readUnsignedShort(); } public int skipBytes(int n) throws IOException { return in.skipBytes(n); } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/serialization/ObjectSerializationEncoder.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/serialization/ObjectSerial0000644000175000017500000000606112032276025032560 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.serialization; import java.io.NotSerializableException; import java.io.Serializable; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolEncoder; import org.apache.mina.filter.codec.ProtocolEncoderAdapter; import org.apache.mina.filter.codec.ProtocolEncoderOutput; /** * A {@link ProtocolEncoder} which serializes {@link Serializable} Java objects * using {@link IoBuffer#putObject(Object)}. * * @author Apache MINA Project */ public class ObjectSerializationEncoder extends ProtocolEncoderAdapter { private int maxObjectSize = Integer.MAX_VALUE; // 2GB /** * Creates a new instance. */ public ObjectSerializationEncoder() { // Do nothing } /** * Returns the allowed maximum size of the encoded object. * If the size of the encoded object exceeds this value, this encoder * will throw a {@link IllegalArgumentException}. The default value * is {@link Integer#MAX_VALUE}. */ public int getMaxObjectSize() { return maxObjectSize; } /** * Sets the allowed maximum size of the encoded object. * If the size of the encoded object exceeds this value, this encoder * will throw a {@link IllegalArgumentException}. The default value * is {@link Integer#MAX_VALUE}. */ public void setMaxObjectSize(int maxObjectSize) { if (maxObjectSize <= 0) { throw new IllegalArgumentException("maxObjectSize: " + maxObjectSize); } this.maxObjectSize = maxObjectSize; } public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { if (!(message instanceof Serializable)) { throw new NotSerializableException(); } IoBuffer buf = IoBuffer.allocate(64); buf.setAutoExpand(true); buf.putObject(message); int objectSize = buf.position() - 4; if (objectSize > maxObjectSize) { throw new IllegalArgumentException("The encoded object is too big: " + objectSize + " (> " + maxObjectSize + ')'); } buf.flip(); out.write(buf); } } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/serialization/ObjectSerializationCodecFactory.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/serialization/ObjectSerial0000644000175000017500000001014312032276025032554 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.serialization; import org.apache.mina.core.buffer.BufferDataException; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFactory; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolEncoder; /** * A {@link ProtocolCodecFactory} that serializes and deserializes Java objects. * This codec is very useful when you have to prototype your application rapidly * without any specific codec. * * @author Apache MINA Project */ public class ObjectSerializationCodecFactory implements ProtocolCodecFactory { private final ObjectSerializationEncoder encoder; private final ObjectSerializationDecoder decoder; /** * Creates a new instance with the {@link ClassLoader} of * the current thread. */ public ObjectSerializationCodecFactory() { this(Thread.currentThread().getContextClassLoader()); } /** * Creates a new instance with the specified {@link ClassLoader}. */ public ObjectSerializationCodecFactory(ClassLoader classLoader) { encoder = new ObjectSerializationEncoder(); decoder = new ObjectSerializationDecoder(classLoader); } public ProtocolEncoder getEncoder(IoSession session) { return encoder; } public ProtocolDecoder getDecoder(IoSession session) { return decoder; } /** * Returns the allowed maximum size of the encoded object. * If the size of the encoded object exceeds this value, the encoder * will throw a {@link IllegalArgumentException}. The default value * is {@link Integer#MAX_VALUE}. *

* This method does the same job with {@link ObjectSerializationEncoder#getMaxObjectSize()}. */ public int getEncoderMaxObjectSize() { return encoder.getMaxObjectSize(); } /** * Sets the allowed maximum size of the encoded object. * If the size of the encoded object exceeds this value, the encoder * will throw a {@link IllegalArgumentException}. The default value * is {@link Integer#MAX_VALUE}. *

* This method does the same job with {@link ObjectSerializationEncoder#setMaxObjectSize(int)}. */ public void setEncoderMaxObjectSize(int maxObjectSize) { encoder.setMaxObjectSize(maxObjectSize); } /** * Returns the allowed maximum size of the object to be decoded. * If the size of the object to be decoded exceeds this value, the * decoder will throw a {@link BufferDataException}. The default * value is 1048576 (1MB). *

* This method does the same job with {@link ObjectSerializationDecoder#getMaxObjectSize()}. */ public int getDecoderMaxObjectSize() { return decoder.getMaxObjectSize(); } /** * Sets the allowed maximum size of the object to be decoded. * If the size of the object to be decoded exceeds this value, the * decoder will throw a {@link BufferDataException}. The default * value is 1048576 (1MB). *

* This method does the same job with {@link ObjectSerializationDecoder#setMaxObjectSize(int)}. */ public void setDecoderMaxObjectSize(int maxObjectSize) { decoder.setMaxObjectSize(maxObjectSize); } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/serialization/ObjectSerializationDecoder.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/serialization/ObjectSerial0000644000175000017500000000630112032276025032555 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec.serialization; import java.io.Serializable; import org.apache.mina.core.buffer.BufferDataException; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.CumulativeProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * A {@link ProtocolDecoder} which deserializes {@link Serializable} Java * objects using {@link IoBuffer#getObject(ClassLoader)}. * * @author Apache MINA Project */ public class ObjectSerializationDecoder extends CumulativeProtocolDecoder { private final ClassLoader classLoader; private int maxObjectSize = 1048576; // 1MB /** * Creates a new instance with the {@link ClassLoader} of * the current thread. */ public ObjectSerializationDecoder() { this(Thread.currentThread().getContextClassLoader()); } /** * Creates a new instance with the specified {@link ClassLoader}. */ public ObjectSerializationDecoder(ClassLoader classLoader) { if (classLoader == null) { throw new IllegalArgumentException("classLoader"); } this.classLoader = classLoader; } /** * Returns the allowed maximum size of the object to be decoded. * If the size of the object to be decoded exceeds this value, this * decoder will throw a {@link BufferDataException}. The default * value is 1048576 (1MB). */ public int getMaxObjectSize() { return maxObjectSize; } /** * Sets the allowed maximum size of the object to be decoded. * If the size of the object to be decoded exceeds this value, this * decoder will throw a {@link BufferDataException}. The default * value is 1048576 (1MB). */ public void setMaxObjectSize(int maxObjectSize) { if (maxObjectSize <= 0) { throw new IllegalArgumentException("maxObjectSize: " + maxObjectSize); } this.maxObjectSize = maxObjectSize; } @Override protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { if (!in.prefixedDataAvailable(4, maxObjectSize)) { return false; } out.write(in.getObject(classLoader)); return true; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/serialization/package.html0000644000175000017500000000171612032276025032552 0ustar ebourgebourg Protocol codecs which uses Java object serilization and leads to rapid protocol implementation. ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/SynchronizedProtocolEncoder.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/SynchronizedProtocolEncode0000644000175000017500000000437212032276025032657 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import org.apache.mina.core.session.IoSession; /** * A {@link ProtocolEncoder} implementation which decorates an existing encoder * to be thread-safe. Please be careful if you're going to use this decorator * because it can be a root of performance degradation in a multi-thread * environment. Please use this decorator only when you need to synchronize * on a per-encoder basis instead of on a per-session basis, which is not * common. * * @author Apache MINA Project */ public class SynchronizedProtocolEncoder implements ProtocolEncoder { private final ProtocolEncoder encoder; /** * Creates a new instance which decorates the specified encoder. */ public SynchronizedProtocolEncoder(ProtocolEncoder encoder) { if (encoder == null) { throw new IllegalArgumentException("encoder"); } this.encoder = encoder; } /** * Returns the encoder this encoder is decorating. */ public ProtocolEncoder getEncoder() { return encoder; } public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { synchronized (encoder) { encoder.encode(session, message, out); } } public void dispose(IoSession session) throws Exception { synchronized (encoder) { encoder.dispose(session); } } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/RecoverableProtocolDecoderException.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/RecoverableProtocolDecoder0000644000175000017500000000447012032276025032600 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; /** * A special exception that tells the {@link ProtocolDecoder} can keep * decoding even after this exception is thrown. *

* Once {@link ProtocolCodecFilter} catches any other type of exception * than {@link RecoverableProtocolDecoderException}, it stops calling * the {@link ProtocolDecoder#decode(org.apache.mina.core.session.IoSession, * org.apache.mina.core.buffer.IoBuffer, ProtocolDecoderOutput)} * immediately and fires an exceptionCaught event. *

* On the other hand, if {@link RecoverableProtocolDecoderException} is thrown, * it doesn't stop immediately but keeps calling the {@link ProtocolDecoder} * as long as the position of the read buffer changes. *

* {@link RecoverableProtocolDecoderException} is useful for a robust * {@link ProtocolDecoder} that can continue decoding even after any * protocol violation. * * @author Apache MINA Project */ public class RecoverableProtocolDecoderException extends ProtocolDecoderException { private static final long serialVersionUID = -8172624045024880678L; public RecoverableProtocolDecoderException() { // Do nothing } public RecoverableProtocolDecoderException(String message) { super(message); } public RecoverableProtocolDecoderException(Throwable cause) { super(cause); } public RecoverableProtocolDecoderException(String message, Throwable cause) { super(message, cause); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/ProtocolEncoder.java0000644000175000017500000000461312032276025031357 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; /** * Encodes higher-level message objects into binary or protocol-specific data. * MINA invokes {@link #encode(IoSession, Object, ProtocolEncoderOutput)} * method with message which is popped from the session write queue, and then * the encoder implementation puts encoded messages (typically {@link IoBuffer}s) * into {@link ProtocolEncoderOutput} by calling {@link ProtocolEncoderOutput#write(Object)}. *

* Please refer to * TextLineEncoder * example. * * @author Apache MINA Project * * @see ProtocolEncoderException */ public interface ProtocolEncoder { /** * Encodes higher-level message objects into binary or protocol-specific data. * MINA invokes {@link #encode(IoSession, Object, ProtocolEncoderOutput)} * method with message which is popped from the session write queue, and then * the encoder implementation puts encoded messages (typically {@link IoBuffer}s) * into {@link ProtocolEncoderOutput}. * * @throws Exception if the message violated protocol specification */ void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception; /** * Releases all resources related with this encoder. * * @throws Exception if failed to dispose all resources */ void dispose(IoSession session) throws Exception; }././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/AbstractProtocolDecoderOutput.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/AbstractProtocolDecoderOut0000644000175000017500000000305512032276026032601 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.codec; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; /** * A {@link ProtocolDecoderOutput} based on queue. * * @author Apache MINA Project */ public abstract class AbstractProtocolDecoderOutput implements ProtocolDecoderOutput { private final Queue messageQueue = new ConcurrentLinkedQueue(); public AbstractProtocolDecoderOutput() { // Do nothing } public Queue getMessageQueue() { return messageQueue; } public void write(Object message) { if (message == null) { throw new IllegalArgumentException("message"); } messageQueue.add(message); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/codec/package.html0000644000175000017500000000171012032276025027667 0ustar ebourgebourg Filter implementations that helps you to implement complex protocols via 'codec' concept. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/util/0000755000175000017500000000000012162575507025322 5ustar ebourgebourg././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/util/SessionAttributeInitializingFilter.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/util/SessionAttributeInitializin0000644000175000017500000001171412032276026032752 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.util; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.session.IoSession; /** * An {@link IoFilter} that sets initial attributes when a new * {@link IoSession} is created. By default, the attribute map is empty when * an {@link IoSession} is newly created. Inserting this filter will make * the pre-configured attributes available after this filter executes the * sessionCreated event. * * @author Apache MINA Project * @org.apache.xbean.XBean */ public class SessionAttributeInitializingFilter extends IoFilterAdapter { private final Map attributes = new ConcurrentHashMap(); /** * Creates a new instance with no default attributes. You can set * the additional attributes by calling methods such as * {@link #setAttribute(String, Object)} and {@link #setAttributes(Map)}. */ public SessionAttributeInitializingFilter() { // Do nothing } /** * Creates a new instance with the specified default attributes. You can * set the additional attributes by calling methods such as * {@link #setAttribute(String, Object)} and {@link #setAttributes(Map)}. */ public SessionAttributeInitializingFilter(Map attributes) { setAttributes(attributes); } /** * Returns the value of user-defined attribute. * * @param key the key of the attribute * @return null if there is no attribute with the specified key */ public Object getAttribute(String key) { return attributes.get(key); } /** * Sets a user-defined attribute. * * @param key the key of the attribute * @param value the value of the attribute * @return The old value of the attribute. null if it is new. */ public Object setAttribute(String key, Object value) { if (value == null) { return removeAttribute(key); } return attributes.put(key, value); } /** * Sets a user defined attribute without a value. This is useful when * you just want to put a 'mark' attribute. Its value is set to * {@link Boolean#TRUE}. * * @param key the key of the attribute * @return The old value of the attribute. null if it is new. */ public Object setAttribute(String key) { return attributes.put(key, Boolean.TRUE); } /** * Removes a user-defined attribute with the specified key. * * @return The old value of the attribute. null if not found. */ public Object removeAttribute(String key) { return attributes.remove(key); } /** * Returns true if this session contains the attribute with * the specified key. */ boolean containsAttribute(String key) { return attributes.containsKey(key); } /** * Returns the set of keys of all user-defined attributes. */ public Set getAttributeKeys() { return attributes.keySet(); } /** * Sets the attribute map. The specified attributes are copied into the * underlying map, so modifying the specified attributes parameter after * the call won't change the internal state. */ public void setAttributes(Map attributes) { if (attributes == null) { attributes = new ConcurrentHashMap(); } this.attributes.clear(); this.attributes.putAll(attributes); } /** * Puts all pre-configured attributes into the actual session attribute * map and forward the event to the next filter. */ @Override public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception { for (Map.Entry e : attributes.entrySet()) { session.setAttribute(e.getKey(), e.getValue()); } nextFilter.sessionCreated(session); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/util/ReferenceCountingFilter.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/util/ReferenceCountingFilter.jav0000644000175000017500000001017212032276026032566 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.util; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; /** * An {@link IoFilter}s wrapper that keeps track of the number of usages of this filter and will call init/destroy * when the filter is not in use. * * @author Apache MINA Project * @org.apache.xbean.XBean */ public class ReferenceCountingFilter extends IoFilterAdapter { private final IoFilter filter; private int count = 0; public ReferenceCountingFilter(IoFilter filter) { this.filter = filter; } public void init() throws Exception { // no-op, will init on-demand in pre-add if count == 0 } public void destroy() throws Exception { //no-op, will destroy on-demand in post-remove if count == 0 } public synchronized void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { if (0 == count) { filter.init(); } ++count; filter.onPreAdd(parent, name, nextFilter); } public synchronized void onPostRemove(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { filter.onPostRemove(parent, name, nextFilter); --count; if (0 == count) { filter.destroy(); } } public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) throws Exception { filter.exceptionCaught(nextFilter, session, cause); } public void filterClose(NextFilter nextFilter, IoSession session) throws Exception { filter.filterClose(nextFilter, session); } public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { filter.filterWrite(nextFilter, session, writeRequest); } public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception { filter.messageReceived(nextFilter, session, message); } public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { filter.messageSent(nextFilter, session, writeRequest); } public void onPostAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { filter.onPostAdd(parent, name, nextFilter); } public void onPreRemove(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { filter.onPreRemove(parent, name, nextFilter); } public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception { filter.sessionClosed(nextFilter, session); } public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception { filter.sessionCreated(nextFilter, session); } public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception { filter.sessionIdle(nextFilter, session, status); } public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception { filter.sessionOpened(nextFilter, session); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/util/WriteRequestFilter.java0000644000175000017500000000624312032276026031771 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.util; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.session.IoEventType; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.core.write.WriteRequestWrapper; /** * An abstract {@link IoFilter} that simplifies the implementation of * an {@link IoFilter} that filters an {@link IoEventType#WRITE} event. * * @author Apache MINA Project * */ public abstract class WriteRequestFilter extends IoFilterAdapter { @Override public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { Object filteredMessage = doFilterWrite(nextFilter, session, writeRequest); if (filteredMessage != null && filteredMessage != writeRequest.getMessage()) { nextFilter.filterWrite(session, new FilteredWriteRequest(filteredMessage, writeRequest)); } else { nextFilter.filterWrite(session, writeRequest); } } @Override public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { if (writeRequest instanceof FilteredWriteRequest) { FilteredWriteRequest req = (FilteredWriteRequest) writeRequest; if (req.getParent() == this) { nextFilter.messageSent(session, req.getParentRequest()); return; } } nextFilter.messageSent(session, writeRequest); } protected abstract Object doFilterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception; private class FilteredWriteRequest extends WriteRequestWrapper { private final Object filteredMessage; public FilteredWriteRequest(Object filteredMessage, WriteRequest writeRequest) { super(writeRequest); if (filteredMessage == null) { throw new IllegalArgumentException("filteredMessage"); } this.filteredMessage = filteredMessage; } public WriteRequestFilter getParent() { return WriteRequestFilter.this; } @Override public Object getMessage() { return filteredMessage; } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/util/NoopFilter.java0000644000175000017500000000257012032276026030240 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.util; import org.apache.mina.core.filterchain.IoFilterAdapter; /** * A Noop filter. It does nothing, as all the method are already implemented * in the super class.
* * This class is used by tests, when some faked filter is needed to test that the * chain is working properly when adding or removing a filter. * * @author Apache MINA Project */ public class NoopFilter extends IoFilterAdapter { /** * Default Constructor. */ public NoopFilter() { super(); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/util/CommonEventFilter.java0000644000175000017500000000672212032276026031562 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.util; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.filterchain.IoFilterEvent; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoEventType; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; /** * Extend this class when you want to create a filter that * wraps the same logic around all 9 IoEvents * * @author Apache MINA Project */ public abstract class CommonEventFilter extends IoFilterAdapter { public CommonEventFilter() { // Do nothing } protected abstract void filter(IoFilterEvent event) throws Exception; @Override public final void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception { filter(new IoFilterEvent(nextFilter, IoEventType.SESSION_CREATED, session, null)); } @Override public final void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception { filter(new IoFilterEvent(nextFilter, IoEventType.SESSION_OPENED, session, null)); } @Override public final void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception { filter(new IoFilterEvent(nextFilter, IoEventType.SESSION_CLOSED, session, null)); } @Override public final void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception { filter(new IoFilterEvent(nextFilter, IoEventType.SESSION_IDLE, session, status)); } @Override public final void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) throws Exception { filter(new IoFilterEvent(nextFilter, IoEventType.EXCEPTION_CAUGHT, session, cause)); } @Override public final void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception { filter(new IoFilterEvent(nextFilter, IoEventType.MESSAGE_RECEIVED, session, message)); } @Override public final void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { filter(new IoFilterEvent(nextFilter, IoEventType.MESSAGE_SENT, session, writeRequest)); } @Override public final void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { filter(new IoFilterEvent(nextFilter, IoEventType.WRITE, session, writeRequest)); } @Override public final void filterClose(NextFilter nextFilter, IoSession session) throws Exception { filter(new IoFilterEvent(nextFilter, IoEventType.CLOSE, session, null)); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/util/package.html0000644000175000017500000000165512032276026027600 0ustar ebourgebourg Utility classes for the MINA filtering portion of the library. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/reqres/0000755000175000017500000000000012162575507025646 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/reqres/Response.java0000644000175000017500000000471012032276023030274 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.reqres; /** * TODO Add documentation * * @author Apache MINA Project */ public class Response { private final Request request; private final ResponseType type; private final Object message; public Response(Request request, Object message, ResponseType type) { if (request == null) { throw new IllegalArgumentException("request"); } if (message == null) { throw new IllegalArgumentException("message"); } if (type == null) { throw new IllegalArgumentException("type"); } this.request = request; this.type = type; this.message = message; } public Request getRequest() { return request; } public ResponseType getType() { return type; } public Object getMessage() { return message; } @Override public int hashCode() { return getRequest().getId().hashCode(); } @Override public boolean equals(Object o) { if (o == this) { return true; } if (o == null) { return false; } if (!(o instanceof Response)) { return false; } Response that = (Response) o; if (!this.getRequest().equals(that.getRequest())) { return false; } return this.getType().equals(that.getType()); } @Override public String toString() { return "response: { requestId=" + getRequest().getId() + ", type=" + getType() + ", message=" + getMessage() + " }"; } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/reqres/RequestTimeoutException.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/reqres/RequestTimeoutException.j0000644000175000017500000000470212032276023032665 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.reqres; import org.apache.mina.core.RuntimeIoException; /** * An {@link RuntimeIoException} which is thrown when a {@link Request} is timed out. * * @author Apache MINA Project */ public class RequestTimeoutException extends RuntimeException { private static final long serialVersionUID = 5546784978950631652L; private final Request request; /** * Creates a new exception. */ public RequestTimeoutException(Request request) { if (request == null) { throw new IllegalArgumentException("request"); } this.request = request; } /** * Creates a new exception. */ public RequestTimeoutException(Request request, String s) { super(s); if (request == null) { throw new IllegalArgumentException("request"); } this.request = request; } /** * Creates a new exception. */ public RequestTimeoutException(Request request, String message, Throwable cause) { super(message); initCause(cause); if (request == null) { throw new IllegalArgumentException("request"); } this.request = request; } /** * Creates a new exception. */ public RequestTimeoutException(Request request, Throwable cause) { initCause(cause); if (request == null) { throw new IllegalArgumentException("request"); } this.request = request; } /** * Returns the request which has timed out. */ public Request getRequest() { return request; } }././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/reqres/ResponseInspectorFactory.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/reqres/ResponseInspectorFactory.0000644000175000017500000000214312032276023032647 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.reqres; /** * TODO Add documentation * * @author Apache MINA Project */ public interface ResponseInspectorFactory { /** * Returns a {@link ResponseInspector}. */ ResponseInspector getResponseInspector(); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/reqres/ResponseType.java0000644000175000017500000000305712032276023031141 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.reqres; /** * Type of Response contained within the {@code Response} class * * Response can be either a single entity or a multiple partial messages, in which * case PARTIAL_LAST signifies the end of partial messages * * For response contained within a single message/entity the ResponseType shall be * WHOLE * * For response with multiple partial messages, we have respnse type sepcified as * * [PARTIAL]+ PARTIAL_LAST * * meaning, we have One or more PARTIAL response type with one PARTIAL_LAST which * signifies end of partial messages or completion of response message * * @author Apache MINA Project */ public enum ResponseType { WHOLE, PARTIAL, PARTIAL_LAST; } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/reqres/ResponseInspector.java0000644000175000017500000000211612032276023032161 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.reqres; /** * TODO Add documentation * * @author Apache MINA Project */ public interface ResponseInspector { Object getRequestId(Object message); ResponseType getResponseType(Object message); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/reqres/Request.java0000644000175000017500000001355412032276023030134 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.reqres; import java.util.NoSuchElementException; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; /** * TODO Add documentation * * @author Apache MINA Project */ public class Request { private final Object id; private final Object message; private final long timeoutMillis; private volatile Runnable timeoutTask; private volatile ScheduledFuture timeoutFuture; private final BlockingQueue responses; private volatile boolean endOfResponses; public Request(Object id, Object message, long timeoutMillis) { this(id, message, true, timeoutMillis); } public Request(Object id, Object message, boolean useResponseQueue, long timeoutMillis) { this(id, message, useResponseQueue, timeoutMillis, TimeUnit.MILLISECONDS); } public Request(Object id, Object message, long timeout, TimeUnit unit) { this(id, message, true, timeout, unit); } public Request(Object id, Object message, boolean useResponseQueue, long timeout, TimeUnit unit) { if (id == null) { throw new IllegalArgumentException("id"); } if (message == null) { throw new IllegalArgumentException("message"); } if (timeout < 0) { throw new IllegalArgumentException("timeout: " + timeout + " (expected: 0+)"); } else if (timeout == 0) { timeout = Long.MAX_VALUE; } if (unit == null) { throw new IllegalArgumentException("unit"); } this.id = id; this.message = message; this.responses = useResponseQueue ? new LinkedBlockingQueue() : null; this.timeoutMillis = unit.toMillis(timeout); } public Object getId() { return id; } public Object getMessage() { return message; } public long getTimeoutMillis() { return timeoutMillis; } public boolean isUseResponseQueue() { return responses != null; } public boolean hasResponse() { checkUseResponseQueue(); return !responses.isEmpty(); } public Response awaitResponse() throws RequestTimeoutException, InterruptedException { checkUseResponseQueue(); chechEndOfResponses(); return convertToResponse(responses.take()); } public Response awaitResponse(long timeout, TimeUnit unit) throws RequestTimeoutException, InterruptedException { checkUseResponseQueue(); chechEndOfResponses(); return convertToResponse(responses.poll(timeout, unit)); } private Response convertToResponse(Object o) { if (o instanceof Response) { return (Response) o; } if (o == null) { return null; } throw (RequestTimeoutException) o; } public Response awaitResponseUninterruptibly() throws RequestTimeoutException { for (;;) { try { return awaitResponse(); } catch (InterruptedException e) { // Do nothing } } } private void chechEndOfResponses() { if (responses != null && endOfResponses && responses.isEmpty()) { throw new NoSuchElementException("All responses has been retrieved already."); } } private void checkUseResponseQueue() { if (responses == null) { throw new UnsupportedOperationException("Response queue is not available; useResponseQueue is false."); } } void signal(Response response) { signal0(response); if (response.getType() != ResponseType.PARTIAL) { endOfResponses = true; } } void signal(RequestTimeoutException e) { signal0(e); endOfResponses = true; } private void signal0(Object answer) { if (responses != null) { responses.add(answer); } } @Override public int hashCode() { return getId().hashCode(); } @Override public boolean equals(Object o) { if (o == this) { return true; } if (o == null) { return false; } if (!(o instanceof Request)) { return false; } Request that = (Request) o; return this.getId().equals(that.getId()); } @Override public String toString() { String timeout = getTimeoutMillis() == Long.MAX_VALUE ? "max" : String.valueOf(getTimeoutMillis()); return "request: { id=" + getId() + ", timeout=" + timeout + ", message=" + getMessage() + " }"; } Runnable getTimeoutTask() { return timeoutTask; } void setTimeoutTask(Runnable timeoutTask) { this.timeoutTask = timeoutTask; } ScheduledFuture getTimeoutFuture() { return timeoutFuture; } void setTimeoutFuture(ScheduledFuture timeoutFuture) { this.timeoutFuture = timeoutFuture; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/reqres/RequestResponseFilter.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/reqres/RequestResponseFilter.jav0000644000175000017500000003263012032276023032654 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.reqres; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.filter.util.WriteRequestFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * TODO Add documentation * * @author Apache MINA Project * @org.apache.xbean.XBean */ public class RequestResponseFilter extends WriteRequestFilter { private final AttributeKey RESPONSE_INSPECTOR = new AttributeKey(getClass(), "responseInspector"); private final AttributeKey REQUEST_STORE = new AttributeKey(getClass(), "requestStore"); private final AttributeKey UNRESPONDED_REQUEST_STORE = new AttributeKey(getClass(), "unrespondedRequestStore"); private final ResponseInspectorFactory responseInspectorFactory; private final ScheduledExecutorService timeoutScheduler; private final static Logger LOGGER = LoggerFactory.getLogger(RequestResponseFilter.class); public RequestResponseFilter(final ResponseInspector responseInspector, ScheduledExecutorService timeoutScheduler) { if (responseInspector == null) { throw new IllegalArgumentException("responseInspector"); } if (timeoutScheduler == null) { throw new IllegalArgumentException("timeoutScheduler"); } this.responseInspectorFactory = new ResponseInspectorFactory() { public ResponseInspector getResponseInspector() { return responseInspector; } }; this.timeoutScheduler = timeoutScheduler; } public RequestResponseFilter(ResponseInspectorFactory responseInspectorFactory, ScheduledExecutorService timeoutScheduler) { if (responseInspectorFactory == null) { throw new IllegalArgumentException("responseInspectorFactory"); } if (timeoutScheduler == null) { throw new IllegalArgumentException("timeoutScheduler"); } this.responseInspectorFactory = responseInspectorFactory; this.timeoutScheduler = timeoutScheduler; } @Override public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { if (parent.contains(this)) { throw new IllegalArgumentException( "You can't add the same filter instance more than once. Create another instance and add it."); } IoSession session = parent.getSession(); session.setAttribute(RESPONSE_INSPECTOR, responseInspectorFactory.getResponseInspector()); session.setAttribute(REQUEST_STORE, createRequestStore(session)); session.setAttribute(UNRESPONDED_REQUEST_STORE, createUnrespondedRequestStore(session)); } @Override public void onPostRemove(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { IoSession session = parent.getSession(); destroyUnrespondedRequestStore(getUnrespondedRequestStore(session)); destroyRequestStore(getRequestStore(session)); session.removeAttribute(UNRESPONDED_REQUEST_STORE); session.removeAttribute(REQUEST_STORE); session.removeAttribute(RESPONSE_INSPECTOR); } @Override public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception { ResponseInspector responseInspector = (ResponseInspector) session.getAttribute(RESPONSE_INSPECTOR); Object requestId = responseInspector.getRequestId(message); if (requestId == null) { // Not a response message. Ignore. nextFilter.messageReceived(session, message); return; } // Retrieve (or remove) the corresponding request. ResponseType type = responseInspector.getResponseType(message); if (type == null) { nextFilter.exceptionCaught(session, new IllegalStateException(responseInspector.getClass().getName() + "#getResponseType() may not return null.")); } Map requestStore = getRequestStore(session); Request request; switch (type) { case WHOLE: case PARTIAL_LAST: synchronized (requestStore) { request = requestStore.remove(requestId); } break; case PARTIAL: synchronized (requestStore) { request = requestStore.get(requestId); } break; default: throw new InternalError(); } if (request == null) { // A response message without request. Swallow the event because // the response might have arrived too late. if (LOGGER.isWarnEnabled()) { LOGGER.warn("Unknown request ID '" + requestId + "' for the response message. Timed out already?: " + message); } } else { // Found a matching request. // Cancel the timeout task if needed. if (type != ResponseType.PARTIAL) { ScheduledFuture scheduledFuture = request.getTimeoutFuture(); if (scheduledFuture != null) { scheduledFuture.cancel(false); Set unrespondedRequests = getUnrespondedRequestStore(session); synchronized (unrespondedRequests) { unrespondedRequests.remove(request); } } } // And forward the event. Response response = new Response(request, message, type); request.signal(response); nextFilter.messageReceived(session, response); } } @Override protected Object doFilterWrite(final NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { Object message = writeRequest.getMessage(); if (!(message instanceof Request)) { return null; } final Request request = (Request) message; if (request.getTimeoutFuture() != null) { throw new IllegalArgumentException("Request can not be reused."); } Map requestStore = getRequestStore(session); Object oldValue = null; Object requestId = request.getId(); synchronized (requestStore) { oldValue = requestStore.get(requestId); if (oldValue == null) { requestStore.put(requestId, request); } } if (oldValue != null) { throw new IllegalStateException("Duplicate request ID: " + request.getId()); } // Schedule a task to be executed on timeout. TimeoutTask timeoutTask = new TimeoutTask(nextFilter, request, session); ScheduledFuture timeoutFuture = timeoutScheduler.schedule(timeoutTask, request.getTimeoutMillis(), TimeUnit.MILLISECONDS); request.setTimeoutTask(timeoutTask); request.setTimeoutFuture(timeoutFuture); // Add the timeout task to the unfinished task set. Set unrespondedRequests = getUnrespondedRequestStore(session); synchronized (unrespondedRequests) { unrespondedRequests.add(request); } return request.getMessage(); } @Override public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception { // Copy the unfinished task set to avoid unnecessary lock acquisition. // Copying will be cheap because there won't be that many requests queued. Set unrespondedRequests = getUnrespondedRequestStore(session); List unrespondedRequestsCopy; synchronized (unrespondedRequests) { unrespondedRequestsCopy = new ArrayList(unrespondedRequests); unrespondedRequests.clear(); } // Generate timeout artificially. for (Request r : unrespondedRequestsCopy) { if (r.getTimeoutFuture().cancel(false)) { r.getTimeoutTask().run(); } } // Clear the request store just in case we missed something, though it's unlikely. Map requestStore = getRequestStore(session); synchronized (requestStore) { requestStore.clear(); } // Now tell the main subject. nextFilter.sessionClosed(session); } @SuppressWarnings("unchecked") private Map getRequestStore(IoSession session) { return (Map) session.getAttribute(REQUEST_STORE); } @SuppressWarnings("unchecked") private Set getUnrespondedRequestStore(IoSession session) { return (Set) session.getAttribute(UNRESPONDED_REQUEST_STORE); } /** * Returns a {@link Map} which stores {@code messageId}-{@link Request} * pairs whose {@link Response}s are not received yet. Please override * this method if you need to use other {@link Map} implementation * than the default one ({@link HashMap}). */ protected Map createRequestStore(IoSession session) { return new ConcurrentHashMap(); } /** * Returns a {@link Set} which stores {@link Request} whose * {@link Response}s are not received yet. Please override * this method if you need to use other {@link Set} implementation * than the default one ({@link LinkedHashSet}). Please note that * the {@link Iterator} of the returned {@link Set} have to iterate * its elements in the insertion order to ensure that * {@link RequestTimeoutException}s are thrown in the order which * {@link Request}s were written. If you don't need to guarantee * the order of thrown exceptions, any {@link Set} implementation * can be used. */ protected Set createUnrespondedRequestStore(IoSession session) { return new LinkedHashSet(); } /** * Releases any resources related with the {@link Map} created by * {@link #createRequestStore(IoSession)}. This method is useful * if you override {@link #createRequestStore(IoSession)}. * * @param requestStore what you returned in {@link #createRequestStore(IoSession)} */ protected void destroyRequestStore(Map requestStore) { // Do nothing } /** * Releases any resources related with the {@link Set} created by * {@link #createUnrespondedRequestStore(IoSession)}. This method is * useful if you override {@link #createUnrespondedRequestStore(IoSession)}. * * @param unrespondedRequestStore what you returned in {@link #createUnrespondedRequestStore(IoSession)} */ protected void destroyUnrespondedRequestStore(Set unrespondedRequestStore) { // Do nothing } private class TimeoutTask implements Runnable { private final NextFilter filter; private final Request request; private final IoSession session; private TimeoutTask(NextFilter filter, Request request, IoSession session) { this.filter = filter; this.request = request; this.session = session; } public void run() { Set unrespondedRequests = getUnrespondedRequestStore(session); if (unrespondedRequests != null) { synchronized (unrespondedRequests) { unrespondedRequests.remove(request); } } Map requestStore = getRequestStore(session); Object requestId = request.getId(); boolean timedOut; synchronized (requestStore) { if (requestStore.get(requestId) == request) { requestStore.remove(requestId); timedOut = true; } else { timedOut = false; } } if (timedOut) { // Throw the exception only when it's really timed out. RequestTimeoutException e = new RequestTimeoutException(request); request.signal(e); filter.exceptionCaught(session, e); } } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/errorgenerating/0000755000175000017500000000000012162575507027542 5ustar ebourgebourg././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/errorgenerating/ErrorGeneratingFilter.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/errorgenerating/ErrorGeneratingF0000644000175000017500000002533112032276026032662 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.filter.errorgenerating; import java.util.Random; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.DefaultWriteRequest; import org.apache.mina.core.write.WriteRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An {@link IoFilter} implementation generating random bytes and PDU modification in * your communication streams. * It's quite simple to use : * ErrorGeneratingFilter egf = new ErrorGeneratingFilter(); * For activate the change of some bytes in your {@link IoBuffer}, for a probability of 200 out * of 1000 {@link IoBuffer} processed : * egf.setChangeByteProbability(200); * For activate the insertion of some bytes in your {@link IoBuffer}, for a * probability of 200 out of 1000 : * egf.setInsertByteProbability(200); * And for the removing of some bytes : * egf.setRemoveByteProbability(200); * You can activate the error generation for write or read with the * following methods : * egf.setManipulateReads(true); * egf.setManipulateWrites(true); * * @author Apache MINA Project * @org.apache.xbean.XBean */ public class ErrorGeneratingFilter extends IoFilterAdapter { private int removeByteProbability = 0; private int insertByteProbability = 0; private int changeByteProbability = 0; private int removePduProbability = 0; private int duplicatePduProbability = 0; private int resendPduLasterProbability = 0; private int maxInsertByte = 10; private boolean manipulateWrites = false; private boolean manipulateReads = false; private Random rng = new Random(); final private Logger logger = LoggerFactory.getLogger(ErrorGeneratingFilter.class); @Override public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { if (manipulateWrites) { // manipulate bytes if (writeRequest.getMessage() instanceof IoBuffer) { manipulateIoBuffer(session, (IoBuffer) writeRequest.getMessage()); IoBuffer buffer = insertBytesToNewIoBuffer(session, (IoBuffer) writeRequest.getMessage()); if (buffer != null) { writeRequest = new DefaultWriteRequest(buffer, writeRequest.getFuture(), writeRequest.getDestination()); } // manipulate PDU } else { if (duplicatePduProbability > rng.nextInt()) { nextFilter.filterWrite(session, writeRequest); } if (resendPduLasterProbability > rng.nextInt()) { // store it somewhere and trigger a write execution for // later // TODO } if (removePduProbability > rng.nextInt()) { return; } } } nextFilter.filterWrite(session, writeRequest); } @Override public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception { if (manipulateReads) { if (message instanceof IoBuffer) { // manipulate bytes manipulateIoBuffer(session, (IoBuffer) message); IoBuffer buffer = insertBytesToNewIoBuffer(session, (IoBuffer) message); if (buffer != null) { message = buffer; } } else { // manipulate PDU // TODO } } nextFilter.messageReceived(session, message); } private IoBuffer insertBytesToNewIoBuffer(IoSession session, IoBuffer buffer) { if (insertByteProbability > rng.nextInt(1000)) { logger.info(buffer.getHexDump()); // where to insert bytes ? int pos = rng.nextInt(buffer.remaining()) - 1; // how many byte to insert ? int count = rng.nextInt(maxInsertByte - 1) + 1; IoBuffer newBuff = IoBuffer.allocate(buffer.remaining() + count); for (int i = 0; i < pos; i++) newBuff.put(buffer.get()); for (int i = 0; i < count; i++) { newBuff.put((byte) (rng.nextInt(256))); } while (buffer.remaining() > 0) { newBuff.put(buffer.get()); } newBuff.flip(); logger.info("Inserted " + count + " bytes."); logger.info(newBuff.getHexDump()); return newBuff; } return null; } private void manipulateIoBuffer(IoSession session, IoBuffer buffer) { if ((buffer.remaining() > 0) && (removeByteProbability > rng.nextInt(1000))) { logger.info(buffer.getHexDump()); // where to remove bytes ? int pos = rng.nextInt(buffer.remaining()); // how many byte to remove ? int count = rng.nextInt(buffer.remaining() - pos) + 1; if (count == buffer.remaining()) count = buffer.remaining() - 1; IoBuffer newBuff = IoBuffer.allocate(buffer.remaining() - count); for (int i = 0; i < pos; i++) newBuff.put(buffer.get()); buffer.skip(count); // hole while (newBuff.remaining() > 0) newBuff.put(buffer.get()); newBuff.flip(); // copy the new buffer in the old one buffer.rewind(); buffer.put(newBuff); buffer.flip(); logger.info("Removed " + count + " bytes at position " + pos + "."); logger.info(buffer.getHexDump()); } if ((buffer.remaining() > 0) && (changeByteProbability > rng.nextInt(1000))) { logger.info(buffer.getHexDump()); // how many byte to change ? int count = rng.nextInt(buffer.remaining() - 1) + 1; byte[] values = new byte[count]; rng.nextBytes(values); for (int i = 0; i < values.length; i++) { int pos = rng.nextInt(buffer.remaining()); buffer.put(pos, values[i]); } logger.info("Modified " + count + " bytes."); logger.info(buffer.getHexDump()); } } public int getChangeByteProbability() { return changeByteProbability; } /** * Set the probability for the change byte error. * If this probability is > 0 the filter will modify a random number of byte * of the processed {@link IoBuffer}. * @param changeByteProbability probability of modifying an IoBuffer out of 1000 processed {@link IoBuffer} */ public void setChangeByteProbability(int changeByteProbability) { this.changeByteProbability = changeByteProbability; } public int getDuplicatePduProbability() { return duplicatePduProbability; } /** * not functional ATM * @param duplicatePduProbability */ public void setDuplicatePduProbability(int duplicatePduProbability) { this.duplicatePduProbability = duplicatePduProbability; } public int getInsertByteProbability() { return insertByteProbability; } /** * Set the probability for the insert byte error. * If this probability is > 0 the filter will insert a random number of byte * in the processed {@link IoBuffer}. * @param changeByteProbability probability of inserting in IoBuffer out of 1000 processed {@link IoBuffer} */ public void setInsertByteProbability(int insertByteProbability) { this.insertByteProbability = insertByteProbability; } public boolean isManipulateReads() { return manipulateReads; } /** * Set to true if you want to apply error to the read {@link IoBuffer} * @param manipulateReads */ public void setManipulateReads(boolean manipulateReads) { this.manipulateReads = manipulateReads; } public boolean isManipulateWrites() { return manipulateWrites; } /** * Set to true if you want to apply error to the written {@link IoBuffer} * @param manipulateWrites */ public void setManipulateWrites(boolean manipulateWrites) { this.manipulateWrites = manipulateWrites; } public int getRemoveByteProbability() { return removeByteProbability; } /** * Set the probability for the remove byte error. * If this probability is > 0 the filter will remove a random number of byte * in the processed {@link IoBuffer}. * @param changeByteProbability probability of modifying an {@link IoBuffer} out of 1000 processed IoBuffer */ public void setRemoveByteProbability(int removeByteProbability) { this.removeByteProbability = removeByteProbability; } public int getRemovePduProbability() { return removePduProbability; } /** * not functional ATM * @param removePduProbability */ public void setRemovePduProbability(int removePduProbability) { this.removePduProbability = removePduProbability; } public int getResendPduLasterProbability() { return resendPduLasterProbability; } /** * not functional ATM * @param resendPduLasterProbability */ public void setResendPduLasterProbability(int resendPduLasterProbability) { this.resendPduLasterProbability = resendPduLasterProbability; } public int getMaxInsertByte() { return maxInsertByte; } /** * Set the maximum number of byte the filter can insert in a {@link IoBuffer}. * The default value is 10. * @param maxInsertByte maximum bytes inserted in a {@link IoBuffer} */ public void setMaxInsertByte(int maxInsertByte) { this.maxInsertByte = maxInsertByte; } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/errorgenerating/package.html0000644000175000017500000000166712032276026032023 0ustar ebourgebourg An IoFilter that provides flexible error generation facilities. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/filter/package.html0000644000175000017500000000163012032276026026614 0ustar ebourgebourg Useful IoFilter implementations. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/0000755000175000017500000000000012032276032025077 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/0000755000175000017500000000000012162575507026404 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/SocketConnector.java0000644000175000017500000000300712032276033032336 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket; import java.net.InetSocketAddress; import org.apache.mina.core.service.IoConnector; /** * {@link IoConnector} for socket transport (TCP/IP). * * @author Apache MINA Project */ public interface SocketConnector extends IoConnector { /** * {@inheritDoc} */ InetSocketAddress getDefaultRemoteAddress(); /** * TODO : add documentation * @param remoteAddress */ void setDefaultRemoteAddress(InetSocketAddress remoteAddress); /** * Returns the default configuration of the new SocketSessions created by * this connect service. */ SocketSessionConfig getSessionConfig(); }././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/DatagramSessionConfig.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/DatagramSessionConfig.0000644000175000017500000000504212032276033032604 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket; import java.net.DatagramSocket; import java.net.PortUnreachableException; import org.apache.mina.core.session.IoSessionConfig; /** * An {@link IoSessionConfig} for datagram transport type. * * @author Apache MINA Project */ public interface DatagramSessionConfig extends IoSessionConfig { /** * @see DatagramSocket#getBroadcast() */ boolean isBroadcast(); /** * @see DatagramSocket#setBroadcast(boolean) */ void setBroadcast(boolean broadcast); /** * @see DatagramSocket#getReuseAddress() */ boolean isReuseAddress(); /** * @see DatagramSocket#setReuseAddress(boolean) */ void setReuseAddress(boolean reuseAddress); /** * @see DatagramSocket#getReceiveBufferSize() */ int getReceiveBufferSize(); /** * @see DatagramSocket#setReceiveBufferSize(int) */ void setReceiveBufferSize(int receiveBufferSize); /** * @see DatagramSocket#getSendBufferSize() */ int getSendBufferSize(); /** * @see DatagramSocket#setSendBufferSize(int) */ void setSendBufferSize(int sendBufferSize); /** * @see DatagramSocket#getTrafficClass() */ int getTrafficClass(); /** * @see DatagramSocket#setTrafficClass(int) */ void setTrafficClass(int trafficClass); /** * If method returns true, it means session should be closed when a * {@link PortUnreachableException} occurs. */ boolean isCloseOnPortUnreachable(); /** * Sets if the session should be closed if an {@link PortUnreachableException} * occurs. */ void setCloseOnPortUnreachable(boolean closeOnPortUnreachable); } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/SocketSessionConfig.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/SocketSessionConfig.ja0000644000175000017500000000625612032276033032637 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket; import java.net.Socket; import org.apache.mina.core.session.IoSessionConfig; /** * An {@link IoSessionConfig} for socket transport type. * * @author Apache MINA Project */ public interface SocketSessionConfig extends IoSessionConfig { /** * @see Socket#getReuseAddress() */ boolean isReuseAddress(); /** * @see Socket#setReuseAddress(boolean) */ void setReuseAddress(boolean reuseAddress); /** * @see Socket#getReceiveBufferSize() */ int getReceiveBufferSize(); /** * @see Socket#setReceiveBufferSize(int) */ void setReceiveBufferSize(int receiveBufferSize); /** * @see Socket#getSendBufferSize() */ int getSendBufferSize(); /** * @see Socket#setSendBufferSize(int) */ void setSendBufferSize(int sendBufferSize); /** * @see Socket#getTrafficClass() */ int getTrafficClass(); /** * @see Socket#setTrafficClass(int) */ void setTrafficClass(int trafficClass); /** * @see Socket#getKeepAlive() */ boolean isKeepAlive(); /** * @see Socket#setKeepAlive(boolean) */ void setKeepAlive(boolean keepAlive); /** * @see Socket#getOOBInline() */ boolean isOobInline(); /** * @see Socket#setOOBInline(boolean) */ void setOobInline(boolean oobInline); /** * Please note that enabling SO_LINGER in Java NIO can result * in platform-dependent behavior and unexpected blocking of I/O thread. * * @see Socket#getSoLinger() * @see Sun Bug Database */ int getSoLinger(); /** * Please note that enabling SO_LINGER in Java NIO can result * in platform-dependent behavior and unexpected blocking of I/O thread. * * @param soLinger Please specify a negative value to disable SO_LINGER. * * @see Socket#setSoLinger(boolean, int) * @see Sun Bug Database */ void setSoLinger(int soLinger); /** * @see Socket#getTcpNoDelay() */ boolean isTcpNoDelay(); /** * @see Socket#setTcpNoDelay(boolean) */ void setTcpNoDelay(boolean tcpNoDelay); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/0000755000175000017500000000000012162575507027171 5ustar ebourgebourg././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioSocketConnector.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioSocketConnector0000644000175000017500000002363112032276033032656 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.util.Collection; import java.util.Iterator; import java.util.concurrent.Executor; import org.apache.mina.core.polling.AbstractPollingIoConnector; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.IoService; import org.apache.mina.core.service.SimpleIoProcessorPool; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.transport.socket.DefaultSocketSessionConfig; import org.apache.mina.transport.socket.SocketConnector; import org.apache.mina.transport.socket.SocketSessionConfig; /** * {@link IoConnector} for socket transport (TCP/IP). * * @author Apache MINA Project */ public final class NioSocketConnector extends AbstractPollingIoConnector implements SocketConnector { private volatile Selector selector; /** * Constructor for {@link NioSocketConnector} with default configuration (multiple thread model). */ public NioSocketConnector() { super(new DefaultSocketSessionConfig(), NioProcessor.class); ((DefaultSocketSessionConfig) getSessionConfig()).init(this); } /** * Constructor for {@link NioSocketConnector} with default configuration, and * given number of {@link NioProcessor} for multithreading I/O operations * @param processorCount the number of processor to create and place in a * {@link SimpleIoProcessorPool} */ public NioSocketConnector(int processorCount) { super(new DefaultSocketSessionConfig(), NioProcessor.class, processorCount); ((DefaultSocketSessionConfig) getSessionConfig()).init(this); } /** * Constructor for {@link NioSocketConnector} with default configuration but a * specific {@link IoProcessor}, useful for sharing the same processor over multiple * {@link IoService} of the same type. * @param processor the processor to use for managing I/O events */ public NioSocketConnector(IoProcessor processor) { super(new DefaultSocketSessionConfig(), processor); ((DefaultSocketSessionConfig) getSessionConfig()).init(this); } /** * Constructor for {@link NioSocketConnector} with a given {@link Executor} for handling * connection events and a given {@link IoProcessor} for handling I/O events, useful for sharing * the same processor and executor over multiple {@link IoService} of the same type. * @param executor the executor for connection * @param processor the processor for I/O operations */ public NioSocketConnector(Executor executor, IoProcessor processor) { super(new DefaultSocketSessionConfig(), executor, processor); ((DefaultSocketSessionConfig) getSessionConfig()).init(this); } /** * Constructor for {@link NioSocketConnector} with default configuration which will use a built-in * thread pool executor to manage the given number of processor instances. The processor class must have * a constructor that accepts ExecutorService or Executor as its single argument, or, failing that, a * no-arg constructor. * * @param processorClass the processor class. * @param processorCount the number of processors to instantiate. * @see org.apache.mina.core.service.SimpleIoProcessorPool#SimpleIoProcessorPool(Class, Executor, int) * @since 2.0.0-M4 */ public NioSocketConnector(Class> processorClass, int processorCount) { super(new DefaultSocketSessionConfig(), processorClass, processorCount); } /** * Constructor for {@link NioSocketConnector} with default configuration with default configuration which will use a built-in * thread pool executor to manage the default number of processor instances. The processor class must have * a constructor that accepts ExecutorService or Executor as its single argument, or, failing that, a * no-arg constructor. The default number of instances is equal to the number of processor cores * in the system, plus one. * * @param processorClass the processor class. * @see org.apache.mina.core.service.SimpleIoProcessorPool#SimpleIoProcessorPool(Class, Executor, int) * @see org.apache.mina.core.service.SimpleIoProcessorPool#DEFAULT_SIZE * @since 2.0.0-M4 */ public NioSocketConnector(Class> processorClass) { super(new DefaultSocketSessionConfig(), processorClass); } /** * {@inheritDoc} */ @Override protected void init() throws Exception { this.selector = Selector.open(); } /** * {@inheritDoc} */ @Override protected void destroy() throws Exception { if (selector != null) { selector.close(); } } /** * {@inheritDoc} */ public TransportMetadata getTransportMetadata() { return NioSocketSession.METADATA; } /** * {@inheritDoc} */ @Override public SocketSessionConfig getSessionConfig() { return (SocketSessionConfig) super.getSessionConfig(); } /** * {@inheritDoc} */ @Override public InetSocketAddress getDefaultRemoteAddress() { return (InetSocketAddress) super.getDefaultRemoteAddress(); } /** * {@inheritDoc} */ public void setDefaultRemoteAddress(InetSocketAddress defaultRemoteAddress) { super.setDefaultRemoteAddress(defaultRemoteAddress); } /** * {@inheritDoc} */ @Override protected Iterator allHandles() { return new SocketChannelIterator(selector.keys()); } /** * {@inheritDoc} */ @Override protected boolean connect(SocketChannel handle, SocketAddress remoteAddress) throws Exception { return handle.connect(remoteAddress); } /** * {@inheritDoc} */ @Override protected ConnectionRequest getConnectionRequest(SocketChannel handle) { SelectionKey key = handle.keyFor(selector); if ((key == null) || (!key.isValid())) { return null; } return (ConnectionRequest) key.attachment(); } /** * {@inheritDoc} */ @Override protected void close(SocketChannel handle) throws Exception { SelectionKey key = handle.keyFor(selector); if (key != null) { key.cancel(); } handle.close(); } /** * {@inheritDoc} */ @Override protected boolean finishConnect(SocketChannel handle) throws Exception { if (handle.finishConnect()) { SelectionKey key = handle.keyFor(selector); if (key != null) { key.cancel(); } return true; } return false; } /** * {@inheritDoc} */ @Override protected SocketChannel newHandle(SocketAddress localAddress) throws Exception { SocketChannel ch = SocketChannel.open(); int receiveBufferSize = (getSessionConfig()).getReceiveBufferSize(); if (receiveBufferSize > 65535) { ch.socket().setReceiveBufferSize(receiveBufferSize); } if (localAddress != null) { ch.socket().bind(localAddress); } ch.configureBlocking(false); return ch; } /** * {@inheritDoc} */ @Override protected NioSession newSession(IoProcessor processor, SocketChannel handle) { return new NioSocketSession(this, processor, handle); } /** * {@inheritDoc} */ @Override protected void register(SocketChannel handle, ConnectionRequest request) throws Exception { handle.register(selector, SelectionKey.OP_CONNECT, request); } /** * {@inheritDoc} */ @Override protected int select(int timeout) throws Exception { return selector.select(timeout); } /** * {@inheritDoc} */ @Override protected Iterator selectedHandles() { return new SocketChannelIterator(selector.selectedKeys()); } /** * {@inheritDoc} */ @Override protected void wakeup() { selector.wakeup(); } private static class SocketChannelIterator implements Iterator { private final Iterator i; private SocketChannelIterator(Collection selectedKeys) { this.i = selectedKeys.iterator(); } /** * {@inheritDoc} */ public boolean hasNext() { return i.hasNext(); } /** * {@inheritDoc} */ public SocketChannel next() { SelectionKey key = i.next(); return (SocketChannel) key.channel(); } /** * {@inheritDoc} */ public void remove() { i.remove(); } } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioSocketAcceptor.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioSocketAcceptor.0000644000175000017500000002334012032276033032537 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.SocketAddress; import java.nio.channels.ClosedSelectorException; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Collection; import java.util.Iterator; import java.util.concurrent.Executor; import org.apache.mina.core.polling.AbstractPollingIoAcceptor; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.IoService; import org.apache.mina.core.service.SimpleIoProcessorPool; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.transport.socket.DefaultSocketSessionConfig; import org.apache.mina.transport.socket.SocketAcceptor; import org.apache.mina.transport.socket.SocketSessionConfig; /** * {@link IoAcceptor} for socket transport (TCP/IP). This class * handles incoming TCP/IP based socket connections. * * @author Apache MINA Project */ public final class NioSocketAcceptor extends AbstractPollingIoAcceptor implements SocketAcceptor { private volatile Selector selector; /** * Constructor for {@link NioSocketAcceptor} using default parameters (multiple thread model). */ public NioSocketAcceptor() { super(new DefaultSocketSessionConfig(), NioProcessor.class); ((DefaultSocketSessionConfig) getSessionConfig()).init(this); } /** * Constructor for {@link NioSocketAcceptor} using default parameters, and * given number of {@link NioProcessor} for multithreading I/O operations. * * @param processorCount the number of processor to create and place in a * {@link SimpleIoProcessorPool} */ public NioSocketAcceptor(int processorCount) { super(new DefaultSocketSessionConfig(), NioProcessor.class, processorCount); ((DefaultSocketSessionConfig) getSessionConfig()).init(this); } /** * Constructor for {@link NioSocketAcceptor} with default configuration but a * specific {@link IoProcessor}, useful for sharing the same processor over multiple * {@link IoService} of the same type. * @param processor the processor to use for managing I/O events */ public NioSocketAcceptor(IoProcessor processor) { super(new DefaultSocketSessionConfig(), processor); ((DefaultSocketSessionConfig) getSessionConfig()).init(this); } /** * Constructor for {@link NioSocketAcceptor} with a given {@link Executor} for handling * connection events and a given {@link IoProcessor} for handling I/O events, useful for * sharing the same processor and executor over multiple {@link IoService} of the same type. * @param executor the executor for connection * @param processor the processor for I/O operations */ public NioSocketAcceptor(Executor executor, IoProcessor processor) { super(new DefaultSocketSessionConfig(), executor, processor); ((DefaultSocketSessionConfig) getSessionConfig()).init(this); } /** * {@inheritDoc} */ @Override protected void init() throws Exception { selector = Selector.open(); } /** * {@inheritDoc} */ @Override protected void destroy() throws Exception { if (selector != null) { selector.close(); } } /** * {@inheritDoc} */ public TransportMetadata getTransportMetadata() { return NioSocketSession.METADATA; } /** * {@inheritDoc} */ @Override public SocketSessionConfig getSessionConfig() { return (SocketSessionConfig) super.getSessionConfig(); } /** * {@inheritDoc} */ @Override public InetSocketAddress getLocalAddress() { return (InetSocketAddress) super.getLocalAddress(); } /** * {@inheritDoc} */ @Override public InetSocketAddress getDefaultLocalAddress() { return (InetSocketAddress) super.getDefaultLocalAddress(); } /** * {@inheritDoc} */ public void setDefaultLocalAddress(InetSocketAddress localAddress) { setDefaultLocalAddress((SocketAddress) localAddress); } /** * {@inheritDoc} */ @Override protected NioSession accept(IoProcessor processor, ServerSocketChannel handle) throws Exception { SelectionKey key = handle.keyFor(selector); if ((key == null) || (!key.isValid()) || (!key.isAcceptable())) { return null; } // accept the connection from the client SocketChannel ch = handle.accept(); if (ch == null) { return null; } return new NioSocketSession(this, processor, ch); } /** * {@inheritDoc} */ @Override protected ServerSocketChannel open(SocketAddress localAddress) throws Exception { // Creates the listening ServerSocket ServerSocketChannel channel = ServerSocketChannel.open(); boolean success = false; try { // This is a non blocking socket channel channel.configureBlocking(false); // Configure the server socket, ServerSocket socket = channel.socket(); // Set the reuseAddress flag accordingly with the setting socket.setReuseAddress(isReuseAddress()); // and bind. socket.bind(localAddress, getBacklog()); // Register the channel within the selector for ACCEPT event channel.register(selector, SelectionKey.OP_ACCEPT); success = true; } finally { if (!success) { close(channel); } } return channel; } /** * {@inheritDoc} */ @Override protected SocketAddress localAddress(ServerSocketChannel handle) throws Exception { return handle.socket().getLocalSocketAddress(); } /** * Check if we have at least one key whose corresponding channels is * ready for I/O operations. * * This method performs a blocking selection operation. * It returns only after at least one channel is selected, * this selector's wakeup method is invoked, or the current thread * is interrupted, whichever comes first. * * @return The number of keys having their ready-operation set updated * @throws IOException If an I/O error occurs * @throws ClosedSelectorException If this selector is closed */ @Override protected int select() throws Exception { return selector.select(); } /** * {@inheritDoc} */ @Override protected Iterator selectedHandles() { return new ServerSocketChannelIterator(selector.selectedKeys()); } /** * {@inheritDoc} */ @Override protected void close(ServerSocketChannel handle) throws Exception { SelectionKey key = handle.keyFor(selector); if (key != null) { key.cancel(); } handle.close(); } /** * {@inheritDoc} */ @Override protected void wakeup() { selector.wakeup(); } /** * Defines an iterator for the selected-key Set returned by the * selector.selectedKeys(). It replaces the SelectionKey operator. */ private static class ServerSocketChannelIterator implements Iterator { /** The selected-key iterator */ private final Iterator iterator; /** * Build a SocketChannel iterator which will return a SocketChannel instead of * a SelectionKey. * * @param selectedKeys The selector selected-key set */ private ServerSocketChannelIterator(Collection selectedKeys) { iterator = selectedKeys.iterator(); } /** * Tells if there are more SockectChannel left in the iterator * @return true if there is at least one more * SockectChannel object to read */ public boolean hasNext() { return iterator.hasNext(); } /** * Get the next SocketChannel in the operator we have built from * the selected-key et for this selector. * * @return The next SocketChannel in the iterator */ public ServerSocketChannel next() { SelectionKey key = iterator.next(); if (key.isValid() && key.isAcceptable()) { return (ServerSocketChannel) key.channel(); } return null; } /** * Remove the current SocketChannel from the iterator */ public void remove() { iterator.remove(); } } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioSocketSession.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioSocketSession.j0000644000175000017500000001675712032276033032612 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketException; import java.nio.channels.SocketChannel; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.file.FileRegion; import org.apache.mina.core.service.DefaultTransportMetadata; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.IoService; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.core.session.IoSession; import org.apache.mina.transport.socket.AbstractSocketSessionConfig; import org.apache.mina.transport.socket.SocketSessionConfig; /** * An {@link IoSession} for socket transport (TCP/IP). * * @author Apache MINA Project */ class NioSocketSession extends NioSession { static final TransportMetadata METADATA = new DefaultTransportMetadata("nio", "socket", false, true, InetSocketAddress.class, SocketSessionConfig.class, IoBuffer.class, FileRegion.class); private Socket getSocket() { return ((SocketChannel) channel).socket(); } /** * * Creates a new instance of NioSocketSession. * * @param service the associated IoService * @param processor the associated IoProcessor * @param ch the used channel */ public NioSocketSession(IoService service, IoProcessor processor, SocketChannel channel) { super(processor, service, channel); config = new SessionConfigImpl(); this.config.setAll(service.getSessionConfig()); } public TransportMetadata getTransportMetadata() { return METADATA; } /** * {@inheritDoc} */ public SocketSessionConfig getConfig() { return (SocketSessionConfig) config; } @Override SocketChannel getChannel() { return (SocketChannel) channel; } /** * {@inheritDoc} */ public InetSocketAddress getRemoteAddress() { if (channel == null) { return null; } Socket socket = getSocket(); if (socket == null) { return null; } return (InetSocketAddress) socket.getRemoteSocketAddress(); } /** * {@inheritDoc} */ public InetSocketAddress getLocalAddress() { if (channel == null) { return null; } Socket socket = getSocket(); if (socket == null) { return null; } return (InetSocketAddress) socket.getLocalSocketAddress(); } @Override public InetSocketAddress getServiceAddress() { return (InetSocketAddress) super.getServiceAddress(); } private class SessionConfigImpl extends AbstractSocketSessionConfig { public boolean isKeepAlive() { try { return getSocket().getKeepAlive(); } catch (SocketException e) { throw new RuntimeIoException(e); } } public void setKeepAlive(boolean on) { try { getSocket().setKeepAlive(on); } catch (SocketException e) { throw new RuntimeIoException(e); } } public boolean isOobInline() { try { return getSocket().getOOBInline(); } catch (SocketException e) { throw new RuntimeIoException(e); } } public void setOobInline(boolean on) { try { getSocket().setOOBInline(on); } catch (SocketException e) { throw new RuntimeIoException(e); } } public boolean isReuseAddress() { try { return getSocket().getReuseAddress(); } catch (SocketException e) { throw new RuntimeIoException(e); } } public void setReuseAddress(boolean on) { try { getSocket().setReuseAddress(on); } catch (SocketException e) { throw new RuntimeIoException(e); } } public int getSoLinger() { try { return getSocket().getSoLinger(); } catch (SocketException e) { throw new RuntimeIoException(e); } } public void setSoLinger(int linger) { try { if (linger < 0) { getSocket().setSoLinger(false, 0); } else { getSocket().setSoLinger(true, linger); } } catch (SocketException e) { throw new RuntimeIoException(e); } } public boolean isTcpNoDelay() { if (!isConnected()) { return false; } try { return getSocket().getTcpNoDelay(); } catch (SocketException e) { throw new RuntimeIoException(e); } } public void setTcpNoDelay(boolean on) { try { getSocket().setTcpNoDelay(on); } catch (SocketException e) { throw new RuntimeIoException(e); } } /** * {@inheritDoc} */ public int getTrafficClass() { try { return getSocket().getTrafficClass(); } catch (SocketException e) { throw new RuntimeIoException(e); } } /** * {@inheritDoc} */ public void setTrafficClass(int tc) { try { getSocket().setTrafficClass(tc); } catch (SocketException e) { throw new RuntimeIoException(e); } } public int getSendBufferSize() { try { return getSocket().getSendBufferSize(); } catch (SocketException e) { throw new RuntimeIoException(e); } } public void setSendBufferSize(int size) { try { getSocket().setSendBufferSize(size); } catch (SocketException e) { throw new RuntimeIoException(e); } } public int getReceiveBufferSize() { try { return getSocket().getReceiveBufferSize(); } catch (SocketException e) { throw new RuntimeIoException(e); } } public void setReceiveBufferSize(int size) { try { getSocket().setReceiveBufferSize(size); } catch (SocketException e) { throw new RuntimeIoException(e); } } } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioDatagramSession.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioDatagramSession0000644000175000017500000000625712032276033032644 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.channels.DatagramChannel; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.service.DefaultTransportMetadata; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.IoService; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.core.session.IoSession; import org.apache.mina.transport.socket.DatagramSessionConfig; /** * An {@link IoSession} for datagram transport (UDP/IP). * * @author Apache MINA Project */ class NioDatagramSession extends NioSession { static final TransportMetadata METADATA = new DefaultTransportMetadata("nio", "datagram", true, false, InetSocketAddress.class, DatagramSessionConfig.class, IoBuffer.class); private final InetSocketAddress localAddress; private final InetSocketAddress remoteAddress; /** * Creates a new acceptor-side session instance. */ NioDatagramSession(IoService service, DatagramChannel channel, IoProcessor processor, SocketAddress remoteAddress) { super(processor, service, channel); config = new NioDatagramSessionConfig(channel); config.setAll(service.getSessionConfig()); this.remoteAddress = (InetSocketAddress) remoteAddress; this.localAddress = (InetSocketAddress) channel.socket().getLocalSocketAddress(); } /** * Creates a new connector-side session instance. */ NioDatagramSession(IoService service, DatagramChannel channel, IoProcessor processor) { this(service, channel, processor, channel.socket().getRemoteSocketAddress()); } /** * {@inheritDoc} */ public DatagramSessionConfig getConfig() { return (DatagramSessionConfig) config; } @Override DatagramChannel getChannel() { return (DatagramChannel) channel; } public TransportMetadata getTransportMetadata() { return METADATA; } public InetSocketAddress getRemoteAddress() { return remoteAddress; } public InetSocketAddress getLocalAddress() { return localAddress; } @Override public InetSocketAddress getServiceAddress() { return (InetSocketAddress) super.getServiceAddress(); } }././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioDatagramConnector.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioDatagramConnect0000644000175000017500000001532612032276033032607 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.channels.DatagramChannel; import java.util.Collections; import java.util.Iterator; import org.apache.mina.core.polling.AbstractPollingIoConnector; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.transport.socket.DatagramConnector; import org.apache.mina.transport.socket.DatagramSessionConfig; import org.apache.mina.transport.socket.DefaultDatagramSessionConfig; /** * {@link IoConnector} for datagram transport (UDP/IP). * * @author Apache MINA Project */ public final class NioDatagramConnector extends AbstractPollingIoConnector implements DatagramConnector { /** * Creates a new instance. */ public NioDatagramConnector() { super(new DefaultDatagramSessionConfig(), NioProcessor.class); } /** * Creates a new instance. */ public NioDatagramConnector(int processorCount) { super(new DefaultDatagramSessionConfig(), NioProcessor.class, processorCount); } /** * Creates a new instance. */ public NioDatagramConnector(IoProcessor processor) { super(new DefaultDatagramSessionConfig(), processor); } /** * Constructor for {@link NioDatagramConnector} with default configuration which will use a built-in * thread pool executor to manage the given number of processor instances. The processor class must have * a constructor that accepts ExecutorService or Executor as its single argument, or, failing that, a * no-arg constructor. * * @param processorClass the processor class. * @param processorCount the number of processors to instantiate. * @see org.apache.mina.core.service.SimpleIoProcessorPool#SimpleIoProcessorPool(Class, Executor, int) * @since 2.0.0-M4 */ public NioDatagramConnector(Class> processorClass, int processorCount) { super(new DefaultDatagramSessionConfig(), processorClass, processorCount); } /** * Constructor for {@link NioDatagramConnector} with default configuration with default configuration which will use a built-in * thread pool executor to manage the default number of processor instances. The processor class must have * a constructor that accepts ExecutorService or Executor as its single argument, or, failing that, a * no-arg constructor. The default number of instances is equal to the number of processor cores * in the system, plus one. * * @param processorClass the processor class. * @see org.apache.mina.core.service.SimpleIoProcessorPool#SimpleIoProcessorPool(Class, Executor, int) * @see org.apache.mina.core.service.SimpleIoProcessorPool#DEFAULT_SIZE * @since 2.0.0-M4 */ public NioDatagramConnector(Class> processorClass) { super(new DefaultDatagramSessionConfig(), processorClass); } public TransportMetadata getTransportMetadata() { return NioDatagramSession.METADATA; } @Override public DatagramSessionConfig getSessionConfig() { return (DatagramSessionConfig) super.getSessionConfig(); } @Override public InetSocketAddress getDefaultRemoteAddress() { return (InetSocketAddress) super.getDefaultRemoteAddress(); } public void setDefaultRemoteAddress(InetSocketAddress defaultRemoteAddress) { super.setDefaultRemoteAddress(defaultRemoteAddress); } @Override protected void init() throws Exception { // Do nothing } @Override protected DatagramChannel newHandle(SocketAddress localAddress) throws Exception { DatagramChannel ch = DatagramChannel.open(); try { if (localAddress != null) { ch.socket().bind(localAddress); } return ch; } catch (Exception e) { // If we got an exception while binding the datagram, // we have to close it otherwise we will loose an handle ch.close(); throw e; } } @Override protected boolean connect(DatagramChannel handle, SocketAddress remoteAddress) throws Exception { handle.connect(remoteAddress); return true; } @Override protected NioSession newSession(IoProcessor processor, DatagramChannel handle) { NioSession session = new NioDatagramSession(this, handle, processor); session.getConfig().setAll(getSessionConfig()); return session; } @Override protected void close(DatagramChannel handle) throws Exception { handle.disconnect(); handle.close(); } // Unused extension points. @Override @SuppressWarnings("unchecked") protected Iterator allHandles() { return Collections.EMPTY_LIST.iterator(); } @Override protected ConnectionRequest getConnectionRequest(DatagramChannel handle) { throw new UnsupportedOperationException(); } @Override protected void destroy() throws Exception { // Do nothing } @Override protected boolean finishConnect(DatagramChannel handle) throws Exception { throw new UnsupportedOperationException(); } @Override protected void register(DatagramChannel handle, ConnectionRequest request) throws Exception { throw new UnsupportedOperationException(); } @Override protected int select(int timeout) throws Exception { return 0; } @Override @SuppressWarnings("unchecked") protected Iterator selectedHandles() { return Collections.EMPTY_LIST.iterator(); } @Override protected void wakeup() { // Do nothing } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioDatagramAcceptor.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioDatagramAccepto0000644000175000017500000001654612032515552032603 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.channels.DatagramChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.util.Set; import java.util.concurrent.Executor; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.polling.AbstractPollingConnectionlessIoAcceptor; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.transport.socket.DatagramAcceptor; import org.apache.mina.transport.socket.DatagramSessionConfig; import org.apache.mina.transport.socket.DefaultDatagramSessionConfig; /** * {@link IoAcceptor} for datagram transport (UDP/IP). * * @author Apache MINA Project * @org.apache.xbean.XBean */ public final class NioDatagramAcceptor extends AbstractPollingConnectionlessIoAcceptor implements DatagramAcceptor { private volatile Selector selector; /** * Creates a new instance. */ public NioDatagramAcceptor() { super(new DefaultDatagramSessionConfig()); } /** * Creates a new instance. */ public NioDatagramAcceptor(Executor executor) { super(new DefaultDatagramSessionConfig(), executor); } @Override protected void init() throws Exception { this.selector = Selector.open(); } @Override protected void destroy() throws Exception { if (selector != null) { selector.close(); } } public TransportMetadata getTransportMetadata() { return NioDatagramSession.METADATA; } @Override public DatagramSessionConfig getSessionConfig() { return (DatagramSessionConfig) super.getSessionConfig(); } @Override public InetSocketAddress getLocalAddress() { return (InetSocketAddress) super.getLocalAddress(); } @Override public InetSocketAddress getDefaultLocalAddress() { return (InetSocketAddress) super.getDefaultLocalAddress(); } public void setDefaultLocalAddress(InetSocketAddress localAddress) { setDefaultLocalAddress((SocketAddress) localAddress); } @Override protected DatagramChannel open(SocketAddress localAddress) throws Exception { final DatagramChannel c = DatagramChannel.open(); boolean success = false; try { new NioDatagramSessionConfig(c).setAll(getSessionConfig()); c.configureBlocking(false); c.socket().bind(localAddress); c.register(selector, SelectionKey.OP_READ); success = true; } finally { if (!success) { close(c); } } return c; } @Override protected boolean isReadable(DatagramChannel handle) { SelectionKey key = handle.keyFor(selector); if ((key == null) || (!key.isValid())) { return false; } return key.isReadable(); } @Override protected boolean isWritable(DatagramChannel handle) { SelectionKey key = handle.keyFor(selector); if ((key == null) || (!key.isValid())) { return false; } return key.isWritable(); } @Override protected SocketAddress localAddress(DatagramChannel handle) throws Exception { InetSocketAddress inetSocketAddress = (InetSocketAddress) handle.socket().getLocalSocketAddress(); InetAddress inetAddress = inetSocketAddress.getAddress(); if ((inetAddress instanceof Inet6Address) && (((Inet6Address) inetAddress).isIPv4CompatibleAddress())) { // Ugly hack to workaround a problem on linux : the ANY address is always converted to IPV6 // even if the original address was an IPV4 address. We do store the two IPV4 and IPV6 // ANY address in the map. byte[] ipV6Address = ((Inet6Address) inetAddress).getAddress(); byte[] ipV4Address = new byte[4]; for (int i = 0; i < 4; i++) { ipV4Address[i] = ipV6Address[12 + i]; } InetAddress inet4Adress = Inet4Address.getByAddress(ipV4Address); return new InetSocketAddress(inet4Adress, inetSocketAddress.getPort()); } else { return inetSocketAddress; } } @Override protected NioSession newSession(IoProcessor processor, DatagramChannel handle, SocketAddress remoteAddress) { SelectionKey key = handle.keyFor(selector); if ((key == null) || (!key.isValid())) { return null; } NioDatagramSession newSession = new NioDatagramSession(this, handle, processor, remoteAddress); newSession.setSelectionKey(key); return newSession; } @Override protected SocketAddress receive(DatagramChannel handle, IoBuffer buffer) throws Exception { return handle.receive(buffer.buf()); } @Override protected int select() throws Exception { return selector.select(); } @Override protected int select(long timeout) throws Exception { return selector.select(timeout); } @Override protected Set selectedHandles() { return selector.selectedKeys(); } @Override protected int send(NioSession session, IoBuffer buffer, SocketAddress remoteAddress) throws Exception { return ((DatagramChannel) session.getChannel()).send(buffer.buf(), remoteAddress); } @Override protected void setInterestedInWrite(NioSession session, boolean isInterested) throws Exception { SelectionKey key = session.getSelectionKey(); if (key == null) { return; } int newInterestOps = key.interestOps(); if (isInterested) { newInterestOps |= SelectionKey.OP_WRITE; //newInterestOps &= ~SelectionKey.OP_READ; } else { newInterestOps &= ~SelectionKey.OP_WRITE; //newInterestOps |= SelectionKey.OP_READ; } key.interestOps(newInterestOps); } @Override protected void close(DatagramChannel handle) throws Exception { SelectionKey key = handle.keyFor(selector); if (key != null) { key.cancel(); } handle.disconnect(); handle.close(); } @Override protected void wakeup() { selector.wakeup(); } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioProcessor.java0000644000175000017500000002453412032276033032455 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import java.io.IOException; import java.nio.channels.ByteChannel; import java.nio.channels.DatagramChannel; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.Set; import java.util.concurrent.Executor; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.file.FileRegion; import org.apache.mina.core.polling.AbstractPollingIoProcessor; import org.apache.mina.core.session.SessionState; /** * TODO Add documentation * * @author Apache MINA Project */ public final class NioProcessor extends AbstractPollingIoProcessor { /** The selector associated with this processor */ private Selector selector; /** * * Creates a new instance of NioProcessor. * * @param executor */ public NioProcessor(Executor executor) { super(executor); try { // Open a new selector selector = Selector.open(); } catch (IOException e) { throw new RuntimeIoException("Failed to open a selector.", e); } } @Override protected void doDispose() throws Exception { selector.close(); } @Override protected int select(long timeout) throws Exception { return selector.select(timeout); } @Override protected int select() throws Exception { return selector.select(); } @Override protected boolean isSelectorEmpty() { return selector.keys().isEmpty(); } @Override protected void wakeup() { wakeupCalled.getAndSet(true); selector.wakeup(); } @Override protected Iterator allSessions() { return new IoSessionIterator(selector.keys()); } @SuppressWarnings("synthetic-access") @Override protected Iterator selectedSessions() { return new IoSessionIterator(selector.selectedKeys()); } @Override protected void init(NioSession session) throws Exception { SelectableChannel ch = (SelectableChannel) session.getChannel(); ch.configureBlocking(false); session.setSelectionKey(ch.register(selector, SelectionKey.OP_READ, session)); } @Override protected void destroy(NioSession session) throws Exception { ByteChannel ch = session.getChannel(); SelectionKey key = session.getSelectionKey(); if (key != null) { key.cancel(); } ch.close(); } /** * In the case we are using the java select() method, this method is used to * trash the buggy selector and create a new one, registering all the * sockets on it. */ @Override protected void registerNewSelector() throws IOException { synchronized (selector) { Set keys = selector.keys(); // Open a new selector Selector newSelector = Selector.open(); // Loop on all the registered keys, and register them on the new selector for (SelectionKey key : keys) { SelectableChannel ch = key.channel(); // Don't forget to attache the session, and back ! NioSession session = (NioSession) key.attachment(); SelectionKey newKey = ch.register(newSelector, key.interestOps(), session); session.setSelectionKey(newKey); } // Now we can close the old selector and switch it selector.close(); selector = newSelector; } } /** * {@inheritDoc} */ @Override protected boolean isBrokenConnection() throws IOException { // A flag set to true if we find a broken session boolean brokenSession = false; synchronized (selector) { // Get the selector keys Set keys = selector.keys(); // Loop on all the keys to see if one of them // has a closed channel for (SelectionKey key : keys) { SelectableChannel channel = key.channel(); if ((((channel instanceof DatagramChannel) && !((DatagramChannel) channel).isConnected())) || ((channel instanceof SocketChannel) && !((SocketChannel) channel).isConnected())) { // The channel is not connected anymore. Cancel // the associated key then. key.cancel(); // Set the flag to true to avoid a selector switch brokenSession = true; } } } return brokenSession; } /** * {@inheritDoc} */ @Override protected SessionState getState(NioSession session) { SelectionKey key = session.getSelectionKey(); if (key == null) { // The channel is not yet registred to a selector return SessionState.OPENING; } if (key.isValid()) { // The session is opened return SessionState.OPENED; } else { // The session still as to be closed return SessionState.CLOSING; } } @Override protected boolean isReadable(NioSession session) { SelectionKey key = session.getSelectionKey(); return key.isValid() && key.isReadable(); } @Override protected boolean isWritable(NioSession session) { SelectionKey key = session.getSelectionKey(); return key.isValid() && key.isWritable(); } @Override protected boolean isInterestedInRead(NioSession session) { SelectionKey key = session.getSelectionKey(); return key.isValid() && ((key.interestOps() & SelectionKey.OP_READ) != 0); } @Override protected boolean isInterestedInWrite(NioSession session) { SelectionKey key = session.getSelectionKey(); return key.isValid() && ((key.interestOps() & SelectionKey.OP_WRITE) != 0); } /** * {@inheritDoc} */ @Override protected void setInterestedInRead(NioSession session, boolean isInterested) throws Exception { SelectionKey key = session.getSelectionKey(); int oldInterestOps = key.interestOps(); int newInterestOps = oldInterestOps; if (isInterested) { newInterestOps |= SelectionKey.OP_READ; } else { newInterestOps &= ~SelectionKey.OP_READ; } if (oldInterestOps != newInterestOps) { key.interestOps(newInterestOps); } } /** * {@inheritDoc} */ @Override protected void setInterestedInWrite(NioSession session, boolean isInterested) throws Exception { SelectionKey key = session.getSelectionKey(); if (key == null) { return; } int newInterestOps = key.interestOps(); if (isInterested) { newInterestOps |= SelectionKey.OP_WRITE; //newInterestOps &= ~SelectionKey.OP_READ; } else { newInterestOps &= ~SelectionKey.OP_WRITE; //newInterestOps |= SelectionKey.OP_READ; } key.interestOps(newInterestOps); } @Override protected int read(NioSession session, IoBuffer buf) throws Exception { ByteChannel channel = session.getChannel(); return channel.read(buf.buf()); } @Override protected int write(NioSession session, IoBuffer buf, int length) throws Exception { if (buf.remaining() <= length) { return session.getChannel().write(buf.buf()); } int oldLimit = buf.limit(); buf.limit(buf.position() + length); try { return session.getChannel().write(buf.buf()); } finally { buf.limit(oldLimit); } } @Override protected int transferFile(NioSession session, FileRegion region, int length) throws Exception { try { return (int) region.getFileChannel().transferTo(region.getPosition(), length, session.getChannel()); } catch (IOException e) { // Check to see if the IOException is being thrown due to // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5103988 String message = e.getMessage(); if ((message != null) && message.contains("temporarily unavailable")) { return 0; } throw e; } } /** * An encapsulating iterator around the {@link Selector#selectedKeys()} or * the {@link Selector#keys()} iterator; */ protected static class IoSessionIterator implements Iterator { private final Iterator iterator; /** * Create this iterator as a wrapper on top of the selectionKey Set. * * @param keys * The set of selected sessions */ private IoSessionIterator(Set keys) { iterator = keys.iterator(); } /** * {@inheritDoc} */ public boolean hasNext() { return iterator.hasNext(); } /** * {@inheritDoc} */ public NioSession next() { SelectionKey key = iterator.next(); NioSession nioSession = (NioSession) key.attachment(); return nioSession; } /** * {@inheritDoc} */ public void remove() { iterator.remove(); } } }././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioDatagramSessionConfig.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioDatagramSession0000644000175000017500000001353512032276033032641 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import java.net.DatagramSocket; import java.net.SocketException; import java.nio.channels.DatagramChannel; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.transport.socket.AbstractDatagramSessionConfig; /** * Define the configuration for a Datagram based session. * * @author Apache MINA Project */ class NioDatagramSessionConfig extends AbstractDatagramSessionConfig { /** The associated channel */ private final DatagramChannel channel; /** * Creates a new instance of NioDatagramSessionConfig, associated * with the given DatagramChannel. * * @param channel The associated DatagramChannel */ NioDatagramSessionConfig(DatagramChannel channel) { this.channel = channel; } /** * Get the Socket receive buffer size for this DatagramChannel. * * @return the DatagramChannel receive buffer size. * @throws RuntimeIoException if the socket is closed or if we * had a SocketException * * @see DatagramSocket#getReceiveBufferSize() */ public int getReceiveBufferSize() { try { return channel.socket().getReceiveBufferSize(); } catch (SocketException e) { throw new RuntimeIoException(e); } } /** * Set the Socket receive buffer size for this DatagramChannel.
*
* Note : The underlying Socket may not accept the new buffer's size. * The user has to check that the new value has been set. * * @param receiveBufferSize the DatagramChannel receive buffer size. * @throws RuntimeIoException if the socket is closed or if we * had a SocketException * * @see DatagramSocket#setReceiveBufferSize() */ public void setReceiveBufferSize(int receiveBufferSize) { try { channel.socket().setReceiveBufferSize(receiveBufferSize); } catch (SocketException e) { throw new RuntimeIoException(e); } } /** * Tells if SO_BROADCAST is enabled. * * @return true if SO_BROADCAST is enabled * @throws RuntimeIoException If the socket is closed or if we get an * {@link SocketException} */ public boolean isBroadcast() { try { return channel.socket().getBroadcast(); } catch (SocketException e) { throw new RuntimeIoException(e); } } public void setBroadcast(boolean broadcast) { try { channel.socket().setBroadcast(broadcast); } catch (SocketException e) { throw new RuntimeIoException(e); } } /** * * @throws RuntimeIoException If the socket is closed or if we get an * {@link SocketException} */ public int getSendBufferSize() { try { return channel.socket().getSendBufferSize(); } catch (SocketException e) { throw new RuntimeIoException(e); } } /** * * @throws RuntimeIoException If the socket is closed or if we get an * {@link SocketException} */ public void setSendBufferSize(int sendBufferSize) { try { channel.socket().setSendBufferSize(sendBufferSize); } catch (SocketException e) { throw new RuntimeIoException(e); } } /** * Tells if SO_REUSEADDR is enabled. * * @return true if SO_REUSEADDR is enabled * @throws RuntimeIoException If the socket is closed or if we get an * {@link SocketException} */ public boolean isReuseAddress() { try { return channel.socket().getReuseAddress(); } catch (SocketException e) { throw new RuntimeIoException(e); } } /** * * @throws RuntimeIoException If the socket is closed or if we get an * {@link SocketException} */ public void setReuseAddress(boolean reuseAddress) { try { channel.socket().setReuseAddress(reuseAddress); } catch (SocketException e) { throw new RuntimeIoException(e); } } /** * Get the current Traffic Class for this Socket, if any. As this is * not a mandatory feature, the returned value should be considered as * a hint. * * @return The Traffic Class supported by this Socket * @throws RuntimeIoException If the socket is closed or if we get an * {@link SocketException} */ public int getTrafficClass() { try { return channel.socket().getTrafficClass(); } catch (SocketException e) { throw new RuntimeIoException(e); } } /** * {@inheritDoc} * @throws RuntimeIoException If the socket is closed or if we get an * {@link SocketException} */ public void setTrafficClass(int trafficClass) { try { channel.socket().setTrafficClass(trafficClass); } catch (SocketException e) { throw new RuntimeIoException(e); } } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/package.html0000644000175000017500000000236012032276033031437 0ustar ebourgebourg Socket (TCP/IP) and Datagram (UDP/IP) support based on Java NIO (New I/O) API.

Configuring the number of NIO selector loops

You can specify the number of Socket I/O thread to utilize multi-processors efficiently by specifying the number of processing threads in the constructor. The default is 1

mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioSession.java0000644000175000017500000000577212032276033032124 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket.nio; import java.nio.channels.ByteChannel; import java.nio.channels.Channel; import java.nio.channels.SelectionKey; import org.apache.mina.core.filterchain.DefaultIoFilterChain; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.IoService; import org.apache.mina.core.session.AbstractIoSession; import org.apache.mina.core.session.IoSession; /** * An {@link IoSession} which is managed by the NIO transport. * * @author Apache MINA Project */ public abstract class NioSession extends AbstractIoSession { /** The NioSession processor */ protected final IoProcessor processor; /** The communication channel */ protected final Channel channel; /** The SelectionKey used for this session */ protected SelectionKey key; /** The FilterChain created for this session */ private final IoFilterChain filterChain; /** * * Creates a new instance of NioSession, with its associated IoProcessor. *
* This method is only called by the inherited class. * * @param processor The associated IoProcessor */ protected NioSession(IoProcessor processor, IoService service, Channel channel) { super(service); this.channel = channel; this.processor = processor; filterChain = new DefaultIoFilterChain(this); } /** * @return The ByteChannel associated with this {@link IoSession} */ abstract ByteChannel getChannel(); public IoFilterChain getFilterChain() { return filterChain; } /** * @return The {@link SelectionKey} associated with this {@link IoSession} */ /* No qualifier*/SelectionKey getSelectionKey() { return key; } /** * Sets the {@link SelectionKey} for this {@link IoSession} * * @param key The new {@link SelectionKey} */ /* No qualifier*/void setSelectionKey(SelectionKey key) { this.key = key; } /** * {@inheritDoc} */ public IoProcessor getProcessor() { return processor; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/DatagramAcceptor.java0000644000175000017500000000324312032276033032436 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket; import java.net.InetSocketAddress; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.session.IoSessionRecycler; /** * {@link IoAcceptor} for datagram transport (UDP/IP). * * @author Apache MINA Project */ public interface DatagramAcceptor extends IoAcceptor { InetSocketAddress getLocalAddress(); InetSocketAddress getDefaultLocalAddress(); void setDefaultLocalAddress(InetSocketAddress localAddress); /** * Returns the {@link IoSessionRecycler} for this service. */ IoSessionRecycler getSessionRecycler(); /** * Sets the {@link IoSessionRecycler} for this service. * * @param sessionRecycler null to use the default recycler */ void setSessionRecycler(IoSessionRecycler sessionRecycler); } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/AbstractSocketSessionConfig.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/AbstractSocketSessionC0000644000175000017500000001572212032276033032705 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket; import org.apache.mina.core.session.AbstractIoSessionConfig; import org.apache.mina.core.session.IoSessionConfig; /** * TODO Add documentation * * @author Apache MINA Project */ public abstract class AbstractSocketSessionConfig extends AbstractIoSessionConfig implements SocketSessionConfig { protected AbstractSocketSessionConfig() { // Do nothing } @Override protected final void doSetAll(IoSessionConfig config) { if (!(config instanceof SocketSessionConfig)) { return; } if (config instanceof AbstractSocketSessionConfig) { // Minimize unnecessary system calls by checking all 'propertyChanged' properties. AbstractSocketSessionConfig cfg = (AbstractSocketSessionConfig) config; if (cfg.isKeepAliveChanged()) { setKeepAlive(cfg.isKeepAlive()); } if (cfg.isOobInlineChanged()) { setOobInline(cfg.isOobInline()); } if (cfg.isReceiveBufferSizeChanged()) { setReceiveBufferSize(cfg.getReceiveBufferSize()); } if (cfg.isReuseAddressChanged()) { setReuseAddress(cfg.isReuseAddress()); } if (cfg.isSendBufferSizeChanged()) { setSendBufferSize(cfg.getSendBufferSize()); } if (cfg.isSoLingerChanged()) { setSoLinger(cfg.getSoLinger()); } if (cfg.isTcpNoDelayChanged()) { setTcpNoDelay(cfg.isTcpNoDelay()); } if (cfg.isTrafficClassChanged() && getTrafficClass() != cfg.getTrafficClass()) { setTrafficClass(cfg.getTrafficClass()); } } else { SocketSessionConfig cfg = (SocketSessionConfig) config; setKeepAlive(cfg.isKeepAlive()); setOobInline(cfg.isOobInline()); setReceiveBufferSize(cfg.getReceiveBufferSize()); setReuseAddress(cfg.isReuseAddress()); setSendBufferSize(cfg.getSendBufferSize()); setSoLinger(cfg.getSoLinger()); setTcpNoDelay(cfg.isTcpNoDelay()); if (getTrafficClass() != cfg.getTrafficClass()) { setTrafficClass(cfg.getTrafficClass()); } } } /** * Returns true if and only if the keepAlive property * has been changed by its setter method. The system call related with * the property is made only when this method returns true. By * default, this method always returns true to simplify implementation * of subclasses, but overriding the default behavior is always encouraged. */ protected boolean isKeepAliveChanged() { return true; } /** * Returns true if and only if the oobInline property * has been changed by its setter method. The system call related with * the property is made only when this method returns true. By * default, this method always returns true to simplify implementation * of subclasses, but overriding the default behavior is always encouraged. */ protected boolean isOobInlineChanged() { return true; } /** * Returns true if and only if the receiveBufferSize property * has been changed by its setter method. The system call related with * the property is made only when this method returns true. By * default, this method always returns true to simplify implementation * of subclasses, but overriding the default behavior is always encouraged. */ protected boolean isReceiveBufferSizeChanged() { return true; } /** * Returns true if and only if the reuseAddress property * has been changed by its setter method. The system call related with * the property is made only when this method returns true. By * default, this method always returns true to simplify implementation * of subclasses, but overriding the default behavior is always encouraged. */ protected boolean isReuseAddressChanged() { return true; } /** * Returns true if and only if the sendBufferSize property * has been changed by its setter method. The system call related with * the property is made only when this method returns true. By * default, this method always returns true to simplify implementation * of subclasses, but overriding the default behavior is always encouraged. */ protected boolean isSendBufferSizeChanged() { return true; } /** * Returns true if and only if the soLinger property * has been changed by its setter method. The system call related with * the property is made only when this method returns true. By * default, this method always returns true to simplify implementation * of subclasses, but overriding the default behavior is always encouraged. */ protected boolean isSoLingerChanged() { return true; } /** * Returns true if and only if the tcpNoDelay property * has been changed by its setter method. The system call related with * the property is made only when this method returns true. By * default, this method always returns true to simplify implementation * of subclasses, but overriding the default behavior is always encouraged. */ protected boolean isTcpNoDelayChanged() { return true; } /** * Returns true if and only if the trafficClass property * has been changed by its setter method. The system call related with * the property is made only when this method returns true. By * default, this method always returns true to simplify implementation * of subclasses, but overriding the default behavior is always encouraged. */ protected boolean isTrafficClassChanged() { return true; } }././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/AbstractDatagramSessionConfig.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/AbstractDatagramSessio0000644000175000017500000001310412032276033032704 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket; import org.apache.mina.core.session.AbstractIoSessionConfig; import org.apache.mina.core.session.IoSessionConfig; /** * TODO Add documentation * * @author Apache MINA Project */ public abstract class AbstractDatagramSessionConfig extends AbstractIoSessionConfig implements DatagramSessionConfig { private static final boolean DEFAULT_CLOSE_ON_PORT_UNREACHABLE = true; private boolean closeOnPortUnreachable = DEFAULT_CLOSE_ON_PORT_UNREACHABLE; protected AbstractDatagramSessionConfig() { // Do nothing } @Override protected void doSetAll(IoSessionConfig config) { if (!(config instanceof DatagramSessionConfig)) { return; } if (config instanceof AbstractDatagramSessionConfig) { // Minimize unnecessary system calls by checking all 'propertyChanged' properties. AbstractDatagramSessionConfig cfg = (AbstractDatagramSessionConfig) config; if (cfg.isBroadcastChanged()) { setBroadcast(cfg.isBroadcast()); } if (cfg.isReceiveBufferSizeChanged()) { setReceiveBufferSize(cfg.getReceiveBufferSize()); } if (cfg.isReuseAddressChanged()) { setReuseAddress(cfg.isReuseAddress()); } if (cfg.isSendBufferSizeChanged()) { setSendBufferSize(cfg.getSendBufferSize()); } if (cfg.isTrafficClassChanged() && getTrafficClass() != cfg.getTrafficClass()) { setTrafficClass(cfg.getTrafficClass()); } } else { DatagramSessionConfig cfg = (DatagramSessionConfig) config; setBroadcast(cfg.isBroadcast()); setReceiveBufferSize(cfg.getReceiveBufferSize()); setReuseAddress(cfg.isReuseAddress()); setSendBufferSize(cfg.getSendBufferSize()); if (getTrafficClass() != cfg.getTrafficClass()) { setTrafficClass(cfg.getTrafficClass()); } } } /** * Returns true if and only if the broadcast property * has been changed by its setter method. The system call related with * the property is made only when this method returns true. By * default, this method always returns true to simplify implementation * of subclasses, but overriding the default behavior is always encouraged. */ protected boolean isBroadcastChanged() { return true; } /** * Returns true if and only if the receiveBufferSize property * has been changed by its setter method. The system call related with * the property is made only when this method returns true. By * default, this method always returns true to simplify implementation * of subclasses, but overriding the default behavior is always encouraged. */ protected boolean isReceiveBufferSizeChanged() { return true; } /** * Returns true if and only if the reuseAddress property * has been changed by its setter method. The system call related with * the property is made only when this method returns true. By * default, this method always returns true to simplify implementation * of subclasses, but overriding the default behavior is always encouraged. */ protected boolean isReuseAddressChanged() { return true; } /** * Returns true if and only if the sendBufferSize property * has been changed by its setter method. The system call related with * the property is made only when this method returns true. By * default, this method always returns true to simplify implementation * of subclasses, but overriding the default behavior is always encouraged. */ protected boolean isSendBufferSizeChanged() { return true; } /** * Returns true if and only if the trafficClass property * has been changed by its setter method. The system call related with * the property is made only when this method returns true. By * default, this method always returns true to simplify implementation * of subclasses, but overriding the default behavior is always encouraged. */ protected boolean isTrafficClassChanged() { return true; } /** * {@inheritDoc} */ public boolean isCloseOnPortUnreachable() { return closeOnPortUnreachable; } /** * {@inheritDoc} */ public void setCloseOnPortUnreachable(boolean closeOnPortUnreachable) { this.closeOnPortUnreachable = closeOnPortUnreachable; } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/DatagramConnector.java0000644000175000017500000000236112032276033032630 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket; import java.net.InetSocketAddress; import org.apache.mina.core.service.IoConnector; /** * {@link IoConnector} for datagram transport (UDP/IP). * * @author Apache MINA Project */ public interface DatagramConnector extends IoConnector { InetSocketAddress getDefaultRemoteAddress(); void setDefaultRemoteAddress(InetSocketAddress remoteAddress); } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/DefaultDatagramSessionConfig.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/DefaultDatagramSession0000644000175000017500000001005212032276033032702 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket; import java.net.DatagramSocket; /** * A default implementation of {@link DatagramSessionConfig}. * * @author Apache MINA Project */ public class DefaultDatagramSessionConfig extends AbstractDatagramSessionConfig { private static boolean DEFAULT_BROADCAST = false; private static boolean DEFAULT_REUSE_ADDRESS = false; /* The SO_RCVBUF parameter. Set to -1 (ie, will default to OS default) */ private static int DEFAULT_RECEIVE_BUFFER_SIZE = -1; /* The SO_SNDBUF parameter. Set to -1 (ie, will default to OS default) */ private static int DEFAULT_SEND_BUFFER_SIZE = -1; private static int DEFAULT_TRAFFIC_CLASS = 0; private boolean broadcast = DEFAULT_BROADCAST; private boolean reuseAddress = DEFAULT_REUSE_ADDRESS; private int receiveBufferSize = DEFAULT_RECEIVE_BUFFER_SIZE; private int sendBufferSize = DEFAULT_SEND_BUFFER_SIZE; private int trafficClass = DEFAULT_TRAFFIC_CLASS; /** * Creates a new instance. */ public DefaultDatagramSessionConfig() { // Do nothing } /** * @see DatagramSocket#getBroadcast() */ public boolean isBroadcast() { return broadcast; } /** * @see DatagramSocket#setBroadcast(boolean) */ public void setBroadcast(boolean broadcast) { this.broadcast = broadcast; } /** * @see DatagramSocket#getReuseAddress() */ public boolean isReuseAddress() { return reuseAddress; } /** * @see DatagramSocket#setReuseAddress(boolean) */ public void setReuseAddress(boolean reuseAddress) { this.reuseAddress = reuseAddress; } /** * @see DatagramSocket#getReceiveBufferSize() */ public int getReceiveBufferSize() { return receiveBufferSize; } /** * @see DatagramSocket#setReceiveBufferSize(int) */ public void setReceiveBufferSize(int receiveBufferSize) { this.receiveBufferSize = receiveBufferSize; } /** * @see DatagramSocket#getSendBufferSize() */ public int getSendBufferSize() { return sendBufferSize; } /** * @see DatagramSocket#setSendBufferSize(int) */ public void setSendBufferSize(int sendBufferSize) { this.sendBufferSize = sendBufferSize; } /** * @see DatagramSocket#getTrafficClass() */ public int getTrafficClass() { return trafficClass; } /** * @see DatagramSocket#setTrafficClass(int) */ public void setTrafficClass(int trafficClass) { this.trafficClass = trafficClass; } @Override protected boolean isBroadcastChanged() { return broadcast != DEFAULT_BROADCAST; } @Override protected boolean isReceiveBufferSizeChanged() { return receiveBufferSize != DEFAULT_RECEIVE_BUFFER_SIZE; } @Override protected boolean isReuseAddressChanged() { return reuseAddress != DEFAULT_REUSE_ADDRESS; } @Override protected boolean isSendBufferSizeChanged() { return sendBufferSize != DEFAULT_SEND_BUFFER_SIZE; } @Override protected boolean isTrafficClassChanged() { return trafficClass != DEFAULT_TRAFFIC_CLASS; } }././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/DefaultSocketSessionConfig.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/DefaultSocketSessionCo0000644000175000017500000001125612032276033032703 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket; import org.apache.mina.core.service.IoService; /** * A default implementation of {@link SocketSessionConfig}. * * @author Apache MINA Project */ public class DefaultSocketSessionConfig extends AbstractSocketSessionConfig { private static boolean DEFAULT_REUSE_ADDRESS = false; private static int DEFAULT_TRAFFIC_CLASS = 0; private static boolean DEFAULT_KEEP_ALIVE = false; private static boolean DEFAULT_OOB_INLINE = false; private static int DEFAULT_SO_LINGER = -1; private static boolean DEFAULT_TCP_NO_DELAY = false; protected IoService parent; private boolean defaultReuseAddress; private boolean reuseAddress; /* The SO_RCVBUF parameter. Set to -1 (ie, will default to OS default) */ private int receiveBufferSize = -1; /* The SO_SNDBUF parameter. Set to -1 (ie, will default to OS default) */ private int sendBufferSize = -1; private int trafficClass = DEFAULT_TRAFFIC_CLASS; private boolean keepAlive = DEFAULT_KEEP_ALIVE; private boolean oobInline = DEFAULT_OOB_INLINE; private int soLinger = DEFAULT_SO_LINGER; private boolean tcpNoDelay = DEFAULT_TCP_NO_DELAY; /** * Creates a new instance. */ public DefaultSocketSessionConfig() { // Do nothing } public void init(IoService parent) { this.parent = parent; if (parent instanceof SocketAcceptor) { defaultReuseAddress = true; } else { defaultReuseAddress = DEFAULT_REUSE_ADDRESS; } reuseAddress = defaultReuseAddress; } public boolean isReuseAddress() { return reuseAddress; } public void setReuseAddress(boolean reuseAddress) { this.reuseAddress = reuseAddress; } public int getReceiveBufferSize() { return receiveBufferSize; } public void setReceiveBufferSize(int receiveBufferSize) { this.receiveBufferSize = receiveBufferSize; } public int getSendBufferSize() { return sendBufferSize; } public void setSendBufferSize(int sendBufferSize) { this.sendBufferSize = sendBufferSize; } public int getTrafficClass() { return trafficClass; } public void setTrafficClass(int trafficClass) { this.trafficClass = trafficClass; } public boolean isKeepAlive() { return keepAlive; } public void setKeepAlive(boolean keepAlive) { this.keepAlive = keepAlive; } public boolean isOobInline() { return oobInline; } public void setOobInline(boolean oobInline) { this.oobInline = oobInline; } public int getSoLinger() { return soLinger; } public void setSoLinger(int soLinger) { this.soLinger = soLinger; } public boolean isTcpNoDelay() { return tcpNoDelay; } public void setTcpNoDelay(boolean tcpNoDelay) { this.tcpNoDelay = tcpNoDelay; } @Override protected boolean isKeepAliveChanged() { return keepAlive != DEFAULT_KEEP_ALIVE; } @Override protected boolean isOobInlineChanged() { return oobInline != DEFAULT_OOB_INLINE; } @Override protected boolean isReceiveBufferSizeChanged() { return receiveBufferSize != -1; } @Override protected boolean isReuseAddressChanged() { return reuseAddress != defaultReuseAddress; } @Override protected boolean isSendBufferSizeChanged() { return sendBufferSize != -1; } @Override protected boolean isSoLingerChanged() { return soLinger != DEFAULT_SO_LINGER; } @Override protected boolean isTcpNoDelayChanged() { return tcpNoDelay != DEFAULT_TCP_NO_DELAY; } @Override protected boolean isTrafficClassChanged() { return trafficClass != DEFAULT_TRAFFIC_CLASS; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/socket/SocketAcceptor.java0000644000175000017500000000374412032276033032154 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.socket; import java.net.InetSocketAddress; import java.net.ServerSocket; import org.apache.mina.core.service.IoAcceptor; /** * {@link IoAcceptor} for socket transport (TCP/IP). This class * handles incoming TCP/IP based socket connections. * * @author Apache MINA Project */ public interface SocketAcceptor extends IoAcceptor { InetSocketAddress getLocalAddress(); InetSocketAddress getDefaultLocalAddress(); void setDefaultLocalAddress(InetSocketAddress localAddress); /** * @see ServerSocket#getReuseAddress() */ public boolean isReuseAddress(); /** * @see ServerSocket#setReuseAddress(boolean) */ public void setReuseAddress(boolean reuseAddress); /** * Returns the size of the backlog. */ public int getBacklog(); /** * Sets the size of the backlog. This can only be done when this * class is not bound */ public void setBacklog(int backlog); /** * Returns the default configuration of the new SocketSessions created by * this acceptor service. */ SocketSessionConfig getSessionConfig(); } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/vmpipe/0000755000175000017500000000000012162575507026414 5ustar ebourgebourg././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeSessionConfig.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeSessionConfig.ja0000644000175000017500000000216512032276032032611 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.vmpipe; import org.apache.mina.core.session.IoSessionConfig; /** * An {@link IoSessionConfig} for vmpipe transport type. * * @author Apache MINA Project */ public interface VmPipeSessionConfig extends IoSessionConfig { // Do nothing } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/vmpipe/VmPipe.java0000644000175000017500000000345112032276032030445 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.vmpipe; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoServiceListenerSupport; /** * TODO Add documentation * * @author Apache MINA Project */ class VmPipe { private final VmPipeAcceptor acceptor; private final VmPipeAddress address; private final IoHandler handler; private final IoServiceListenerSupport listeners; VmPipe(VmPipeAcceptor acceptor, VmPipeAddress address, IoHandler handler, IoServiceListenerSupport listeners) { this.acceptor = acceptor; this.address = address; this.handler = handler; this.listeners = listeners; } public VmPipeAcceptor getAcceptor() { return acceptor; } public VmPipeAddress getAddress() { return address; } public IoHandler getHandler() { return handler; } public IoServiceListenerSupport getListeners() { return listeners; } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeAcceptor.java0000644000175000017500000001322412032276032032125 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.vmpipe; import java.io.IOException; import java.net.SocketAddress; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.Executor; import org.apache.mina.core.future.IoFuture; import org.apache.mina.core.service.AbstractIoAcceptor; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.core.session.IdleStatusChecker; import org.apache.mina.core.session.IoSession; /** * Binds the specified {@link IoHandler} to the specified * {@link VmPipeAddress}. * * @author Apache MINA Project */ public final class VmPipeAcceptor extends AbstractIoAcceptor { // object used for checking session idle private IdleStatusChecker idleChecker; static final Map boundHandlers = new HashMap(); /** * Creates a new instance. */ public VmPipeAcceptor() { this(null); } /** * Creates a new instance. */ public VmPipeAcceptor(Executor executor) { super(new DefaultVmPipeSessionConfig(), executor); idleChecker = new IdleStatusChecker(); // we schedule the idle status checking task in this service exceutor // it will be woke up every seconds executeWorker(idleChecker.getNotifyingTask(), "idleStatusChecker"); } public TransportMetadata getTransportMetadata() { return VmPipeSession.METADATA; } @Override public VmPipeSessionConfig getSessionConfig() { return (VmPipeSessionConfig) super.getSessionConfig(); } @Override public VmPipeAddress getLocalAddress() { return (VmPipeAddress) super.getLocalAddress(); } @Override public VmPipeAddress getDefaultLocalAddress() { return (VmPipeAddress) super.getDefaultLocalAddress(); } // This method is overriden to work around a problem with // bean property access mechanism. public void setDefaultLocalAddress(VmPipeAddress localAddress) { super.setDefaultLocalAddress(localAddress); } @Override protected void dispose0() throws Exception { // stop the idle checking task idleChecker.getNotifyingTask().cancel(); unbind(); } @Override protected Set bindInternal(List localAddresses) throws IOException { Set newLocalAddresses = new HashSet(); synchronized (boundHandlers) { for (SocketAddress a : localAddresses) { VmPipeAddress localAddress = (VmPipeAddress) a; if (localAddress == null || localAddress.getPort() == 0) { localAddress = null; for (int i = 10000; i < Integer.MAX_VALUE; i++) { VmPipeAddress newLocalAddress = new VmPipeAddress(i); if (!boundHandlers.containsKey(newLocalAddress) && !newLocalAddresses.contains(newLocalAddress)) { localAddress = newLocalAddress; break; } } if (localAddress == null) { throw new IOException("No port available."); } } else if (localAddress.getPort() < 0) { throw new IOException("Bind port number must be 0 or above."); } else if (boundHandlers.containsKey(localAddress)) { throw new IOException("Address already bound: " + localAddress); } newLocalAddresses.add(localAddress); } for (SocketAddress a : newLocalAddresses) { VmPipeAddress localAddress = (VmPipeAddress) a; if (!boundHandlers.containsKey(localAddress)) { boundHandlers.put(localAddress, new VmPipe(this, localAddress, getHandler(), getListeners())); } else { for (SocketAddress a2 : newLocalAddresses) { boundHandlers.remove(a2); } throw new IOException("Duplicate local address: " + a); } } } return newLocalAddresses; } @Override protected void unbind0(List localAddresses) { synchronized (boundHandlers) { for (SocketAddress a : localAddresses) { boundHandlers.remove(a); } } } public IoSession newSession(SocketAddress remoteAddress, SocketAddress localAddress) { throw new UnsupportedOperationException(); } void doFinishSessionInitialization(IoSession session, IoFuture future) { initSession(session, future, null); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/vmpipe/DefaultVmPipeSessionConfig.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/vmpipe/DefaultVmPipeSessionCo0000644000175000017500000000254612032276032032664 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.vmpipe; import org.apache.mina.core.session.AbstractIoSessionConfig; import org.apache.mina.core.session.IoSessionConfig; /** * A default implementation of {@link VmPipeSessionConfig}. * * @author Apache MINA Project */ class DefaultVmPipeSessionConfig extends AbstractIoSessionConfig implements VmPipeSessionConfig { DefaultVmPipeSessionConfig() { // Do nothing } @Override protected void doSetAll(IoSessionConfig config) { // Do nothing } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeConnector.java0000644000175000017500000001473512032276032032327 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.vmpipe; import java.io.IOException; import java.net.SocketAddress; import java.util.HashSet; import java.util.Set; import java.util.concurrent.Executor; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.DefaultConnectFuture; import org.apache.mina.core.future.IoFuture; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.service.AbstractIoConnector; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.core.session.IdleStatusChecker; import org.apache.mina.core.session.IoSessionInitializer; import org.apache.mina.util.ExceptionMonitor; /** * Connects to {@link IoHandler}s which is bound on the specified * {@link VmPipeAddress}. * * @author Apache MINA Project */ public final class VmPipeConnector extends AbstractIoConnector { // object used for checking session idle private IdleStatusChecker idleChecker; /** * Creates a new instance. */ public VmPipeConnector() { this(null); } /** * Creates a new instance. */ public VmPipeConnector(Executor executor) { super(new DefaultVmPipeSessionConfig(), executor); idleChecker = new IdleStatusChecker(); // we schedule the idle status checking task in this service exceutor // it will be woke up every seconds executeWorker(idleChecker.getNotifyingTask(), "idleStatusChecker"); } public TransportMetadata getTransportMetadata() { return VmPipeSession.METADATA; } @Override public VmPipeSessionConfig getSessionConfig() { return (VmPipeSessionConfig) super.getSessionConfig(); } @Override protected ConnectFuture connect0(SocketAddress remoteAddress, SocketAddress localAddress, IoSessionInitializer sessionInitializer) { VmPipe entry = VmPipeAcceptor.boundHandlers.get(remoteAddress); if (entry == null) { return DefaultConnectFuture.newFailedFuture(new IOException("Endpoint unavailable: " + remoteAddress)); } DefaultConnectFuture future = new DefaultConnectFuture(); // Assign the local address dynamically, VmPipeAddress actualLocalAddress; try { actualLocalAddress = nextLocalAddress(); } catch (IOException e) { return DefaultConnectFuture.newFailedFuture(e); } VmPipeSession localSession = new VmPipeSession(this, getListeners(), actualLocalAddress, getHandler(), entry); initSession(localSession, future, sessionInitializer); // and reclaim the local address when the connection is closed. localSession.getCloseFuture().addListener(LOCAL_ADDRESS_RECLAIMER); // initialize connector session try { IoFilterChain filterChain = localSession.getFilterChain(); this.getFilterChainBuilder().buildFilterChain(filterChain); // The following sentences don't throw any exceptions. getListeners().fireSessionCreated(localSession); idleChecker.addSession(localSession); } catch (Throwable t) { future.setException(t); return future; } // initialize acceptor session VmPipeSession remoteSession = localSession.getRemoteSession(); ((VmPipeAcceptor) remoteSession.getService()).doFinishSessionInitialization(remoteSession, null); try { IoFilterChain filterChain = remoteSession.getFilterChain(); entry.getAcceptor().getFilterChainBuilder().buildFilterChain(filterChain); // The following sentences don't throw any exceptions. entry.getListeners().fireSessionCreated(remoteSession); idleChecker.addSession(remoteSession); } catch (Throwable t) { ExceptionMonitor.getInstance().exceptionCaught(t); remoteSession.close(true); } // Start chains, and then allow and messages read/written to be processed. This is to ensure that // sessionOpened gets received before a messageReceived ((VmPipeFilterChain) localSession.getFilterChain()).start(); ((VmPipeFilterChain) remoteSession.getFilterChain()).start(); return future; } @Override protected void dispose0() throws Exception { // stop the idle checking task idleChecker.getNotifyingTask().cancel(); } private static final Set TAKEN_LOCAL_ADDRESSES = new HashSet(); private static int nextLocalPort = -1; private static final IoFutureListener LOCAL_ADDRESS_RECLAIMER = new LocalAddressReclaimer(); private static VmPipeAddress nextLocalAddress() throws IOException { synchronized (TAKEN_LOCAL_ADDRESSES) { if (nextLocalPort >= 0) { nextLocalPort = -1; } for (int i = 0; i < Integer.MAX_VALUE; i++) { VmPipeAddress answer = new VmPipeAddress(nextLocalPort--); if (!TAKEN_LOCAL_ADDRESSES.contains(answer)) { TAKEN_LOCAL_ADDRESSES.add(answer); return answer; } } } throw new IOException("Can't assign a local VM pipe port."); } private static class LocalAddressReclaimer implements IoFutureListener { public void operationComplete(IoFuture future) { synchronized (TAKEN_LOCAL_ADDRESSES) { TAKEN_LOCAL_ADDRESSES.remove(future.getSession().getLocalAddress()); } } } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeAddress.java0000644000175000017500000000415512032276032031755 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.vmpipe; import java.net.SocketAddress; /** * A {@link SocketAddress} which represents in-VM pipe port number. * * @author Apache MINA Project */ public class VmPipeAddress extends SocketAddress implements Comparable { private static final long serialVersionUID = 3257844376976830515L; private final int port; /** * Creates a new instance with the specifid port number. */ public VmPipeAddress(int port) { this.port = port; } /** * Returns the port number. */ public int getPort() { return port; } @Override public int hashCode() { return port; } @Override public boolean equals(Object o) { if (o == null) { return false; } if (this == o) { return true; } if (o instanceof VmPipeAddress) { VmPipeAddress that = (VmPipeAddress) o; return this.port == that.port; } return false; } public int compareTo(VmPipeAddress o) { return this.port - o.port; } @Override public String toString() { if (port >= 0) { return "vm:server:" + port; } return "vm:client:" + -port; } }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeSession.java0000644000175000017500000001114312032276032032006 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.vmpipe; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.service.DefaultTransportMetadata; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.IoService; import org.apache.mina.core.service.IoServiceListenerSupport; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.core.session.AbstractIoSession; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequestQueue; /** * A {@link IoSession} for in-VM transport (VM_PIPE). * * @author Apache MINA Project */ class VmPipeSession extends AbstractIoSession { static final TransportMetadata METADATA = new DefaultTransportMetadata("mina", "vmpipe", false, false, VmPipeAddress.class, VmPipeSessionConfig.class, Object.class); private final IoServiceListenerSupport serviceListeners; private final VmPipeAddress localAddress; private final VmPipeAddress remoteAddress; private final VmPipeAddress serviceAddress; private final VmPipeFilterChain filterChain; private final VmPipeSession remoteSession; private final Lock lock; final BlockingQueue receivedMessageQueue; /* * Constructor for client-side session. */ VmPipeSession(IoService service, IoServiceListenerSupport serviceListeners, VmPipeAddress localAddress, IoHandler handler, VmPipe remoteEntry) { super(service); config = new DefaultVmPipeSessionConfig(); this.serviceListeners = serviceListeners; lock = new ReentrantLock(); this.localAddress = localAddress; remoteAddress = serviceAddress = remoteEntry.getAddress(); filterChain = new VmPipeFilterChain(this); receivedMessageQueue = new LinkedBlockingQueue(); remoteSession = new VmPipeSession(this, remoteEntry); } /* * Constructor for server-side session. */ private VmPipeSession(VmPipeSession remoteSession, VmPipe entry) { super(entry.getAcceptor()); config = new DefaultVmPipeSessionConfig(); serviceListeners = entry.getListeners(); lock = remoteSession.lock; localAddress = serviceAddress = remoteSession.remoteAddress; remoteAddress = remoteSession.localAddress; filterChain = new VmPipeFilterChain(this); this.remoteSession = remoteSession; receivedMessageQueue = new LinkedBlockingQueue(); } @Override public IoProcessor getProcessor() { return filterChain.getProcessor(); } IoServiceListenerSupport getServiceListeners() { return serviceListeners; } public VmPipeSessionConfig getConfig() { return (VmPipeSessionConfig) config; } public IoFilterChain getFilterChain() { return filterChain; } public VmPipeSession getRemoteSession() { return remoteSession; } public TransportMetadata getTransportMetadata() { return METADATA; } public VmPipeAddress getRemoteAddress() { return remoteAddress; } public VmPipeAddress getLocalAddress() { return localAddress; } @Override public VmPipeAddress getServiceAddress() { return serviceAddress; } void increaseWrittenBytes0(int increment, long currentTime) { super.increaseWrittenBytes(increment, currentTime); } WriteRequestQueue getWriteRequestQueue0() { return super.getWriteRequestQueue(); } Lock getLock() { return lock; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeFilterChain.java0000644000175000017500000002341512032276032032560 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.vmpipe; import java.util.ArrayList; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.DefaultIoFilterChain; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.session.AbstractIoSession; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoEvent; import org.apache.mina.core.session.IoEventType; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.core.write.WriteRequestQueue; import org.apache.mina.core.write.WriteToClosedSessionException; /** * TODO Add documentation * * @author Apache MINA Project */ class VmPipeFilterChain extends DefaultIoFilterChain { private final Queue eventQueue = new ConcurrentLinkedQueue(); private final IoProcessor processor = new VmPipeIoProcessor(); private volatile boolean flushEnabled; private volatile boolean sessionOpened; VmPipeFilterChain(AbstractIoSession session) { super(session); } IoProcessor getProcessor() { return processor; } public void start() { flushEnabled = true; flushEvents(); flushPendingDataQueues((VmPipeSession) getSession()); } private void pushEvent(IoEvent e) { pushEvent(e, flushEnabled); } private void pushEvent(IoEvent e, boolean flushNow) { eventQueue.add(e); if (flushNow) { flushEvents(); } } private void flushEvents() { IoEvent e; while ((e = eventQueue.poll()) != null) { fireEvent(e); } } private void fireEvent(IoEvent e) { VmPipeSession session = (VmPipeSession) getSession(); IoEventType type = e.getType(); Object data = e.getParameter(); if (type == IoEventType.MESSAGE_RECEIVED) { if (sessionOpened && (!session.isReadSuspended()) && session.getLock().tryLock()) { try { if (session.isReadSuspended()) { session.receivedMessageQueue.add(data); } else { super.fireMessageReceived(data); } } finally { session.getLock().unlock(); } } else { session.receivedMessageQueue.add(data); } } else if (type == IoEventType.WRITE) { super.fireFilterWrite((WriteRequest) data); } else if (type == IoEventType.MESSAGE_SENT) { super.fireMessageSent((WriteRequest) data); } else if (type == IoEventType.EXCEPTION_CAUGHT) { super.fireExceptionCaught((Throwable) data); } else if (type == IoEventType.SESSION_IDLE) { super.fireSessionIdle((IdleStatus) data); } else if (type == IoEventType.SESSION_OPENED) { super.fireSessionOpened(); sessionOpened = true; } else if (type == IoEventType.SESSION_CREATED) { session.getLock().lock(); try { super.fireSessionCreated(); } finally { session.getLock().unlock(); } } else if (type == IoEventType.SESSION_CLOSED) { flushPendingDataQueues(session); super.fireSessionClosed(); } else if (type == IoEventType.CLOSE) { super.fireFilterClose(); } } private static void flushPendingDataQueues(VmPipeSession s) { s.getProcessor().updateTrafficControl(s); s.getRemoteSession().getProcessor().updateTrafficControl(s); } @Override public void fireFilterClose() { pushEvent(new IoEvent(IoEventType.CLOSE, getSession(), null)); } @Override public void fireFilterWrite(WriteRequest writeRequest) { pushEvent(new IoEvent(IoEventType.WRITE, getSession(), writeRequest)); } @Override public void fireExceptionCaught(Throwable cause) { pushEvent(new IoEvent(IoEventType.EXCEPTION_CAUGHT, getSession(), cause)); } @Override public void fireMessageSent(WriteRequest request) { pushEvent(new IoEvent(IoEventType.MESSAGE_SENT, getSession(), request)); } @Override public void fireSessionClosed() { pushEvent(new IoEvent(IoEventType.SESSION_CLOSED, getSession(), null)); } @Override public void fireSessionCreated() { pushEvent(new IoEvent(IoEventType.SESSION_CREATED, getSession(), null)); } @Override public void fireSessionIdle(IdleStatus status) { pushEvent(new IoEvent(IoEventType.SESSION_IDLE, getSession(), status)); } @Override public void fireSessionOpened() { pushEvent(new IoEvent(IoEventType.SESSION_OPENED, getSession(), null)); } @Override public void fireMessageReceived(Object message) { pushEvent(new IoEvent(IoEventType.MESSAGE_RECEIVED, getSession(), message)); } private class VmPipeIoProcessor implements IoProcessor { public void flush(VmPipeSession session) { WriteRequestQueue queue = session.getWriteRequestQueue0(); if (!session.isClosing()) { session.getLock().lock(); try { if (queue.isEmpty(session)) { return; } WriteRequest req; long currentTime = System.currentTimeMillis(); while ((req = queue.poll(session)) != null) { Object m = req.getMessage(); pushEvent(new IoEvent(IoEventType.MESSAGE_SENT, session, req), false); session.getRemoteSession().getFilterChain().fireMessageReceived(getMessageCopy(m)); if (m instanceof IoBuffer) { session.increaseWrittenBytes0(((IoBuffer) m).remaining(), currentTime); } } } finally { if (flushEnabled) { flushEvents(); } session.getLock().unlock(); } flushPendingDataQueues(session); } else { List failedRequests = new ArrayList(); WriteRequest req; while ((req = queue.poll(session)) != null) { failedRequests.add(req); } if (!failedRequests.isEmpty()) { WriteToClosedSessionException cause = new WriteToClosedSessionException(failedRequests); for (WriteRequest r : failedRequests) { r.getFuture().setException(cause); } session.getFilterChain().fireExceptionCaught(cause); } } } /** * {@inheritDoc} */ public void write(VmPipeSession session, WriteRequest writeRequest) { WriteRequestQueue writeRequestQueue = session.getWriteRequestQueue(); writeRequestQueue.offer(session, writeRequest); if (!session.isWriteSuspended()) { this.flush(session); } } private Object getMessageCopy(Object message) { Object messageCopy = message; if (message instanceof IoBuffer) { IoBuffer rb = (IoBuffer) message; rb.mark(); IoBuffer wb = IoBuffer.allocate(rb.remaining()); wb.put(rb); wb.flip(); rb.reset(); messageCopy = wb; } return messageCopy; } public void remove(VmPipeSession session) { try { session.getLock().lock(); if (!session.getCloseFuture().isClosed()) { session.getServiceListeners().fireSessionDestroyed(session); session.getRemoteSession().close(true); } } finally { session.getLock().unlock(); } } public void add(VmPipeSession session) { // Unused } public void updateTrafficControl(VmPipeSession session) { if (!session.isReadSuspended()) { List data = new ArrayList(); session.receivedMessageQueue.drainTo(data); for (Object aData : data) { VmPipeFilterChain.this.fireMessageReceived(aData); } } if (!session.isWriteSuspended()) { flush(session); } } public void dispose() { // Nothing to dispose } public boolean isDisposed() { return false; } public boolean isDisposing() { return false; } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/transport/vmpipe/package.html0000644000175000017500000000314012032276032030656 0ustar ebourgebourg In-VM pipe support which removes the overhead of local loopback communication.

What is 'in-VM pipe'?

In-VM pipe is a direct event forwarding mechanism between two ProtocolHandlers in the same Java Virtual Machine. Using in-VM pipe, you can remove the overhead of encoding and decoding which is caused uselessly by local loopback network communication. Here are some useful situations possible:

  • SMTP server and SPAM filtering server,
  • web server and Servlet/JSP container.

Please refer to Tennis example.

mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/0000755000175000017500000000000012162575507024475 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/chain/0000755000175000017500000000000012162575507025557 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/chain/IoHandlerChain.java0000644000175000017500000002254412032276033031225 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.handler.chain; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.apache.mina.core.session.IoSession; /** * A chain of {@link IoHandlerCommand}s. * * @author Apache MINA Project */ public class IoHandlerChain implements IoHandlerCommand { private static volatile int nextId = 0; private final int id = nextId++; private final String NEXT_COMMAND = IoHandlerChain.class.getName() + '.' + id + ".nextCommand"; private final Map name2entry = new ConcurrentHashMap(); private final Entry head; private final Entry tail; /** * Creates a new, empty chain of {@link IoHandlerCommand}s. */ public IoHandlerChain() { head = new Entry(null, null, "head", createHeadCommand()); tail = new Entry(head, null, "tail", createTailCommand()); head.nextEntry = tail; } private IoHandlerCommand createHeadCommand() { return new IoHandlerCommand() { public void execute(NextCommand next, IoSession session, Object message) throws Exception { next.execute(session, message); } }; } private IoHandlerCommand createTailCommand() { return new IoHandlerCommand() { public void execute(NextCommand next, IoSession session, Object message) throws Exception { next = (NextCommand) session.getAttribute(NEXT_COMMAND); if (next != null) { next.execute(session, message); } } }; } public Entry getEntry(String name) { Entry e = name2entry.get(name); if (e == null) { return null; } return e; } public IoHandlerCommand get(String name) { Entry e = getEntry(name); if (e == null) { return null; } return e.getCommand(); } public NextCommand getNextCommand(String name) { Entry e = getEntry(name); if (e == null) { return null; } return e.getNextCommand(); } public synchronized void addFirst(String name, IoHandlerCommand command) { checkAddable(name); register(head, name, command); } public synchronized void addLast(String name, IoHandlerCommand command) { checkAddable(name); register(tail.prevEntry, name, command); } public synchronized void addBefore(String baseName, String name, IoHandlerCommand command) { Entry baseEntry = checkOldName(baseName); checkAddable(name); register(baseEntry.prevEntry, name, command); } public synchronized void addAfter(String baseName, String name, IoHandlerCommand command) { Entry baseEntry = checkOldName(baseName); checkAddable(name); register(baseEntry, name, command); } public synchronized IoHandlerCommand remove(String name) { Entry entry = checkOldName(name); deregister(entry); return entry.getCommand(); } public synchronized void clear() throws Exception { Iterator it = new ArrayList(name2entry.keySet()).iterator(); while (it.hasNext()) { this.remove(it.next()); } } private void register(Entry prevEntry, String name, IoHandlerCommand command) { Entry newEntry = new Entry(prevEntry, prevEntry.nextEntry, name, command); prevEntry.nextEntry.prevEntry = newEntry; prevEntry.nextEntry = newEntry; name2entry.put(name, newEntry); } private void deregister(Entry entry) { Entry prevEntry = entry.prevEntry; Entry nextEntry = entry.nextEntry; prevEntry.nextEntry = nextEntry; nextEntry.prevEntry = prevEntry; name2entry.remove(entry.name); } /** * Throws an exception when the specified filter name is not registered in this chain. * * @return An filter entry with the specified name. */ private Entry checkOldName(String baseName) { Entry e = name2entry.get(baseName); if (e == null) { throw new IllegalArgumentException("Unknown filter name:" + baseName); } return e; } /** * Checks the specified filter name is already taken and throws an exception if already taken. */ private void checkAddable(String name) { if (name2entry.containsKey(name)) { throw new IllegalArgumentException("Other filter is using the same name '" + name + "'"); } } public void execute(NextCommand next, IoSession session, Object message) throws Exception { if (next != null) { session.setAttribute(NEXT_COMMAND, next); } try { callNextCommand(head, session, message); } finally { session.removeAttribute(NEXT_COMMAND); } } private void callNextCommand(Entry entry, IoSession session, Object message) throws Exception { entry.getCommand().execute(entry.getNextCommand(), session, message); } public List getAll() { List list = new ArrayList(); Entry e = head.nextEntry; while (e != tail) { list.add(e); e = e.nextEntry; } return list; } public List getAllReversed() { List list = new ArrayList(); Entry e = tail.prevEntry; while (e != head) { list.add(e); e = e.prevEntry; } return list; } public boolean contains(String name) { return getEntry(name) != null; } public boolean contains(IoHandlerCommand command) { Entry e = head.nextEntry; while (e != tail) { if (e.getCommand() == command) { return true; } e = e.nextEntry; } return false; } public boolean contains(Class commandType) { Entry e = head.nextEntry; while (e != tail) { if (commandType.isAssignableFrom(e.getCommand().getClass())) { return true; } e = e.nextEntry; } return false; } @Override public String toString() { StringBuilder buf = new StringBuilder(); buf.append("{ "); boolean empty = true; Entry e = head.nextEntry; while (e != tail) { if (!empty) { buf.append(", "); } else { empty = false; } buf.append('('); buf.append(e.getName()); buf.append(':'); buf.append(e.getCommand()); buf.append(')'); e = e.nextEntry; } if (empty) { buf.append("empty"); } buf.append(" }"); return buf.toString(); } /** * Represents a name-command pair that an {@link IoHandlerChain} contains. * * @author Apache MINA Project */ public class Entry { private Entry prevEntry; private Entry nextEntry; private final String name; private final IoHandlerCommand command; private final NextCommand nextCommand; private Entry(Entry prevEntry, Entry nextEntry, String name, IoHandlerCommand command) { if (command == null) { throw new IllegalArgumentException("command"); } if (name == null) { throw new IllegalArgumentException("name"); } this.prevEntry = prevEntry; this.nextEntry = nextEntry; this.name = name; this.command = command; this.nextCommand = new NextCommand() { public void execute(IoSession session, Object message) throws Exception { Entry nextEntry = Entry.this.nextEntry; callNextCommand(nextEntry, session, message); } }; } /** * Returns the name of the command. */ public String getName() { return name; } /** * Returns the command. */ public IoHandlerCommand getCommand() { return command; } /** * Returns the {@link IoHandlerCommand.NextCommand} of the command. */ public NextCommand getNextCommand() { return nextCommand; } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/chain/IoHandlerCommand.java0000644000175000017500000000765212032276033031564 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.handler.chain; import org.apache.mina.core.session.IoSession; /** *

A {@link IoHandlerCommand} encapsulates a unit of processing work to be * performed, whose purpose is to examine and/or modify the state of a * transaction that is represented by custom attributes provided by * {@link IoSession}. Individual {@link IoHandlerCommand}s can be assembled into * a {@link IoHandlerChain}, which allows them to either complete the * required processing or delegate further processing to the next * {@link IoHandlerCommand} in the {@link IoHandlerChain}.

* *

{@link IoHandlerCommand} implementations typically retrieve and store state * information in the {@link IoSession} that is passed as a parameter to * the {@link #execute(NextCommand,IoSession,Object)} method, using custom * session attributes. If you think getting attributes is tedious process, * you can create a bean which contains getters and setters of all properties * and store the bean as a session attribute:

* *
 * public class MyContext {
 *   public String getPropertyX() { ... };
 *   public void setPropertyX(String propertyX) { ... };
 *   public int getPropertyZ() { ... };
 *   public void setPropertyZ(int propertyZ) { ... };
 * }
 *
 * public class MyHandlderCommand implements IoHandlerCommand {
 *   public void execute( NextCommand next, IoSession session, Object message ) throws Exception {
 *     MyContext ctx = session.getAttribute( "mycontext" );
 *     ...
 *   }
 * }
 * 
* * @author Apache MINA Project */ public interface IoHandlerCommand { /** *

Execute a unit of processing work to be performed. This * {@link IoHandlerCommand} may either complete the required processing * and just return to stop the processing, or delegate remaining * processing to the next {@link IoHandlerCommand} in a {@link IoHandlerChain} * containing this {@link IoHandlerCommand} by calling * {@link NextCommand#execute(IoSession,Object)}. * * @param next an indirect reference to the next {@link IoHandlerCommand} that * provides a way to forward the request to the next {@link IoHandlerCommand}. * @param session the {@link IoSession} which is associated with * this request * @param message the message object of this request * * @exception Exception general purpose exception return * to indicate abnormal termination */ void execute(NextCommand next, IoSession session, Object message) throws Exception; /** * Represents an indirect reference to the next {@link IoHandlerCommand} of * the {@link IoHandlerChain}. This interface provides a way to forward * the request to the next {@link IoHandlerCommand}. * * @author Apache MINA Project */ public interface NextCommand { /** * Forwards the request to the next {@link IoHandlerCommand} in the * {@link IoHandlerChain}. */ void execute(IoSession session, Object message) throws Exception; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/chain/package.html0000644000175000017500000000174712032276033030035 0ustar ebourgebourg A handler implementation that helps you implement sequentially layered protocols using Chains of Responsibility pattern. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/chain/ChainedIoHandler.java0000644000175000017500000000453312032276033031534 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.handler.chain; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; /** * An {@link IoHandler} which executes an {@link IoHandlerChain} * on a messageReceived event. * * @author Apache MINA Project */ public class ChainedIoHandler extends IoHandlerAdapter { private final IoHandlerChain chain; /** * Creates a new instance which contains an empty {@link IoHandlerChain}. */ public ChainedIoHandler() { chain = new IoHandlerChain(); } /** * Creates a new instance which executes the specified * {@link IoHandlerChain} on a messageReceived event. * * @param chain an {@link IoHandlerChain} to execute */ public ChainedIoHandler(IoHandlerChain chain) { if (chain == null) { throw new IllegalArgumentException("chain"); } this.chain = chain; } /** * Returns the {@link IoHandlerCommand} this handler will use to * handle messageReceived events. */ public IoHandlerChain getChain() { return chain; } /** * Handles the specified messageReceived event with the * {@link IoHandlerCommand} or {@link IoHandlerChain} you specified * in the constructor. */ @Override public void messageReceived(IoSession session, Object message) throws Exception { chain.execute(null, session, message); } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/demux/0000755000175000017500000000000012162575507025617 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/demux/DemuxingIoHandler.java0000644000175000017500000003321312032276033032016 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.handler.demux; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.UnknownMessageTypeException; import org.apache.mina.util.IdentityHashSet; /** * A {@link IoHandler} that demuxes messageReceived events * to the appropriate {@link MessageHandler}. *

* You can freely register and deregister {@link MessageHandler}s using * {@link #addReceivedMessageHandler(Class, MessageHandler)} and * {@link #removeReceivedMessageHandler(Class)}. *

*

* When message is received through a call to * {@link #messageReceived(IoSession, Object)} the class of the * message object will be used to find a {@link MessageHandler} for * that particular message type. If no {@link MessageHandler} instance can be * found for the immediate class (i.e. message.getClass()) the * interfaces implemented by the immediate class will be searched in depth-first * order. If no match can be found for any of the interfaces the search will be * repeated recursively for the superclass of the immediate class * (i.e. message.getClass().getSuperclass()). *

*

* Consider the following type hierarchy (Cx are classes while * Ix are interfaces): *

 *     C3 - I7 - I9
 *      |    |   /\
 *      |   I8  I3 I4
 *      |
 *     C2 - I5 - I6
 *      |
 *     C1 - I1 - I2 - I4
 *      |         |
 *      |        I3
 *    Object
 * 
* When message is of type C3 this hierarchy will be * searched in the following order: * C3, I7, I8, I9, I3, I4, C2, I5, I6, C1, I1, I2, I3, I4, Object. *

*

* For efficiency searches will be cached. Calls to * {@link #addReceivedMessageHandler(Class, MessageHandler)} and * {@link #removeReceivedMessageHandler(Class)} clear this cache. *

* * @author Apache MINA Project */ public class DemuxingIoHandler extends IoHandlerAdapter { private final Map, MessageHandler> receivedMessageHandlerCache = new ConcurrentHashMap, MessageHandler>(); private final Map, MessageHandler> receivedMessageHandlers = new ConcurrentHashMap, MessageHandler>(); private final Map, MessageHandler> sentMessageHandlerCache = new ConcurrentHashMap, MessageHandler>(); private final Map, MessageHandler> sentMessageHandlers = new ConcurrentHashMap, MessageHandler>(); private final Map, ExceptionHandler> exceptionHandlerCache = new ConcurrentHashMap, ExceptionHandler>(); private final Map, ExceptionHandler> exceptionHandlers = new ConcurrentHashMap, ExceptionHandler>(); /** * Creates a new instance with no registered {@link MessageHandler}s. */ public DemuxingIoHandler() { // Do nothing } /** * Registers a {@link MessageHandler} that handles the received messages of * the specified type. * * @return the old handler if there is already a registered handler for * the specified type. null otherwise. */ @SuppressWarnings("unchecked") public MessageHandler addReceivedMessageHandler(Class type, MessageHandler handler) { receivedMessageHandlerCache.clear(); return (MessageHandler) receivedMessageHandlers.put(type, handler); } /** * Deregisters a {@link MessageHandler} that handles the received messages * of the specified type. * * @return the removed handler if successfully removed. null otherwise. */ @SuppressWarnings("unchecked") public MessageHandler removeReceivedMessageHandler(Class type) { receivedMessageHandlerCache.clear(); return (MessageHandler) receivedMessageHandlers.remove(type); } /** * Registers a {@link MessageHandler} that handles the sent messages of the * specified type. * * @return the old handler if there is already a registered handler for * the specified type. null otherwise. */ @SuppressWarnings("unchecked") public MessageHandler addSentMessageHandler(Class type, MessageHandler handler) { sentMessageHandlerCache.clear(); return (MessageHandler) sentMessageHandlers.put(type, handler); } /** * Deregisters a {@link MessageHandler} that handles the sent messages of * the specified type. * * @return the removed handler if successfully removed. null otherwise. */ @SuppressWarnings("unchecked") public MessageHandler removeSentMessageHandler(Class type) { sentMessageHandlerCache.clear(); return (MessageHandler) sentMessageHandlers.remove(type); } /** * Registers a {@link MessageHandler} that receives the messages of * the specified type. * * @return the old handler if there is already a registered handler for * the specified type. null otherwise. */ @SuppressWarnings("unchecked") public ExceptionHandler addExceptionHandler(Class type, ExceptionHandler handler) { exceptionHandlerCache.clear(); return (ExceptionHandler) exceptionHandlers.put(type, handler); } /** * Deregisters a {@link MessageHandler} that receives the messages of * the specified type. * * @return the removed handler if successfully removed. null otherwise. */ @SuppressWarnings("unchecked") public ExceptionHandler removeExceptionHandler(Class type) { exceptionHandlerCache.clear(); return (ExceptionHandler) exceptionHandlers.remove(type); } /** * Returns the {@link MessageHandler} which is registered to process * the specified type. */ @SuppressWarnings("unchecked") public MessageHandler getMessageHandler(Class type) { return (MessageHandler) receivedMessageHandlers.get(type); } /** * Returns the {@link Map} which contains all messageType-{@link MessageHandler} * pairs registered to this handler for received messages. */ public Map, MessageHandler> getReceivedMessageHandlerMap() { return Collections.unmodifiableMap(receivedMessageHandlers); } /** * Returns the {@link Map} which contains all messageType-{@link MessageHandler} * pairs registered to this handler for sent messages. */ public Map, MessageHandler> getSentMessageHandlerMap() { return Collections.unmodifiableMap(sentMessageHandlers); } /** * Returns the {@link Map} which contains all messageType-{@link MessageHandler} * pairs registered to this handler. */ public Map, ExceptionHandler> getExceptionHandlerMap() { return Collections.unmodifiableMap(exceptionHandlers); } /** * Forwards the received events into the appropriate {@link MessageHandler} * which is registered by {@link #addReceivedMessageHandler(Class, MessageHandler)}. * * Warning ! If you are to overload this method, be aware that you * _must_ call the messageHandler in your own method, otherwise it won't * be called. */ @Override public void messageReceived(IoSession session, Object message) throws Exception { MessageHandler handler = findReceivedMessageHandler(message.getClass()); if (handler != null) { handler.handleMessage(session, message); } else { throw new UnknownMessageTypeException("No message handler found for message type: " + message.getClass().getSimpleName()); } } /** * Invoked when a message written by IoSession.write(Object) is sent out. * * Warning ! If you are to overload this method, be aware that you * _must_ call the messageHandler in your own method, otherwise it won't * be called. */ @Override public void messageSent(IoSession session, Object message) throws Exception { MessageHandler handler = findSentMessageHandler(message.getClass()); if (handler != null) { handler.handleMessage(session, message); } else { throw new UnknownMessageTypeException("No handler found for message type: " + message.getClass().getSimpleName()); } } /** * Invoked when any exception is thrown by user IoHandler implementation * or by MINA. If cause is an instance of IOException, MINA will close the * connection automatically. * * Warning ! If you are to overload this method, be aware that you * _must_ call the messageHandler in your own method, otherwise it won't * be called. */ @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { ExceptionHandler handler = findExceptionHandler(cause.getClass()); if (handler != null) { handler.exceptionCaught(session, cause); } else { throw new UnknownMessageTypeException("No handler found for exception type: " + cause.getClass().getSimpleName()); } } protected MessageHandler findReceivedMessageHandler(Class type) { return findReceivedMessageHandler(type, null); } protected MessageHandler findSentMessageHandler(Class type) { return findSentMessageHandler(type, null); } protected ExceptionHandler findExceptionHandler(Class type) { return findExceptionHandler(type, null); } @SuppressWarnings("unchecked") private MessageHandler findReceivedMessageHandler(Class type, Set triedClasses) { return (MessageHandler) findHandler(receivedMessageHandlers, receivedMessageHandlerCache, type, triedClasses); } @SuppressWarnings("unchecked") private MessageHandler findSentMessageHandler(Class type, Set triedClasses) { return (MessageHandler) findHandler(sentMessageHandlers, sentMessageHandlerCache, type, triedClasses); } @SuppressWarnings("unchecked") private ExceptionHandler findExceptionHandler(Class type, Set triedClasses) { return (ExceptionHandler) findHandler(exceptionHandlers, exceptionHandlerCache, type, triedClasses); } @SuppressWarnings("unchecked") private Object findHandler(Map handlers, Map handlerCache, Class type, Set triedClasses) { Object handler = null; if (triedClasses != null && triedClasses.contains(type)) { return null; } /* * Try the cache first. */ handler = handlerCache.get(type); if (handler != null) { return handler; } /* * Try the registered handlers for an immediate match. */ handler = handlers.get(type); if (handler == null) { /* * No immediate match could be found. Search the type's interfaces. */ if (triedClasses == null) { triedClasses = new IdentityHashSet(); } triedClasses.add(type); Class[] interfaces = type.getInterfaces(); for (Class element : interfaces) { handler = findHandler(handlers, handlerCache, element, triedClasses); if (handler != null) { break; } } } if (handler == null) { /* * No match in type's interfaces could be found. Search the * superclass. */ Class superclass = type.getSuperclass(); if (superclass != null) { handler = findHandler(handlers, handlerCache, superclass, null); } } /* * Make sure the handler is added to the cache. By updating the cache * here all the types (superclasses and interfaces) in the path which * led to a match will be cached along with the immediate message type. */ if (handler != null) { handlerCache.put(type, handler); } return handler; } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/demux/ExceptionHandler.java0000644000175000017500000000436012032276033031705 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.handler.demux; import org.apache.mina.core.session.IoSession; /** * A handler interface that {@link DemuxingIoHandler} forwards * exceptionCaught events to. You have to register your * handler with the type of exception you want to get notified using * {@link DemuxingIoHandler#addExceptionHandler(Class, ExceptionHandler)}. * * @author Apache MINA Project */ public interface ExceptionHandler { /** * A {@link ExceptionHandler} that does nothing. This is useful when * you want to ignore an exception of a specific type silently. */ static ExceptionHandler NOOP = new ExceptionHandler() { public void exceptionCaught(IoSession session, Throwable cause) { // Do nothing } }; /** * A {@link ExceptionHandler} that closes the session immediately. * This is useful when you want to close the session when an exception of * a specific type is raised. */ static ExceptionHandler CLOSE = new ExceptionHandler() { public void exceptionCaught(IoSession session, Throwable cause) { session.close(true); } }; /** * Invoked when the specific type of exception is caught from the * specified session. */ void exceptionCaught(IoSession session, E cause) throws Exception; }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/demux/MessageHandler.java0000644000175000017500000000420312032276033031327 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.handler.demux; import org.apache.mina.core.session.IoSession; /** * A handler interface that {@link DemuxingIoHandler} forwards * messageReceived or messageSent events to. You have to * register your handler with the type of the message you want to get notified * using {@link DemuxingIoHandler#addReceivedMessageHandler(Class, MessageHandler)} * or {@link DemuxingIoHandler#addSentMessageHandler(Class, MessageHandler)}. * * @author Apache MINA Project */ public interface MessageHandler { /** * A {@link MessageHandler} that does nothing. This is useful when * you want to ignore a message of a specific type silently. */ static MessageHandler NOOP = new MessageHandler() { public void handleMessage(IoSession session, Object message) { // Do nothing } }; /** * Invoked when the specific type of message is received from or sent to * the specified session. * * @param session the associated {@link IoSession} * @param message the message to decode. Its type is set by the implementation * @throws Exception if there is an error during the message processing */ void handleMessage(IoSession session, E message) throws Exception; }mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/demux/package.html0000644000175000017500000000177512032276033030076 0ustar ebourgebourg A handler implementation that helps you implement complex protocols by splitting messageReceived handlers into multiple sub-handlers. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/stream/0000755000175000017500000000000012162575507025770 5ustar ebourgebourg././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/stream/IoSessionInputStream.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/stream/IoSessionInputStream.jav0000644000175000017500000001025512032276033032570 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.handler.stream; import java.io.IOException; import java.io.InputStream; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.service.IoHandler; /** * An {@link InputStream} that buffers data read from * {@link IoHandler#messageReceived(IoSession, Object)} events. * * @author Apache MINA Project */ class IoSessionInputStream extends InputStream { private final Object mutex = new Object(); private final IoBuffer buf; private volatile boolean closed; private volatile boolean released; private IOException exception; public IoSessionInputStream() { buf = IoBuffer.allocate(16); buf.setAutoExpand(true); buf.limit(0); } @Override public int available() { if (released) { return 0; } synchronized (mutex) { return buf.remaining(); } } @Override public void close() { if (closed) { return; } synchronized (mutex) { closed = true; releaseBuffer(); mutex.notifyAll(); } } @Override public int read() throws IOException { synchronized (mutex) { if (!waitForData()) { return -1; } return buf.get() & 0xff; } } @Override public int read(byte[] b, int off, int len) throws IOException { synchronized (mutex) { if (!waitForData()) { return -1; } int readBytes; if (len > buf.remaining()) { readBytes = buf.remaining(); } else { readBytes = len; } buf.get(b, off, readBytes); return readBytes; } } private boolean waitForData() throws IOException { if (released) { return false; } synchronized (mutex) { while (!released && buf.remaining() == 0 && exception == null) { try { mutex.wait(); } catch (InterruptedException e) { IOException ioe = new IOException("Interrupted while waiting for more data"); ioe.initCause(e); throw ioe; } } } if (exception != null) { releaseBuffer(); throw exception; } if (closed && buf.remaining() == 0) { releaseBuffer(); return false; } return true; } private void releaseBuffer() { if (released) { return; } released = true; } public void write(IoBuffer src) { synchronized (mutex) { if (closed) { return; } if (buf.hasRemaining()) { this.buf.compact(); this.buf.put(src); this.buf.flip(); } else { this.buf.clear(); this.buf.put(src); this.buf.flip(); mutex.notifyAll(); } } } public void throwException(IOException e) { synchronized (mutex) { if (exception == null) { exception = e; mutex.notifyAll(); } } } }././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/stream/IoSessionOutputStream.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/stream/IoSessionOutputStream.ja0000644000175000017500000000516512032276033032607 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.handler.stream; import java.io.IOException; import java.io.OutputStream; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.session.IoSession; /** * An {@link OutputStream} that forwards all write operations to * the associated {@link IoSession}. * * @author Apache MINA Project */ class IoSessionOutputStream extends OutputStream { private final IoSession session; private WriteFuture lastWriteFuture; public IoSessionOutputStream(IoSession session) { this.session = session; } @Override public void close() throws IOException { try { flush(); } finally { session.close(true).awaitUninterruptibly(); } } private void checkClosed() throws IOException { if (!session.isConnected()) { throw new IOException("The session has been closed."); } } private synchronized void write(IoBuffer buf) throws IOException { checkClosed(); WriteFuture future = session.write(buf); lastWriteFuture = future; } @Override public void write(byte[] b, int off, int len) throws IOException { write(IoBuffer.wrap(b.clone(), off, len)); } @Override public void write(int b) throws IOException { IoBuffer buf = IoBuffer.allocate(1); buf.put((byte) b); buf.flip(); write(buf); } @Override public synchronized void flush() throws IOException { if (lastWriteFuture == null) { return; } lastWriteFuture.awaitUninterruptibly(); if (!lastWriteFuture.isWritten()) { throw new IOException("The bytes could not be written to the session"); } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/stream/StreamIoHandler.java0000644000175000017500000001304312032276033031641 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.handler.stream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.SocketTimeoutException; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A {@link IoHandler} that adapts asynchronous MINA events to stream I/O. *

* Please extend this class and implement * {@link #processStreamIo(IoSession, InputStream, OutputStream)} to * execute your stream I/O logic; please note that you must forward * the process request to other thread or thread pool. * * @author Apache MINA Project */ public abstract class StreamIoHandler extends IoHandlerAdapter { private final static Logger LOGGER = LoggerFactory.getLogger(StreamIoHandler.class); private static final AttributeKey KEY_IN = new AttributeKey(StreamIoHandler.class, "in"); private static final AttributeKey KEY_OUT = new AttributeKey(StreamIoHandler.class, "out"); private int readTimeout; private int writeTimeout; protected StreamIoHandler() { // Do nothing } /** * Implement this method to execute your stream I/O logic; * please note that you must forward the process request to other * thread or thread pool. */ protected abstract void processStreamIo(IoSession session, InputStream in, OutputStream out); /** * Returns read timeout in seconds. * The default value is 0 (disabled). */ public int getReadTimeout() { return readTimeout; } /** * Sets read timeout in seconds. * The default value is 0 (disabled). */ public void setReadTimeout(int readTimeout) { this.readTimeout = readTimeout; } /** * Returns write timeout in seconds. * The default value is 0 (disabled). */ public int getWriteTimeout() { return writeTimeout; } /** * Sets write timeout in seconds. * The default value is 0 (disabled). */ public void setWriteTimeout(int writeTimeout) { this.writeTimeout = writeTimeout; } /** * Initializes streams and timeout settings. */ @Override public void sessionOpened(IoSession session) { // Set timeouts session.getConfig().setWriteTimeout(writeTimeout); session.getConfig().setIdleTime(IdleStatus.READER_IDLE, readTimeout); // Create streams InputStream in = new IoSessionInputStream(); OutputStream out = new IoSessionOutputStream(session); session.setAttribute(KEY_IN, in); session.setAttribute(KEY_OUT, out); processStreamIo(session, in, out); } /** * Closes streams */ @Override public void sessionClosed(IoSession session) throws Exception { final InputStream in = (InputStream) session.getAttribute(KEY_IN); final OutputStream out = (OutputStream) session.getAttribute(KEY_OUT); try { in.close(); } finally { out.close(); } } /** * Forwards read data to input stream. */ @Override public void messageReceived(IoSession session, Object buf) { final IoSessionInputStream in = (IoSessionInputStream) session.getAttribute(KEY_IN); in.write((IoBuffer) buf); } /** * Forwards caught exceptions to input stream. */ @Override public void exceptionCaught(IoSession session, Throwable cause) { final IoSessionInputStream in = (IoSessionInputStream) session.getAttribute(KEY_IN); IOException e = null; if (cause instanceof StreamIoException) { e = (IOException) cause.getCause(); } else if (cause instanceof IOException) { e = (IOException) cause; } if (e != null && in != null) { in.throwException(e); } else { LOGGER.warn("Unexpected exception.", cause); session.close(true); } } /** * Handles read timeout. */ @Override public void sessionIdle(IoSession session, IdleStatus status) { if (status == IdleStatus.READER_IDLE) { throw new StreamIoException(new SocketTimeoutException("Read timeout")); } } private static class StreamIoException extends RuntimeException { private static final long serialVersionUID = 3976736960742503222L; public StreamIoException(IOException cause) { super(cause); } } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/multiton/0000755000175000017500000000000012162575507026350 5ustar ebourgebourg././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/multiton/SingleSessionIoHandler.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/multiton/SingleSessionIoHandler0000644000175000017500000000736312032276033032643 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.handler.multiton; import java.io.IOException; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; /** * A session handler without an {@link IoSession} parameter for simplicity. *

* A {@link SingleSessionIoHandler} is similar to an {@link IoHandler} with * the notable difference that a {@link SingleSessionIoHandler} is used only * by one session at a time. Thus, there is no {@link IoSession} parameter in * the methods of this interface. *

*

* Because events are passed to the session in order, it is possible to store * conversational state as instance variables in this object. *

* * WARNING: This class is badly named as the actual {@link IoHandler} implementor * is in fact the {@link SingleSessionIoHandlerDelegate}. * * @author Apache MINA Project */ @Deprecated public interface SingleSessionIoHandler { /** * Invoked when the session is created. Initialize default socket parameters * and user-defined attributes here. * * @throws Exception * @see IoHandler#sessionCreated(IoSession) */ void sessionCreated() throws Exception; /** * Invoked when the connection is opened. This method is not invoked if the * transport type is UDP. * * @see IoHandler#sessionOpened(IoSession) */ void sessionOpened() throws Exception; /** * Invoked when the connection is closed. This method is not invoked if the * transport type is UDP. * * @see IoHandler#sessionClosed(IoSession) */ void sessionClosed() throws Exception; /** * Invoked when the connection is idle. Refer to {@link IdleStatus}. This * method is not invoked if the transport type is UDP. * * @param status the type of idleness * @see IoHandler#sessionIdle(IoSession, IdleStatus) */ void sessionIdle(IdleStatus status) throws Exception; /** * Invoked when any exception is thrown by user {@link IoHandler} * implementation or by MINA. If cause is instanceof * {@link IOException}, MINA will close the connection automatically. * * @param cause the caught exception * @see IoHandler#exceptionCaught(IoSession, Throwable) */ void exceptionCaught(Throwable cause) throws Exception; /** * Invoked when protocol message is received. Implement your protocol flow * here. * * @param message the received message * @see IoHandler#messageReceived(IoSession, Object) */ void messageReceived(Object message) throws Exception; /** * Invoked when protocol message that user requested by * {@link IoSession#write(Object)} is sent out actually. * * @param message the sent message * @see IoHandler#messageSent(IoSession, Object) */ void messageSent(Object message) throws Exception; } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/multiton/SingleSessionIoHandlerFactory.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/multiton/SingleSessionIoHandler0000644000175000017500000000262512032276033032637 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.handler.multiton; import org.apache.mina.core.session.IoSession; /** * A factory that creates {@link SingleSessionIoHandler} to be used with one * particular session. * * @see SingleSessionIoHandler * * @author Apache MINA Project */ @Deprecated public interface SingleSessionIoHandlerFactory { /** * Returns a {@link SingleSessionIoHandler} for the given session. * * @param session the session for which a handler is requested */ SingleSessionIoHandler getHandler(IoSession session) throws Exception; } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/multiton/SingleSessionIoHandlerDelegate.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/multiton/SingleSessionIoHandler0000644000175000017500000001317212032276033032636 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.handler.multiton; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; /** * An {@link IoHandler} implementation which delegates all requests to * {@link SingleSessionIoHandler}s. A {@link SingleSessionIoHandlerFactory} * is used to create a new {@link SingleSessionIoHandler} for each newly * created session. * * WARNING : This {@link IoHandler} implementation may be easier to understand and * thus to use but the user should be aware that creating one handler by session * will lower scalability if building an high performance server. This should only * be used with very specific needs in mind. * * @author Apache MINA Project */ @Deprecated public class SingleSessionIoHandlerDelegate implements IoHandler { /** * The key used to store the {@link SingleSessionIoHandler} as a session * attribute. */ public static final AttributeKey HANDLER = new AttributeKey(SingleSessionIoHandlerDelegate.class, "handler"); /** * The {@link SingleSessionIoHandlerFactory} used to create new * {@link SingleSessionIoHandler}s. */ private final SingleSessionIoHandlerFactory factory; /** * Creates a new instance that uses the passed in * {@link SingleSessionIoHandlerFactory} to create new * {@link SingleSessionIoHandler}s. * * @param factory the factory for {@link SingleSessionIoHandler}s */ public SingleSessionIoHandlerDelegate(SingleSessionIoHandlerFactory factory) { if (factory == null) { throw new IllegalArgumentException("factory"); } this.factory = factory; } /** * Returns the {@link SingleSessionIoHandlerFactory} that is used to create a new * {@link SingleSessionIoHandler} instance. */ public SingleSessionIoHandlerFactory getFactory() { return factory; } /** * Creates a new instance with the factory passed to the constructor of * this class. The created handler is stored as a session * attribute named {@link #HANDLER}. * * @see org.apache.mina.core.service.IoHandler#sessionCreated(org.apache.mina.core.session.IoSession) */ public void sessionCreated(IoSession session) throws Exception { SingleSessionIoHandler handler = factory.getHandler(session); session.setAttribute(HANDLER, handler); handler.sessionCreated(); } /** * Delegates the method call to the * {@link SingleSessionIoHandler#sessionOpened()} method of the handler * assigned to this session. */ public void sessionOpened(IoSession session) throws Exception { SingleSessionIoHandler handler = (SingleSessionIoHandler) session.getAttribute(HANDLER); handler.sessionOpened(); } /** * Delegates the method call to the * {@link SingleSessionIoHandler#sessionClosed()} method of the handler * assigned to this session. */ public void sessionClosed(IoSession session) throws Exception { SingleSessionIoHandler handler = (SingleSessionIoHandler) session.getAttribute(HANDLER); handler.sessionClosed(); } /** * Delegates the method call to the * {@link SingleSessionIoHandler#sessionIdle(IdleStatus)} method of the * handler assigned to this session. */ public void sessionIdle(IoSession session, IdleStatus status) throws Exception { SingleSessionIoHandler handler = (SingleSessionIoHandler) session.getAttribute(HANDLER); handler.sessionIdle(status); } /** * Delegates the method call to the * {@link SingleSessionIoHandler#exceptionCaught(Throwable)} method of the * handler assigned to this session. */ public void exceptionCaught(IoSession session, Throwable cause) throws Exception { SingleSessionIoHandler handler = (SingleSessionIoHandler) session.getAttribute(HANDLER); handler.exceptionCaught(cause); } /** * Delegates the method call to the * {@link SingleSessionIoHandler#messageReceived(Object)} method of the * handler assigned to this session. */ public void messageReceived(IoSession session, Object message) throws Exception { SingleSessionIoHandler handler = (SingleSessionIoHandler) session.getAttribute(HANDLER); handler.messageReceived(message); } /** * Delegates the method call to the * {@link SingleSessionIoHandler#messageSent(Object)} method of the handler * assigned to this session. */ public void messageSent(IoSession session, Object message) throws Exception { SingleSessionIoHandler handler = (SingleSessionIoHandler) session.getAttribute(HANDLER); handler.messageSent(message); } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/multiton/SingleSessionIoHandlerAdapter.javamina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/multiton/SingleSessionIoHandler0000644000175000017500000000504712032276033032640 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.handler.multiton; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; /** * Adapter class for implementors of the {@link SingleSessionIoHandler} * interface. The session to which the handler is assigned is accessible * through the {@link #getSession()} method. * * @author Apache MINA Project */ @Deprecated public class SingleSessionIoHandlerAdapter implements SingleSessionIoHandler { /** * The session to which the handler is assigned. */ private final IoSession session; /** * Creates a new instance that is assigned to the passed in session. * * @param session the session to which the handler is assigned */ public SingleSessionIoHandlerAdapter(IoSession session) { if (session == null) { throw new IllegalArgumentException("session"); } this.session = session; } /** * Retrieves the session to which this handler is assigned. * * @return the session */ protected IoSession getSession() { return session; } public void exceptionCaught(Throwable th) throws Exception { // Do nothing } public void messageReceived(Object message) throws Exception { // Do nothing } public void messageSent(Object message) throws Exception { // Do nothing } public void sessionClosed() throws Exception { // Do nothing } public void sessionCreated() throws Exception { // Do nothing } public void sessionIdle(IdleStatus status) throws Exception { // Do nothing } public void sessionOpened() throws Exception { // Do nothing } } mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/multiton/package.html0000644000175000017500000000203212032276033030612 0ustar ebourgebourg Enables creating a handler per session instead of having one handler for many sessions, using Multiton pattern. mina2-2.0.7.orig/src/mina-core/src/main/java/org/apache/mina/handler/package.html0000644000175000017500000000163112032276033026743 0ustar ebourgebourg Useful IoHandler implementations. mina2-2.0.7.orig/src/mina-core/src/main/resources/0000755000175000017500000000000012032276034021202 5ustar ebourgebourgmina2-2.0.7.orig/src/resources/0000755000175000017500000000000012162575507015630 5ustar ebourgebourgmina2-2.0.7.orig/src/resources/ImprovedJavaConventions.xml0000644000175000017500000006455612032276034023174 0ustar ebourgebourg mina2-2.0.7.orig/src/mina-example/0000755000175000017500000000000012162575507016173 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/pom.xml.releaseBackup0000644000175000017500000000467512033674301022256 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7-SNAPSHOT mina-example Apache MINA Examples jar ${project.groupId} mina-core ${project.version} bundle ${project.groupId} mina-integration-beans ${project.version} bundle ${project.groupId} mina-integration-jmx ${project.version} bundle ${project.groupId} mina-statemachine ${project.version} bundle org.springframework spring jmock jmock test org.slf4j jcl-over-slf4j mina2-2.0.7.orig/src/mina-example/pom.xml0000644000175000017500000000466412033674306017514 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7 mina-example Apache MINA Examples jar ${project.groupId} mina-core ${project.version} bundle ${project.groupId} mina-integration-beans ${project.version} bundle ${project.groupId} mina-integration-jmx ${project.version} bundle ${project.groupId} mina-statemachine ${project.version} bundle org.springframework spring jmock jmock test org.slf4j jcl-over-slf4j mina2-2.0.7.orig/src/mina-example/src/0000755000175000017500000000000012032276035016750 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/test/0000755000175000017500000000000012032276035017727 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/test/java/0000755000175000017500000000000012032276034020647 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/test/java/org/0000755000175000017500000000000012032276034021436 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/0000755000175000017500000000000012032276034022657 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/0000755000175000017500000000000012032276034023603 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/0000755000175000017500000000000012032276035025237 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/proxy/0000755000175000017500000000000012162575507026432 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/proxy/telnet/0000755000175000017500000000000012162575507027725 5ustar ebourgebourg././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/proxy/telnet/TelnetSessionHandler.javamina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/proxy/telnet/TelnetSessionHa0000644000175000017500000000621112032276035032706 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.proxy.telnet; import java.io.BufferedReader; import java.io.InputStreamReader; import org.apache.mina.core.session.IoSession; import org.apache.mina.proxy.AbstractProxyIoHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * TelnetSessionHandler.java - Telnet session handler. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class TelnetSessionHandler extends AbstractProxyIoHandler { private final static Logger logger = LoggerFactory .getLogger(TelnetSessionHandler.class); /** * Default constructor. */ public TelnetSessionHandler() { } /** * {@inheritDoc} */ @Override public void sessionCreated(IoSession session) throws Exception { logger.debug("CLIENT - Session created: " + session); } /** * {@inheritDoc} */ @Override public void proxySessionOpened(IoSession session) throws Exception { logger.debug("CLIENT - Session opened: " + session); final IoSession _session = session; // Enter typing loop new Thread(new Runnable() { public void run() { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); while (!_session.isClosing()) { try { String line = br.readLine(); if (line != null) { _session.write(line); } } catch (Exception e) { break; } } _session.close(true); } }).start(); } /** * {@inheritDoc} */ @Override public void messageReceived(IoSession session, Object message) { //System.out.println((String) message); } /** * {@inheritDoc} */ @Override public void sessionClosed(IoSession session) throws Exception { logger.debug("CLIENT - Session closed"); } /** * {@inheritDoc} */ @Override public void exceptionCaught(IoSession session, Throwable cause) { logger.debug("CLIENT - Exception caught"); //cause.printStackTrace(); session.close(true); } }././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/proxy/telnet/ProxyTelnetTestClient.javamina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/proxy/telnet/ProxyTelnetTest0000644000175000017500000001142112032276035032772 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.proxy.telnet; import java.net.InetSocketAddress; import java.nio.charset.Charset; import java.util.HashMap; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.LineDelimiter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.proxy.ProxyConnector; import org.apache.mina.proxy.handlers.http.HttpProxyConstants; import org.apache.mina.proxy.handlers.http.HttpProxyRequest; import org.apache.mina.proxy.session.ProxyIoSession; import org.apache.mina.transport.socket.nio.NioSocketConnector; /** * ProxyTelnetTestClient.java - Tests a classical text communication through a proxy. * Changing the params and request type will allow to test the multiple options * (http or socks proxying, various authentications methods, ...). * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class ProxyTelnetTestClient { /** * The user login used to authenticate with the proxy. */ public final static String USER = "TED_KODS"; /** * The password used to authenticate with the proxy. */ public final static String PWD = "EDOUARD"; /** * The address we really want to connect to. */ public final static InetSocketAddress serverAddress = new InetSocketAddress( "localhost", 25); /** * The address of the proxy server. */ public final static InetSocketAddress proxyAddress = new InetSocketAddress( "localhost", 8080); /** * Connects to the endpoint running a text based protocol server through the * proxy and allows user to type commands in the console to dialog with the * server. * * @throws Exception */ public ProxyTelnetTestClient() throws Exception { // Create proxy connector. NioSocketConnector targetConnector = new NioSocketConnector(Runtime .getRuntime().availableProcessors() + 1); ProxyConnector connector = new ProxyConnector(targetConnector); /* // Example of socks v5 proxy use SocksProxyRequest req = new SocksProxyRequest( SocksProxyConstants.SOCKS_VERSION_5, SocksProxyConstants.ESTABLISH_TCPIP_STREAM, serverAddress, USER); req.setPassword(PWD); */ HttpProxyRequest req = new HttpProxyRequest(serverAddress); HashMap props = new HashMap(); props.put(HttpProxyConstants.USER_PROPERTY, USER); props.put(HttpProxyConstants.PWD_PROPERTY, PWD); req.setProperties(props); ProxyIoSession proxyIoSession = new ProxyIoSession(proxyAddress, req); connector.setProxyIoSession(proxyIoSession); LineDelimiter delim = new LineDelimiter("\r\n"); targetConnector.getFilterChain().addLast( "codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset .forName("UTF-8"), delim, delim))); connector.setHandler(new TelnetSessionHandler()); IoSession session; for (;;) { try { ConnectFuture future = connector.connect(); future.awaitUninterruptibly(); session = future.getSession(); break; } catch (RuntimeIoException e) { System.err.println("Failed to connect. Retrying in 5 secs ..."); Thread.sleep(5000); } } // Wait until done if (session != null) { session.getCloseFuture().awaitUninterruptibly(); } connector.dispose(); System.exit(0); } /** * {@inheritDoc} */ public static void main(String[] args) throws Exception { new ProxyTelnetTestClient(); } }././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/proxy/ClientSessionHandler.javamina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/proxy/ClientSessionHandler.j0000644000175000017500000001246312032276035032661 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.proxy; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.proxy.AbstractProxyIoHandler; import org.apache.mina.proxy.handlers.ProxyRequest; import org.apache.mina.proxy.handlers.http.HttpProxyConstants; import org.apache.mina.proxy.handlers.http.HttpProxyRequest; import org.apache.mina.proxy.handlers.socks.SocksProxyRequest; import org.apache.mina.proxy.session.ProxyIoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * ClientSessionHandler.java - Client session handler for the mina proxy test class. * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class ClientSessionHandler extends AbstractProxyIoHandler { private final static Logger logger = LoggerFactory .getLogger(ClientSessionHandler.class); /** * The temporary file were the request result will be written. */ private File file; /** * NIO channel of the temporary file. */ private FileChannel wChannel; /** * The command to issue to the proxy. */ private String cmd; public ClientSessionHandler(String cmd) { this.cmd = cmd; } /** * {@inheritDoc} */ @Override public void sessionCreated(IoSession session) throws Exception { logger.debug("CLIENT - Session created: " + session); } /** * Sends the request to the proxy server when session is opened with * the proxy. */ @Override public void proxySessionOpened(IoSession session) throws Exception { logger.debug("CLIENT - Session opened: " + session); ProxyIoSession proxyIoSession = (ProxyIoSession) session .getAttribute(ProxyIoSession.PROXY_SESSION); if (proxyIoSession != null) { ProxyRequest req = proxyIoSession.getRequest(); byte[] c = null; if (req instanceof SocksProxyRequest && cmd != null) { logger.debug("Sending request to a SOCKS SESSION ..."); c = cmd.getBytes(proxyIoSession.getCharsetName()); } else if (req instanceof HttpProxyRequest && ((HttpProxyRequest) req).getHttpVerb() == HttpProxyConstants.CONNECT) { logger.debug("Sending request to a HTTP CONNECTED SESSION ..."); c = (((HttpProxyRequest) req).toHttpString()) .getBytes(proxyIoSession.getCharsetName()); } if (c != null) { IoBuffer buf = IoBuffer.allocate(c.length); buf.put(c); buf.flip(); session.write(buf); } } } /** * Writes the request result to a temporary file. */ @Override public void messageReceived(IoSession session, Object message) { logger.debug("CLIENT - Message received: " + session); IoBuffer buf = (IoBuffer) message; try { if (file == null) { file = File.createTempFile("http", ".html"); logger.info("Writing request result to " + file.getAbsolutePath()); wChannel = new FileOutputStream(file, false).getChannel(); } // Write the ByteBuffer contents; the bytes between the ByteBuffer's // position and the limit is written to the file wChannel.write(buf.buf()); } catch (IOException e) { //e.printStackTrace(); } } /** * Closes the temporary file if it was opened. */ @Override public void sessionClosed(IoSession session) throws Exception { logger.debug("CLIENT - Session closed - closing result file if open."); // Close the file if (wChannel != null) { wChannel.close(); } } /** * {@inheritDoc} */ @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { if (session.isClosing()) { return; } logger.debug("CLIENT - Session idle"); } /** * {@inheritDoc} */ @Override public void exceptionCaught(IoSession session, Throwable cause) { logger.debug("CLIENT - Exception caught"); //cause.printStackTrace(); session.close(true); } }././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/proxy/Socks5GSSAPITestServer.javamina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/proxy/Socks5GSSAPITestServer0000644000175000017500000002012412032276035032447 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.proxy; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import org.apache.mina.proxy.handlers.socks.SocksProxyConstants; import org.apache.mina.proxy.utils.ByteUtilities; import org.ietf.jgss.GSSContext; import org.ietf.jgss.GSSCredential; import org.ietf.jgss.GSSException; import org.ietf.jgss.GSSManager; import org.ietf.jgss.Oid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Socks5GSSAPITestServer.java - Basic test server for SOCKS5 GSSAPI authentication. * * NOTE: Launch this program with the following params in a pre-configured Kerberos V env. * Do not forget to replace < ... > vars with your own values. * * -Djava.security.krb5.realm= * -Djavax.security.auth.useSubjectCredsOnly=false * -Djava.security.krb5.kdc= * -Djava.security.auth.login.config=${workspace_loc}\Mina2Proxy\src\bcsLogin.conf * -Dsun.security.krb5.debug=true * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class Socks5GSSAPITestServer { private final static Logger logger = LoggerFactory .getLogger(Socks5GSSAPITestServer.class); /** * NOTE : change this to comply with your Kerberos environment. */ protected final static String SERVICE_NAME = "host/myworkstation.local.network"; /** * Selected mechanism message: advertises client to use SocksV5 protocol with * GSSAPI authentication. */ public final static byte[] SELECT_GSSAPI_AUTH_MSG = new byte[] { SocksProxyConstants.SOCKS_VERSION_5, SocksProxyConstants.GSSAPI_AUTH }; /** * Simulates a Socks v5 server using only Kerberos V authentication. * * @param localPort the local port used to bind the server * @throws IOException * @throws GSSException */ private static void doHandShake(int localPort) throws IOException, GSSException { ServerSocket ss = new ServerSocket(localPort); GSSManager manager = GSSManager.getInstance(); /* * Create a GSSContext to receive the incoming request from the client. * Use null for the server credentials passed in to tell the underlying * mechanism to use whatever credentials it has available that can be * used to accept this connection. */ GSSCredential serverCreds = manager.createCredential(manager .createName(SERVICE_NAME, null), GSSCredential.DEFAULT_LIFETIME, new Oid( SocksProxyConstants.KERBEROS_V5_OID), GSSCredential.ACCEPT_ONLY); while (true) { logger.debug("Waiting for incoming connection on port {} ...", localPort); GSSContext context = manager.createContext(serverCreds); Socket socket = ss.accept(); try { DataInputStream inStream = new DataInputStream(socket .getInputStream()); DataOutputStream outStream = new DataOutputStream(socket .getOutputStream()); logger.debug("Got connection from client @ {}", socket .getInetAddress()); // Read SOCKS5 greeting packet byte ver = (byte) inStream.read(); if (ver != 0x05) { throw new IllegalStateException( "Wrong socks version received - " + ver); } byte nbAuthMethods = (byte) inStream.read(); byte[] methods = new byte[nbAuthMethods]; inStream.readFully(methods); boolean found = false; for (byte b : methods) { if (b == SocksProxyConstants.GSSAPI_AUTH) { found = true; break; } } if (!found) { throw new IllegalStateException( "Client does not support GSSAPI authentication"); } // Send selected mechanism message outStream.write(SELECT_GSSAPI_AUTH_MSG); outStream.flush(); // Do the context establishment loop byte[] token = null; while (!context.isEstablished()) { byte authVersion = (byte) inStream.read(); if (authVersion != 0x01) { throw new IllegalStateException( "Wrong socks GSSAPI auth version received: " + authVersion); } byte mtyp = (byte) inStream.read(); if (mtyp != 0x01) { throw new IllegalArgumentException( "Message type should be equal to 1."); } int len = inStream.readShort(); token = new byte[len]; inStream.readFully(token); logger.debug(" Received Token[{}] = {}", len, ByteUtilities.asHex(token)); token = context.acceptSecContext(token, 0, token.length); // Send a token to the peer if one was generated by acceptSecContext if (token != null) { logger.debug(" Sending Token[{}] = {}", token.length, ByteUtilities.asHex(token)); outStream.writeByte(authVersion); outStream.writeByte(mtyp); outStream.writeShort(token.length); outStream.write(token); outStream.flush(); } } logger.debug("Context Established !"); logger.debug("Client is {}", context.getSrcName()); logger.debug("Server is {}", context.getTargName()); /* * If mutual authentication did not take place, then * only the client was authenticated to the * server. Otherwise, both client and server were * authenticated to each other. */ if (context.getMutualAuthState()) { logger.debug("Mutual authentication took place !"); } // We can now abort the process after a short time as auth is OK // and finally block will close session Thread.sleep(500); } catch (Exception ex) { //ex.printStackTrace(); } finally { context.dispose(); socket.close(); } } } /** * {@inheritDoc} */ public static void main(String[] args) throws Exception { // Obtain the command-line arguments and parse the port number if (args.length != 1) { System.err .println("Usage: java Socks5GSSAPITestServer "); System.exit(-1); } doHandShake(Integer.parseInt(args[0])); System.exit(0); } }mina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/proxy/ProxyTestClient.java0000644000175000017500000002060312032276035032404 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.proxy; import java.net.InetSocketAddress; import java.net.URL; import java.security.Security; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.proxy.ProxyConnector; import org.apache.mina.proxy.handlers.ProxyRequest; import org.apache.mina.proxy.handlers.http.HttpAuthenticationMethods; import org.apache.mina.proxy.handlers.http.HttpProxyConstants; import org.apache.mina.proxy.handlers.http.HttpProxyRequest; import org.apache.mina.proxy.handlers.socks.SocksProxyConstants; import org.apache.mina.proxy.handlers.socks.SocksProxyRequest; import org.apache.mina.proxy.session.ProxyIoSession; import org.apache.mina.proxy.utils.MD4Provider; import org.apache.mina.transport.socket.nio.NioSocketConnector; /** * ProxyTestClient.java - Base test class for mina proxy * * @author Apache MINA Project * @since MINA 2.0.0-M3 */ public class ProxyTestClient { /** * The global variables used when creating the HTTP proxy connection. */ /** * The user login. */ public final static String USER = "TED_KODS"; /** * The user password. */ public final static String PWD = "EDOUARD"; /** * The domain name. (used in NTLM connections) */ public final static String DOMAIN = "MYDOMAIN"; /** * The workstation name. (used in NTLM connections) */ public final static String WORKSTATION = "MYWORKSTATION"; /** * Set this variable to true in order to generate HTTP/1.1 requests. */ private final static boolean USE_HTTP_1_1 = false; /** * NTLM proxy authentication needs a JCE provider that handles MD4 hashing. */ static { if (Security.getProvider("MINA") == null) { Security.addProvider(new MD4Provider()); } } /** * Creates a connection to the endpoint through a proxy server using the specified * authentication method. * * Command line arguments: * ProxyTestClient * * Note that is OPTIONNAL a HTTP proxy connection will be used if not * specified. * * Examples: * ProxyTestClient myproxy 8080 http://mina.apache.org SOCKS4 * ProxyTestClient squidsrv 3128 http://mina.apache.org:80 * * @param args parse arguments to get proxy hostaname, proxy port, the url to connect to * and optionnaly the proxy authentication method * @throws Exception */ public ProxyTestClient(String[] args) throws Exception { if (args.length < 3) { System.out .println(ProxyTestClient.class.getName() + " ( is OPTIONNAL)"); return; } // Create proxy connector. NioSocketConnector socketConnector = new NioSocketConnector(Runtime .getRuntime().availableProcessors() + 1); ProxyConnector connector = new ProxyConnector(socketConnector); // Set connect timeout. connector.setConnectTimeoutMillis(5000); URL url = new URL(args[2]); int port = url.getPort() == -1 ? url.getDefaultPort() : url.getPort(); ProxyRequest req = null; if (args.length == 4) { if ("SOCKS4".equals(args[3])) { req = new SocksProxyRequest( SocksProxyConstants.SOCKS_VERSION_4, SocksProxyConstants.ESTABLISH_TCPIP_STREAM, new InetSocketAddress(url.getHost(), port), USER); } else if ("SOCKS4a".equals(args[3])) { req = new SocksProxyRequest( SocksProxyConstants.ESTABLISH_TCPIP_STREAM, url .getHost(), port, USER); } else if ("SOCKS5".equals(args[3])) { req = new SocksProxyRequest( SocksProxyConstants.SOCKS_VERSION_5, SocksProxyConstants.ESTABLISH_TCPIP_STREAM, new InetSocketAddress(url.getHost(), port), USER); ((SocksProxyRequest) req).setPassword(PWD); ((SocksProxyRequest) req) .setServiceKerberosName(Socks5GSSAPITestServer.SERVICE_NAME); } else { req = createHttpProxyRequest(args[2]); } } else { req = createHttpProxyRequest(args[2]); } ProxyIoSession proxyIoSession = new ProxyIoSession( new InetSocketAddress(args[0], Integer.parseInt(args[1])), req); // Tests modifying authentication order preferences. First algorithm in list available on server // will be used for authentication. List l = new ArrayList(); l.add(HttpAuthenticationMethods.DIGEST); l.add(HttpAuthenticationMethods.BASIC); proxyIoSession.setPreferedOrder(l); connector.setProxyIoSession(proxyIoSession); socketConnector.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 5); connector.getFilterChain().addLast("logger", new LoggingFilter()); // This command is sent when using a socks proxy to request a page from the web server. String cmd = "GET " + url.toExternalForm() + " HTTP/1.0" + HttpProxyConstants.CRLF + HttpProxyConstants.CRLF; connector.setHandler(new ClientSessionHandler(cmd)); IoSession session; for (;;) { try { ConnectFuture future = connector.connect(); future.awaitUninterruptibly(); session = future.getSession(); break; } catch (RuntimeIoException e) { System.err.println("Failed to connect. Retrying in 5 secs ..."); Thread.sleep(5000); } } // Wait until done if (session != null) { session.getCloseFuture().awaitUninterruptibly(); } connector.dispose(); System.exit(0); } /** * Creates a {@link HttpProxyRequest} from the provided uri parameter. * It uses the global variables defined at the top of the class to fill the * connection properties of the request. If the global variable useHttp1_1 * is set to true, it will create a HTTP/1.1 request. * * @param uri the requested uri to connect to through the HTTP proxy * @return the fully initialized {@link HttpProxyRequest} object */ private HttpProxyRequest createHttpProxyRequest(String uri) { HttpProxyRequest req = new HttpProxyRequest(uri); HashMap props = new HashMap(); props.put(HttpProxyConstants.USER_PROPERTY, USER); props.put(HttpProxyConstants.PWD_PROPERTY, PWD); props.put(HttpProxyConstants.DOMAIN_PROPERTY, DOMAIN); props.put(HttpProxyConstants.WORKSTATION_PROPERTY, WORKSTATION); req.setProperties(props); if (USE_HTTP_1_1) { req.setHttpVersion(HttpProxyConstants.HTTP_1_1); } return req; } /** * {@inheritDoc} */ public static void main(String[] args) throws Exception { new ProxyTestClient(args); } }mina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/echoserver/0000755000175000017500000000000012162575507027416 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/echoserver/ssl/0000755000175000017500000000000012162575507030217 5ustar ebourgebourg././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/echoserver/ssl/SslFilterTest.javamina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/echoserver/ssl/SslFilterTest0000644000175000017500000001451712032276035032707 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.echoserver.ssl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.net.InetSocketAddress; import java.net.Socket; import java.nio.charset.Charset; import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.List; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.filter.ssl.SslFilter; import org.apache.mina.transport.socket.SocketAcceptor; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * TODO Add documentation * * @author Apache MINA Project */ public class SslFilterTest { private int port; private SocketAcceptor acceptor; @Before public void setUp() throws Exception { acceptor = new NioSocketAcceptor(); } @After public void tearDown() throws Exception { acceptor.setCloseOnDeactivation(true); acceptor.dispose(); } @Test public void testMessageSentIsCalled() throws Exception { testMessageSentIsCalled(false); } @Test public void testMessageSentIsCalled_With_SSL() throws Exception { testMessageSentIsCalled(true); } private void testMessageSentIsCalled(boolean useSSL) throws Exception { // Workaround to fix TLS issue : http://java.sun.com/javase/javaseforbusiness/docs/TLSReadme.html java.lang.System.setProperty( "sun.security.ssl.allowUnsafeRenegotiation", "true" ); SslFilter sslFilter = null; if (useSSL) { sslFilter = new SslFilter(BogusSslContextFactory.getInstance(true)); acceptor.getFilterChain().addLast("sslFilter", sslFilter); } acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset .forName("UTF-8")))); EchoHandler handler = new EchoHandler(); acceptor.setHandler(handler); acceptor.bind(new InetSocketAddress(0)); port = acceptor.getLocalAddress().getPort(); //System.out.println("MINA server started."); Socket socket = getClientSocket(useSSL); int bytesSent = 0; bytesSent += writeMessage(socket, "test-1\n"); if (useSSL) { // Test renegotiation SSLSocket ss = (SSLSocket) socket; //ss.getSession().invalidate(); ss.startHandshake(); } bytesSent += writeMessage(socket, "test-2\n"); int[] response = new int[bytesSent]; for (int i = 0; i < response.length; i++) { response[i] = socket.getInputStream().read(); } if (useSSL) { // Read SSL close notify. while (socket.getInputStream().read() >= 0) { continue; } } socket.close(); while (acceptor.getManagedSessions().size() != 0) { Thread.sleep(100); } //System.out.println("handler: " + handler.sentMessages); assertEquals("handler should have sent 2 messages:", 2, handler.sentMessages.size()); assertTrue(handler.sentMessages.contains("test-1")); assertTrue(handler.sentMessages.contains("test-2")); } private int writeMessage(Socket socket, String message) throws Exception { byte request[] = message.getBytes("UTF-8"); socket.getOutputStream().write(request); return request.length; } private Socket getClientSocket(boolean ssl) throws Exception { if (ssl) { SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(null, trustManagers, null); return ctx.getSocketFactory().createSocket("localhost", port); } return new Socket("localhost", port); } private static class EchoHandler extends IoHandlerAdapter { List sentMessages = new ArrayList(); @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { //cause.printStackTrace(); } @Override public void messageReceived(IoSession session, Object message) throws Exception { session.write(message); } @Override public void messageSent(IoSession session, Object message) throws Exception { sentMessages.add(message.toString()); if (sentMessages.size() >= 2) { session.close(true); } } } TrustManager[] trustManagers = new TrustManager[] { new TrustAnyone() }; private static class TrustAnyone implements X509TrustManager { public void checkClientTrusted( java.security.cert.X509Certificate[] x509Certificates, String s) throws CertificateException { } public void checkServerTrusted( java.security.cert.X509Certificate[] x509Certificates, String s) throws CertificateException { } public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[0]; } } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/echoserver/ConnectorTest.javamina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/echoserver/ConnectorTest.jav0000644000175000017500000002154212032276035032704 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.echoserver; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.net.InetSocketAddress; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteException; import org.apache.mina.example.echoserver.ssl.BogusSslContextFactory; import org.apache.mina.filter.ssl.SslFilter; import org.apache.mina.transport.socket.nio.NioDatagramConnector; import org.apache.mina.transport.socket.nio.NioSocketConnector; import org.apache.mina.util.AvailablePortFinder; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Tests echo server example. * * @author Apache MINA Project */ public class ConnectorTest extends AbstractTest { private final static Logger LOGGER = LoggerFactory.getLogger(ConnectorTest.class); private static final int TIMEOUT = 10000; // 10 seconds private final int COUNT = 10; private final int DATA_SIZE = 16; private EchoConnectorHandler handler; private SslFilter connectorSSLFilter; public ConnectorTest() { // Do nothing } @Before public void setUp() throws Exception { super.setUp(); handler = new EchoConnectorHandler(); connectorSSLFilter = new SslFilter(BogusSslContextFactory .getInstance(false)); connectorSSLFilter.setUseClientMode(true); // set client mode } @Test public void testTCP() throws Exception { IoConnector connector = new NioSocketConnector(); testConnector(connector); } @Test public void testTCPWithSSL() throws Exception { useSSL = true; // Create a connector IoConnector connector = new NioSocketConnector(); // Add an SSL filter to connector connector.getFilterChain().addLast("SSL", connectorSSLFilter); testConnector(connector); } @Test public void testUDP() throws Exception { IoConnector connector = new NioDatagramConnector(); testConnector(connector); } private void testConnector(IoConnector connector) throws Exception { connector.setHandler(handler); //System.out.println("* Without localAddress"); testConnector(connector, false); //System.out.println("* With localAddress"); testConnector(connector, true); } private void testConnector(IoConnector connector, boolean useLocalAddress) throws Exception { IoSession session = null; if (!useLocalAddress) { ConnectFuture future = connector.connect(new InetSocketAddress( "127.0.0.1", port)); future.awaitUninterruptibly(); session = future.getSession(); } else { int clientPort = port; for (int i = 0; i < 65536; i++) { clientPort = AvailablePortFinder .getNextAvailable(clientPort + 1); try { ConnectFuture future = connector.connect( new InetSocketAddress("127.0.0.1", port), new InetSocketAddress(clientPort)); future.awaitUninterruptibly(); session = future.getSession(); break; } catch (RuntimeIoException e) { // Try again until we succeed to bind. } } if (session == null) { fail("Failed to find out an appropriate local address."); } } // Run a basic connector test. testConnector0(session); // Send closeNotify to test TLS closure if it is TLS connection. if (useSSL) { connectorSSLFilter.stopSsl(session).awaitUninterruptibly(); System.out .println("-------------------------------------------------------------------------------"); // Test again after we finished TLS session. testConnector0(session); System.out .println("-------------------------------------------------------------------------------"); // Test if we can enter TLS mode again. //// Send StartTLS request. handler.readBuf.clear(); IoBuffer buf = IoBuffer.allocate(1); buf.put((byte) '.'); buf.flip(); session.write(buf).awaitUninterruptibly(); //// Wait for StartTLS response. waitForResponse(handler, 1); handler.readBuf.flip(); assertEquals(1, handler.readBuf.remaining()); assertEquals((byte) '.', handler.readBuf.get()); // Now start TLS connection assertTrue(connectorSSLFilter.startSsl(session)); testConnector0(session); } session.close(true).awaitUninterruptibly(); } private void testConnector0(IoSession session) throws InterruptedException { EchoConnectorHandler handler = (EchoConnectorHandler) session .getHandler(); IoBuffer readBuf = handler.readBuf; readBuf.clear(); WriteFuture writeFuture = null; for (int i = 0; i < COUNT; i++) { IoBuffer buf = IoBuffer.allocate(DATA_SIZE); buf.limit(DATA_SIZE); fillWriteBuffer(buf, i); buf.flip(); writeFuture = session.write(buf); if (session.getService().getTransportMetadata().isConnectionless()) { // This will align message arrival order in connectionless transport types waitForResponse(handler, (i + 1) * DATA_SIZE); } } writeFuture.awaitUninterruptibly(); waitForResponse(handler, DATA_SIZE * COUNT); // Assert data //// Please note that BufferOverflowException can be thrown //// in SocketIoProcessor if there was a read timeout because //// we share readBuf. readBuf.flip(); LOGGER.info("readBuf: " + readBuf); assertEquals(DATA_SIZE * COUNT, readBuf.remaining()); IoBuffer expectedBuf = IoBuffer.allocate(DATA_SIZE * COUNT); for (int i = 0; i < COUNT; i++) { expectedBuf.limit((i + 1) * DATA_SIZE); fillWriteBuffer(expectedBuf, i); } expectedBuf.position(0); isEquals(expectedBuf, readBuf); } private void waitForResponse(EchoConnectorHandler handler, int bytes) throws InterruptedException { for (int j = 0; j < TIMEOUT / 10; j++) { if (handler.readBuf.position() >= bytes) { break; } Thread.sleep(10); } assertEquals(bytes, handler.readBuf.position()); } private void fillWriteBuffer(IoBuffer writeBuf, int i) { while (writeBuf.remaining() > 0) { writeBuf.put((byte) i++); } } private static class EchoConnectorHandler extends IoHandlerAdapter { private final IoBuffer readBuf = IoBuffer.allocate(1024); private EchoConnectorHandler() { readBuf.setAutoExpand(true); } @Override public void messageReceived(IoSession session, Object message) { readBuf.put((IoBuffer) message); } @Override public void messageSent(IoSession session, Object message) { } @Override public void exceptionCaught(IoSession session, Throwable cause) { LOGGER.warn("Unexpected exception.", cause); if (cause instanceof WriteException) { WriteException e = (WriteException) cause; LOGGER.warn("Failed write requests: {}", e.getRequests()); } } } } mina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/echoserver/AcceptorTest.java0000644000175000017500000001020412032276035032644 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.echoserver; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketTimeoutException; import java.util.Arrays; import org.apache.mina.example.echoserver.ssl.SslServerSocketFactory; import org.apache.mina.example.echoserver.ssl.SslSocketFactory; import org.junit.Test; /** * Tests echo server example. * * @author Apache MINA Project */ public class AcceptorTest extends AbstractTest { public AcceptorTest() { } @Test public void testTCP() throws Exception { testTCP0(new Socket("127.0.0.1", port)); } @Test public void testTCPWithSSL() throws Exception { // Add an SSL filter useSSL = true; // Create a echo client with SSL factory and test it. SslSocketFactory.setSslEnabled(true); SslServerSocketFactory.setSslEnabled(true); testTCP0(SslSocketFactory.getSocketFactory().createSocket( "localhost", port)); } private void testTCP0(Socket client) throws Exception { client.setSoTimeout(3000); byte[] writeBuf = new byte[16]; for (int i = 0; i < 10; i++) { fillWriteBuffer(writeBuf, i); client.getOutputStream().write(writeBuf); } byte[] readBuf = new byte[writeBuf.length]; for (int i = 0; i < 10; i++) { fillWriteBuffer(writeBuf, i); int readBytes = 0; while (readBytes < readBuf.length) { int nBytes = client.getInputStream().read(readBuf, readBytes, readBuf.length - readBytes); if (nBytes < 0) { fail("Unexpected disconnection."); } readBytes += nBytes; } assertTrue(Arrays.equals( writeBuf, readBuf)); } client.setSoTimeout(500); try { client.getInputStream().read(); fail("Unexpected incoming data."); } catch (SocketTimeoutException e) { } client.getInputStream().close(); client.close(); } public void testUDP() throws Exception { DatagramSocket client = new DatagramSocket(); client.connect(new InetSocketAddress("127.0.0.1", port)); client.setSoTimeout(500); byte[] writeBuf = new byte[16]; byte[] readBuf = new byte[writeBuf.length]; DatagramPacket wp = new DatagramPacket(writeBuf, writeBuf.length); DatagramPacket rp = new DatagramPacket(readBuf, readBuf.length); for (int i = 0; i < 10; i++) { fillWriteBuffer(writeBuf, i); client.send(wp); client.receive(rp); assertEquals(writeBuf.length, rp.getLength()); assertTrue(Arrays.equals(writeBuf, readBuf)); } try { client.receive(rp); fail("Unexpected incoming data."); } catch (SocketTimeoutException e) { } client.close(); } private void fillWriteBuffer(byte[] writeBuf, int i) { for (int j = writeBuf.length - 1; j >= 0; j--) { writeBuf[j] = (byte) (j + i); } } } mina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/echoserver/AbstractTest.java0000644000175000017500000001475612032276035032667 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.echoserver; import static org.junit.Assert.assertEquals; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.security.GeneralSecurityException; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.echoserver.ssl.BogusSslContextFactory; import org.apache.mina.filter.ssl.SslFilter; import org.apache.mina.transport.socket.DatagramSessionConfig; import org.apache.mina.transport.socket.nio.NioDatagramAcceptor; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import org.apache.mina.util.AvailablePortFinder; import org.junit.After; import org.junit.Before; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Tests echo server example. * * @author Apache MINA Project */ public abstract class AbstractTest { private final static Logger LOGGER = LoggerFactory.getLogger(AbstractTest.class); protected boolean useSSL; protected int port; protected SocketAddress boundAddress; protected IoAcceptor datagramAcceptor; protected IoAcceptor socketAcceptor; protected AbstractTest() { // Do nothing } protected static void isEquals(byte[] expected, byte[] actual) { assertEquals(toString(expected), toString(actual)); } protected static void isEquals(IoBuffer expected, IoBuffer actual) { assertEquals(toString(expected), toString(actual)); } protected static String toString(byte[] buf) { StringBuilder str = new StringBuilder(buf.length * 4); for (byte element : buf) { str.append(element); str.append(' '); } return str.toString(); } protected static String toString(IoBuffer buf) { return buf.getHexDump(); } @Before public void setUp() throws Exception { // Disable SSL by default useSSL = false; boundAddress = null; datagramAcceptor = new NioDatagramAcceptor(); socketAcceptor = new NioSocketAcceptor(); ((DatagramSessionConfig) datagramAcceptor.getSessionConfig()) .setReuseAddress(true); ((NioSocketAcceptor) socketAcceptor).setReuseAddress(true); // Find an available test port and bind to it. boolean socketBound = false; boolean datagramBound = false; // Let's start from port #1 to detect possible resource leak // because test will fail in port 1-1023 if user run this test // as a normal user. SocketAddress address = null; // Find the first available port above 1024 port = AvailablePortFinder.getNextAvailable(1024); socketBound = false; datagramBound = false; address = new InetSocketAddress(port); try { socketAcceptor.setHandler(new EchoProtocolHandler() { @Override public void sessionCreated(IoSession session) { if (useSSL) { try { session.getFilterChain().addFirst( "SSL", new SslFilter(BogusSslContextFactory .getInstance(true))); } catch (GeneralSecurityException e) { LOGGER.error("", e); throw new RuntimeException(e); } } } // This is for TLS re-entrance test @Override public void messageReceived(IoSession session, Object message) throws Exception { if (!(message instanceof IoBuffer)) { return; } IoBuffer buf = (IoBuffer) message; buf.mark(); if (session.getFilterChain().contains("SSL") && buf.remaining() == 1 && buf.get() == (byte) '.') { LOGGER.info("TLS Reentrance"); ((SslFilter) session.getFilterChain().get("SSL")) .startSsl(session); // Send a response buf.capacity(1); buf.flip(); session.setAttribute(SslFilter.DISABLE_ENCRYPTION_ONCE); session.write(buf); } else { buf.reset(); super.messageReceived(session, buf); } } }); socketAcceptor.bind(address); socketBound = true; datagramAcceptor.setHandler(new EchoProtocolHandler()); datagramAcceptor.bind(address); datagramBound = true; } catch (IOException e) { // Do nothing } finally { if (socketBound && !datagramBound) { socketAcceptor.unbind(); } if (datagramBound && !socketBound) { datagramAcceptor.unbind(); } } // If there is no port available, test fails. if (!socketBound || !datagramBound) { throw new IOException("Cannot bind any test port."); } boundAddress = address; LOGGER.info("Using port " + port + " for testing."); } @After public void tearDown() throws Exception { if (boundAddress != null) { socketAcceptor.dispose(); datagramAcceptor.dispose(); } } } mina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/chat/0000755000175000017500000000000012162575507026170 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/chat/SpringMainTest.java0000644000175000017500000000361312032276034031732 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.chat; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.apache.mina.core.service.IoService; import org.junit.Before; import org.junit.Test; import org.springframework.context.ConfigurableApplicationContext; /** * TODO Add documentation * * @author Apache MINA Project */ public class SpringMainTest { private ConfigurableApplicationContext appContext; @Before public void tearDown() throws Exception { if (appContext != null) { appContext.close(); } } @Test public void testContext() { appContext = SpringMain.getApplicationContext(); IoService service = (IoService) appContext.getBean("ioAcceptor"); IoService ioAcceptorWithSSL = (IoService) appContext.getBean("ioAcceptorWithSSL"); assertTrue(service.isActive()); assertTrue(ioAcceptorWithSSL.isActive()); appContext.close(); assertFalse(service.isActive()); assertFalse(ioAcceptorWithSSL.isActive()); } } mina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/haiku/0000755000175000017500000000000012162575507026352 5ustar ebourgebourg././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/haiku/HaikuValidatorTest.javamina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/haiku/HaikuValidatorTest.jav0000644000175000017500000000550312032276035032614 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.mina.example.haiku; import org.junit.Before; import org.junit.Test; /** * @author Apache MINA Project */ public class HaikuValidatorTest { // from http://allrileyedup.blogspot.com/2006/10/dont-hassle-haiku.html -- good friend of proyal@apache.org private static final String[] HAIKUS = { "This class is boring.\n" + "Will David ever shut up?\n" + "What is Steph wearing?", "Oh, I drank too much.\n" + "Why, oh why did I sign up\n" + "For an eight thirty?", "Which one should I do?\n" + "Wax my chest or perm my hair?\n" + "Can’t wait to decide.", "Watch my video.\n" + "I can't stop this fee-ee-ling!\n" + "What is wrong with me?", "The car chases me.\n" + "I must get away from it.\n" + "Turbo Boost! Oh, yeah.", "My new slogan is\n" + "Don't hassle me... I'm oiling.\n" + "You know it’s so true.", "Michael, I love you.\n" + "I long for you to tell me\n" + "\"KITT, need you buddy.\"", "In Knight Rider, I’m\n" + "A Man Who Does Not Exist.\n" + "(Except in your dreams).", "Yes, I’m Michael Knight\n" + "Check out my unbuttoned shirt.\n" + "And sexy tight pants.", "My bitch ex-wife sucks.\n" + "And so do all the airlines.\n" + "I miss Knight Rider.", "I am Michael Knight.\n" + "I am David Hasselhoff.\n" + "I’m not Rick James, bitch." }; private HaikuValidator validator; @Before public void setUp() throws Exception { validator = new HaikuValidator(); } @Test public void testValidateHaikus() throws Exception { for (String s : HAIKUS) { String[] lines = s.split("\n"); Haiku haiku = new Haiku(lines); validator.validate(haiku); } } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/haiku/ToHaikuIoFilterTest.javamina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/haiku/ToHaikuIoFilterTest.ja0000644000175000017500000000605112032276035032520 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.mina.example.haiku; import java.util.Collections; import java.util.List; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.session.IoSession; import org.jmock.Mock; import org.jmock.MockObjectTestCase; /** * @author Apache MINA Project */ public class ToHaikuIoFilterTest extends MockObjectTestCase { private IoFilter filter; @Override protected void setUp() throws Exception { super.setUp(); filter = new ToHaikuIoFilter(); } public void testThreeStringsMakesAHaiku() throws Exception { Mock list = mock(List.class); list.expects(once()).method("add").with(eq("two")).will( returnValue(true)); list.expects(once()).method("add").with(eq("three")).will( returnValue(true)); list.expects(once()).method("toArray").with(isA(String[].class)).will( returnValue(new String[] { "one", "two", "three" })); list.expects(exactly(2)).method("size").will( onConsecutiveCalls(returnValue(2), returnValue(3))); Mock session = mock(IoSession.class); session.expects(exactly(3)).method("getAttribute").with(eq("phrases")) .will( onConsecutiveCalls(returnValue(null), returnValue(list .proxy()), returnValue(list.proxy()), returnValue(list.proxy()))); session.expects(exactly(1)).method("setAttribute").with(eq("phrases"), eq(Collections.emptyList())); session.expects(exactly(1)).method("removeAttribute").with( eq("phrases")); IoSession sessionProxy = (IoSession) session.proxy(); Mock nextFilter = mock(IoFilter.NextFilter.class); nextFilter.expects(once()).method("messageReceived").with( eq(sessionProxy), eq(new Haiku("one", "two", "three"))); IoFilter.NextFilter nextFilterProxy = (IoFilter.NextFilter) nextFilter .proxy(); filter.messageReceived(nextFilterProxy, sessionProxy, "one"); filter.messageReceived(nextFilterProxy, sessionProxy, "two"); filter.messageReceived(nextFilterProxy, sessionProxy, "three"); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/haiku/PhraseUtilitiesTest.javamina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/haiku/PhraseUtilitiesTest.ja0000644000175000017500000000520412032276035032633 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.mina.example.haiku; import static org.junit.Assert.assertEquals; import org.junit.Test; /** * @author Apache MINA Project */ public class PhraseUtilitiesTest { @Test public void testCountSyllablesInWord() throws Exception { assertSyllableCount(1, "one"); assertSyllableCount(1, "I"); assertSyllableCount(1, "too"); assertSyllableCount(1, "why"); assertSyllableCount(1, "oh"); assertSyllableCount(1, "did"); assertSyllableCount(1, "sign"); assertSyllableCount(1, "up"); assertSyllableCount(1, "watch"); assertSyllableCount(1, "my"); assertSyllableCount(1, "what"); assertSyllableCount(1, "is"); assertSyllableCount(1, "wrong"); assertSyllableCount(1, "with"); assertSyllableCount(1, "me"); assertSyllableCount(1, "don't"); assertSyllableCount(1, "you"); assertSyllableCount(1, "love"); assertSyllableCount(2, "hassle"); assertSyllableCount(2, "oiling"); assertSyllableCount(2, "decide"); assertSyllableCount(2, "Michael"); assertSyllableCount(1, "I'm"); assertSyllableCount(1, "check"); assertSyllableCount(1, "out"); assertSyllableCount(1, "shirt"); assertSyllableCount(1, "bitch"); assertSyllableCount(1, "sucks"); assertSyllableCount(1, "James"); assertSyllableCount(2, "ex-wife"); assertSyllableCount(2, "airlines"); assertSyllableCount(3, "video"); assertSyllableCount(3, "fee-ee-ling"); assertSyllableCount(3, "unbuttoned"); } private static void assertSyllableCount(int count, String word) { assertEquals("syllables in " + word, count, PhraseUtilities .countSyllablesInWord(word.toLowerCase())); } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/haiku/HaikuValidatorIoHandlerTest.javamina2-2.0.7.orig/src/mina-example/src/test/java/org/apache/mina/example/haiku/HaikuValidatorIoHandle0000644000175000017500000000411612032276035032600 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.mina.example.haiku; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.session.IoSession; import org.jmock.Mock; import org.jmock.MockObjectTestCase; /** * @author Apache MINA Project */ public class HaikuValidatorIoHandlerTest extends MockObjectTestCase { private IoHandler handler; @Override protected void setUp() throws Exception { super.setUp(); handler = new HaikuValidatorIoHandler(); } public void testValidHaiku() throws Exception { Mock session = mock(IoSession.class); session.expects(once()).method("write").with(eq("HAIKU!")); IoSession sessionProxy = (IoSession) session.proxy(); handler.messageReceived(sessionProxy, new Haiku( "Oh, I drank too much.", "Why, oh why did I sign up", "For an eight thirty?")); } public void testInvalidHaiku() throws Exception { Mock session = mock(IoSession.class); session.expects(once()).method("write").with( eq("NOT A HAIKU: phrase 1, 'foo' had 1 syllables, not 5")); IoSession sessionProxy = (IoSession) session.proxy(); handler.messageReceived(sessionProxy, new Haiku("foo", "a haiku", "poo")); } } mina2-2.0.7.orig/src/mina-example/src/test/resources/0000755000175000017500000000000012162575507021753 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/test/resources/log4j.properties0000644000175000017500000000244112032276035025077 0ustar ebourgebourg############################################################################# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ############################################################################# log4j.rootCategory=ERROR, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c] - %m%n log4j.logger.org.apache.mina.filter.ssl.SslFilter=ERROR log4j.logger.org.apache.mina.filter.ssl.SslHandler=ERROR mina2-2.0.7.orig/src/mina-example/src/main/0000755000175000017500000000000012032276040017670 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/0000755000175000017500000000000012032276035020615 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/0000755000175000017500000000000012032276035021404 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/0000755000175000017500000000000012032276035022625 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/0000755000175000017500000000000012032276035023551 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/0000755000175000017500000000000012032276040025200 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tennis/0000755000175000017500000000000012162575507026516 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tennis/TennisPlayer.java0000644000175000017500000000465012032276036031772 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tennis; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; /** * A {@link IoHandler} implementation which plays a tennis game. * * @author Apache MINA Project */ public class TennisPlayer extends IoHandlerAdapter { private static int nextId = 0; /** Player ID **/ private final int id = nextId++; @Override public void sessionOpened(IoSession session) { System.out.println("Player-" + id + ": READY"); } @Override public void sessionClosed(IoSession session) { System.out.println("Player-" + id + ": QUIT"); } @Override public void messageReceived(IoSession session, Object message) { System.out.println("Player-" + id + ": RCVD " + message); TennisBall ball = (TennisBall) message; // Stroke: TTL decreases and PING/PONG state changes. ball = ball.stroke(); if (ball.getTTL() > 0) { // If the ball is still alive, pass it back to peer. session.write(ball); } else { // If the ball is dead, this player loses. System.out.println("Player-" + id + ": LOSE"); session.close(true); } } @Override public void messageSent(IoSession session, Object message) { System.out.println("Player-" + id + ": SENT " + message); } @Override public void exceptionCaught(IoSession session, Throwable cause) { cause.printStackTrace(); session.close(true); } }mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tennis/Main.java0000644000175000017500000000467612032276036030251 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tennis; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.session.IoSession; import org.apache.mina.transport.vmpipe.VmPipeAcceptor; import org.apache.mina.transport.vmpipe.VmPipeAddress; import org.apache.mina.transport.vmpipe.VmPipeConnector; /** * (Entry point) An 'in-VM pipe' example which simulates a tennis game * between client and server. *
    *
  1. Client connects to server
  2. *
  3. At first, client sends {@link TennisBall} with TTL value '10'.
  4. *
  5. Received side (either server or client) decreases the TTL value of the * received ball, and returns it to remote peer.
  6. *
  7. Who gets the ball with 0 TTL loses.
  8. *
* * @author Apache MINA Project */ public class Main { public static void main(String[] args) throws Exception { IoAcceptor acceptor = new VmPipeAcceptor(); VmPipeAddress address = new VmPipeAddress(8080); // Set up server acceptor.setHandler(new TennisPlayer()); acceptor.bind(address); // Connect to the server. VmPipeConnector connector = new VmPipeConnector(); connector.setHandler(new TennisPlayer()); ConnectFuture future = connector.connect(address); future.awaitUninterruptibly(); IoSession session = future.getSession(); // Send the first ping message session.write(new TennisBall(10)); // Wait until the match ends. session.getCloseFuture().awaitUninterruptibly(); acceptor.unbind(); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tennis/TennisBall.java0000644000175000017500000000410612032276036031404 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tennis; /** * A tennis ball which has TTL value and state whose value is one of 'PING' and * 'PONG'. * * @author Apache MINA Project */ public class TennisBall { private final boolean ping; private final int ttl; /** * Creates a new ball with the specified TTL (Time To Live) value. */ public TennisBall(int ttl) { this(ttl, true); } /** * Creates a new ball with the specified TTL value and PING/PONG state. */ private TennisBall(int ttl, boolean ping) { this.ttl = ttl; this.ping = ping; } /** * Returns the TTL value of this ball. */ public int getTTL() { return ttl; } /** * Returns the ball after {@link TennisPlayer}'s stroke. * The returned ball has decreased TTL value and switched PING/PONG state. */ public TennisBall stroke() { return new TennisBall(ttl - 1, !ping); } /** * Returns string representation of this message ([PING|PONG] * (TTL)). */ @Override public String toString() { if (ping) { return "PING (" + ttl + ")"; } else { return "PONG (" + ttl + ")"; } } }mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tennis/package.html0000644000175000017500000000165412032276036030774 0ustar ebourgebourg Two tennis players play a game which demonstates in-VM pipes. mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/proxy/0000755000175000017500000000000012162575507026377 5ustar ebourgebourg././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/proxy/ClientToProxyIoHandler.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/proxy/ClientToProxyIoHandler0000644000175000017500000000512612032276036032666 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.proxy; import java.net.SocketAddress; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.session.IoSession; /** * Handles the client to proxy part of the proxied connection. * * @author Apache MINA Project */ public class ClientToProxyIoHandler extends AbstractProxyIoHandler { private final ServerToProxyIoHandler connectorHandler = new ServerToProxyIoHandler(); private final IoConnector connector; private final SocketAddress remoteAddress; public ClientToProxyIoHandler(IoConnector connector, SocketAddress remoteAddress) { this.connector = connector; this.remoteAddress = remoteAddress; connector.setHandler(connectorHandler); } @Override public void sessionOpened(final IoSession session) throws Exception { connector.connect(remoteAddress).addListener(new IoFutureListener() { public void operationComplete(ConnectFuture future) { try { future.getSession().setAttribute(OTHER_IO_SESSION, session); session.setAttribute(OTHER_IO_SESSION, future.getSession()); IoSession session2 = future.getSession(); session2.resumeRead(); session2.resumeWrite(); } catch (RuntimeIoException e) { // Connect failed session.close(true); } finally { session.resumeRead(); session.resumeWrite(); } } }); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/proxy/ServerToProxyIoHandler.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/proxy/ServerToProxyIoHandler0000644000175000017500000000206612032276036032716 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.proxy; /** * Handles the server to proxy part of the proxied connection. * * @author Apache MINA Project */ public class ServerToProxyIoHandler extends AbstractProxyIoHandler { } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/proxy/AbstractProxyIoHandler.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/proxy/AbstractProxyIoHandler0000644000175000017500000000506512032276036032712 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.proxy; import java.nio.charset.Charset; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Base class of {@link org.apache.mina.core.service.IoHandler} classes which handle * proxied connections. * * @author Apache MINA Project */ public abstract class AbstractProxyIoHandler extends IoHandlerAdapter { private static final Charset CHARSET = Charset.forName("iso8859-1"); public static final String OTHER_IO_SESSION = AbstractProxyIoHandler.class.getName()+".OtherIoSession"; private final static Logger LOGGER = LoggerFactory.getLogger(AbstractProxyIoHandler.class); @Override public void sessionCreated(IoSession session) throws Exception { session.suspendRead(); session.suspendWrite(); } @Override public void sessionClosed(IoSession session) throws Exception { if (session.getAttribute( OTHER_IO_SESSION ) != null) { IoSession sess = (IoSession) session.getAttribute(OTHER_IO_SESSION); sess.setAttribute(OTHER_IO_SESSION, null); sess.close(false); session.setAttribute(OTHER_IO_SESSION, null); } } @Override public void messageReceived(IoSession session, Object message) throws Exception { IoBuffer rb = (IoBuffer) message; IoBuffer wb = IoBuffer.allocate(rb.remaining()); rb.mark(); wb.put(rb); wb.flip(); ((IoSession) session.getAttribute(OTHER_IO_SESSION)).write(wb); rb.reset(); LOGGER.info(rb.getString(CHARSET.newDecoder())); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/proxy/Main.java0000644000175000017500000000502212032276036030114 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.proxy; import java.net.InetSocketAddress; import org.apache.mina.core.service.IoConnector; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import org.apache.mina.transport.socket.nio.NioSocketConnector; /** * (Entry point) Demonstrates how to write a very simple tunneling proxy * using MINA. The proxy only logs all data passing through it. This is only * suitable for text based protocols since received data will be converted into * strings before being logged. *

* Start a proxy like this:
* org.apache.mina.example.proxy.Main 12345 www.google.com 80
* and open http://localhost:12345 in a * browser window. *

* * @author Apache MINA Project */ public class Main { public static void main(String[] args) throws Exception { if (args.length != 3) { System.out.println(Main.class.getName() + " "); return; } // Create TCP/IP acceptor. NioSocketAcceptor acceptor = new NioSocketAcceptor(); // Create TCP/IP connector. IoConnector connector = new NioSocketConnector(); // Set connect timeout. connector.setConnectTimeoutMillis(30*1000L); ClientToProxyIoHandler handler = new ClientToProxyIoHandler(connector, new InetSocketAddress(args[1], Integer.parseInt(args[2]))); // Start proxy. acceptor.setHandler(handler); acceptor.bind(new InetSocketAddress(Integer.parseInt(args[0]))); System.out.println("Listening on port " + Integer.parseInt(args[0])); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/proxy/package.html0000644000175000017500000000163012032276036030647 0ustar ebourgebourg A TCP/IP tunneling proxy example. mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/echoserver/0000755000175000017500000000000012162575507027363 5ustar ebourgebourg././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/echoserver/EchoProtocolHandler.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/echoserver/EchoProtocolHandl0000644000175000017500000000502412032276036032645 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.echoserver; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.ssl.SslFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * {@link IoHandler} implementation for echo server. * * @author Apache MINA Project */ public class EchoProtocolHandler extends IoHandlerAdapter { private final static Logger LOGGER = LoggerFactory.getLogger(EchoProtocolHandler.class); @Override public void sessionCreated(IoSession session) { session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10); // We're going to use SSL negotiation notification. session.setAttribute(SslFilter.USE_NOTIFICATION); } @Override public void sessionClosed(IoSession session) throws Exception { LOGGER.info("CLOSED"); } @Override public void sessionOpened(IoSession session) throws Exception { LOGGER.info("OPENED"); } @Override public void sessionIdle(IoSession session, IdleStatus status) { LOGGER.info("*** IDLE #" + session.getIdleCount(IdleStatus.BOTH_IDLE) + " ***"); } @Override public void exceptionCaught(IoSession session, Throwable cause) { session.close(true); } @Override public void messageReceived(IoSession session, Object message) throws Exception { LOGGER.info( "Received : " + message ); // Write the received data back to remote peer session.write(((IoBuffer) message).duplicate()); } }mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/echoserver/ssl/0000755000175000017500000000000012162575507030164 5ustar ebourgebourg././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/echoserver/ssl/SslServerSocketFactory.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/echoserver/ssl/SslServerSock0000644000175000017500000000600512032276036032647 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.echoserver.ssl; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.security.GeneralSecurityException; import javax.net.ServerSocketFactory; /** * Simple Server Socket factory to create sockets with or without SSL enabled. * If SSL enabled a "bougus" SSL Context is used (suitable for test purposes) * * @author Apache MINA Project */ public class SslServerSocketFactory extends javax.net.ServerSocketFactory { private static boolean sslEnabled = false; private static javax.net.ServerSocketFactory sslFactory = null; private static ServerSocketFactory factory = null; public SslServerSocketFactory() { super(); } @Override public ServerSocket createServerSocket(int port) throws IOException { return new ServerSocket(port); } @Override public ServerSocket createServerSocket(int port, int backlog) throws IOException { return new ServerSocket(port, backlog); } @Override public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) throws IOException { return new ServerSocket(port, backlog, ifAddress); } public static javax.net.ServerSocketFactory getServerSocketFactory() throws IOException { if (isSslEnabled()) { if (sslFactory == null) { try { sslFactory = BogusSslContextFactory.getInstance(true) .getServerSocketFactory(); } catch (GeneralSecurityException e) { IOException ioe = new IOException( "could not create SSL socket"); ioe.initCause(e); throw ioe; } } return sslFactory; } else { if (factory == null) { factory = new SslServerSocketFactory(); } return factory; } } public static boolean isSslEnabled() { return sslEnabled; } public static void setSslEnabled(boolean newSslEnabled) { sslEnabled = newSslEnabled; } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/echoserver/ssl/BogusTrustManagerFactory.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/echoserver/ssl/BogusTrustMan0000644000175000017500000000462612032276036032663 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.echoserver.ssl; import java.security.InvalidAlgorithmParameterException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.ManagerFactoryParameters; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactorySpi; import javax.net.ssl.X509TrustManager; /** * Bogus trust manager factory. Creates BogusX509TrustManager * * @author Apache MINA Project */ class BogusTrustManagerFactory extends TrustManagerFactorySpi { static final X509TrustManager X509 = new X509TrustManager() { public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { } public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }; static final TrustManager[] X509_MANAGERS = new TrustManager[] { X509 }; public BogusTrustManagerFactory() { } @Override protected TrustManager[] engineGetTrustManagers() { return X509_MANAGERS; } @Override protected void engineInit(KeyStore keystore) throws KeyStoreException { // noop } @Override protected void engineInit(ManagerFactoryParameters managerFactoryParameters) throws InvalidAlgorithmParameterException { // noop } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/echoserver/ssl/BogusSslContextFactory.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/echoserver/ssl/BogusSslConte0000644000175000017500000001134712032276036032636 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.echoserver.ssl; import java.io.IOException; import java.io.InputStream; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.Security; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; /** * Factory to create a bogus SSLContext. * * @author Apache MINA Project */ public class BogusSslContextFactory { /** * Protocol to use. */ private static final String PROTOCOL = "TLS"; private static final String KEY_MANAGER_FACTORY_ALGORITHM; static { String algorithm = Security .getProperty("ssl.KeyManagerFactory.algorithm"); if (algorithm == null) { algorithm = KeyManagerFactory.getDefaultAlgorithm(); } KEY_MANAGER_FACTORY_ALGORITHM = algorithm; } /** * Bougus Server certificate keystore file name. */ private static final String BOGUS_KEYSTORE = "bogus.cert"; // NOTE: The keystore was generated using keytool: // keytool -genkey -alias bogus -keysize 512 -validity 3650 // -keyalg RSA -dname "CN=bogus.com, OU=XXX CA, // O=Bogus Inc, L=Stockholm, S=Stockholm, C=SE" // -keypass boguspw -storepass boguspw -keystore bogus.cert /** * Bougus keystore password. */ private static final char[] BOGUS_PW = { 'b', 'o', 'g', 'u', 's', 'p', 'w' }; private static SSLContext serverInstance = null; private static SSLContext clientInstance = null; /** * Get SSLContext singleton. * * @return SSLContext * @throws java.security.GeneralSecurityException * */ public static SSLContext getInstance(boolean server) throws GeneralSecurityException { SSLContext retInstance = null; if (server) { synchronized(BogusSslContextFactory.class) { if (serverInstance == null) { try { serverInstance = createBougusServerSslContext(); } catch (Exception ioe) { throw new GeneralSecurityException( "Can't create Server SSLContext:" + ioe); } } } retInstance = serverInstance; } else { synchronized (BogusSslContextFactory.class) { if (clientInstance == null) { clientInstance = createBougusClientSslContext(); } } retInstance = clientInstance; } return retInstance; } private static SSLContext createBougusServerSslContext() throws GeneralSecurityException, IOException { // Create keystore KeyStore ks = KeyStore.getInstance("JKS"); InputStream in = null; try { in = BogusSslContextFactory.class .getResourceAsStream(BOGUS_KEYSTORE); ks.load(in, BOGUS_PW); } finally { if (in != null) { try { in.close(); } catch (IOException ignored) { } } } // Set up key manager factory to use our key store KeyManagerFactory kmf = KeyManagerFactory .getInstance(KEY_MANAGER_FACTORY_ALGORITHM); kmf.init(ks, BOGUS_PW); // Initialize the SSLContext to work with our key managers. SSLContext sslContext = SSLContext.getInstance(PROTOCOL); sslContext.init(kmf.getKeyManagers(), BogusTrustManagerFactory.X509_MANAGERS, null); return sslContext; } private static SSLContext createBougusClientSslContext() throws GeneralSecurityException { SSLContext context = SSLContext.getInstance(PROTOCOL); context.init(null, BogusTrustManagerFactory.X509_MANAGERS, null); return context; } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/echoserver/ssl/package.html0000644000175000017500000000160312032276036032434 0ustar ebourgebourg SSL support classes. ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/echoserver/ssl/SslSocketFactory.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/echoserver/ssl/SslSocketFact0000644000175000017500000000701212032276036032606 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.echoserver.ssl; import java.io.IOException; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.security.GeneralSecurityException; import javax.net.SocketFactory; /** * Simple Socket factory to create sockets with or without SSL enabled. * If SSL enabled a "bougus" SSL Context is used (suitable for test purposes) * * @author Apache MINA Project */ public class SslSocketFactory extends SocketFactory { private static boolean sslEnabled = false; private static javax.net.ssl.SSLSocketFactory sslFactory = null; private static javax.net.SocketFactory factory = null; public SslSocketFactory() { super(); } @Override public Socket createSocket(String arg1, int arg2) throws IOException, UnknownHostException { if (isSslEnabled()) { return getSSLFactory().createSocket(arg1, arg2); } else { return new Socket(arg1, arg2); } } @Override public Socket createSocket(String arg1, int arg2, InetAddress arg3, int arg4) throws IOException, UnknownHostException { if (isSslEnabled()) { return getSSLFactory().createSocket(arg1, arg2, arg3, arg4); } else { return new Socket(arg1, arg2, arg3, arg4); } } @Override public Socket createSocket(InetAddress arg1, int arg2) throws IOException { if (isSslEnabled()) { return getSSLFactory().createSocket(arg1, arg2); } else { return new Socket(arg1, arg2); } } @Override public Socket createSocket(InetAddress arg1, int arg2, InetAddress arg3, int arg4) throws IOException { if (isSslEnabled()) { return getSSLFactory().createSocket(arg1, arg2, arg3, arg4); } else { return new Socket(arg1, arg2, arg3, arg4); } } public static javax.net.SocketFactory getSocketFactory() { if (factory == null) { factory = new SslSocketFactory(); } return factory; } private javax.net.ssl.SSLSocketFactory getSSLFactory() { if (sslFactory == null) { try { sslFactory = BogusSslContextFactory.getInstance(false) .getSocketFactory(); } catch (GeneralSecurityException e) { throw new RuntimeException("could not create SSL socket", e); } } return sslFactory; } public static boolean isSslEnabled() { return sslEnabled; } public static void setSslEnabled(boolean newSslEnabled) { sslEnabled = newSslEnabled; } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/echoserver/Main.java0000644000175000017500000000511412032276036031102 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.echoserver; import java.net.InetSocketAddress; import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; import org.apache.mina.example.echoserver.ssl.BogusSslContextFactory; import org.apache.mina.filter.ssl.SslFilter; import org.apache.mina.transport.socket.SocketAcceptor; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; /** * (Entry point) Echo server * * @author Apache MINA Project */ public class Main { /** Choose your favorite port number. */ private static final int PORT = 8080; /** Set this to true if you want to make the server SSL */ private static final boolean USE_SSL = false; public static void main(String[] args) throws Exception { SocketAcceptor acceptor = new NioSocketAcceptor(); acceptor.setReuseAddress( true ); DefaultIoFilterChainBuilder chain = acceptor.getFilterChain(); // Add SSL filter if SSL is enabled. if (USE_SSL) { addSSLSupport(chain); } // Bind acceptor.setHandler(new EchoProtocolHandler()); acceptor.bind(new InetSocketAddress(PORT)); System.out.println("Listening on port " + PORT); for (;;) { System.out.println("R: " + acceptor.getStatistics().getReadBytesThroughput() + ", W: " + acceptor.getStatistics().getWrittenBytesThroughput()); Thread.sleep(3000); } } private static void addSSLSupport(DefaultIoFilterChainBuilder chain) throws Exception { SslFilter sslFilter = new SslFilter(BogusSslContextFactory .getInstance(true)); chain.addLast("sslFilter", sslFilter); System.out.println("SSL ON"); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/echoserver/package.html0000644000175000017500000000166112032276036031637 0ustar ebourgebourg Echo server which demonstates low-level I/O layer and SSL support. mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/reverser/0000755000175000017500000000000012162575507027053 5ustar ebourgebourg././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/reverser/ReverseProtocolHandler.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/reverser/ReverseProtocolHand0000644000175000017500000000342112032276040032710 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.reverser; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; /** * {@link IoHandler} implementation of reverser server protocol. * * @author Apache MINA Project */ public class ReverseProtocolHandler extends IoHandlerAdapter { @Override public void exceptionCaught(IoSession session, Throwable cause) { // Close connection when unexpected exception is caught. session.close(true); } @Override public void messageReceived(IoSession session, Object message) { // Reverse reveiced string String str = message.toString(); StringBuilder buf = new StringBuilder(str.length()); for (int i = str.length() - 1; i >= 0; i--) { buf.append(str.charAt(i)); } // and write it back. session.write(buf.toString()); } }mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/reverser/Main.java0000644000175000017500000000375012032276040030571 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.reverser; import java.net.InetSocketAddress; import java.nio.charset.Charset; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; /** * (Entry point) Reverser server which reverses all text lines from * clients. * * @author Apache MINA Project */ public class Main { private static final int PORT = 8080; public static void main(String[] args) throws Exception { NioSocketAcceptor acceptor = new NioSocketAcceptor(); // Prepare the configuration acceptor.getFilterChain().addLast("logger", new LoggingFilter()); acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset .forName("UTF-8")))); // Bind acceptor.setHandler(new ReverseProtocolHandler()); acceptor.bind(new InetSocketAddress(PORT)); System.out.println("Listening on port " + PORT); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/reverser/package.html0000644000175000017500000000171412032276040031321 0ustar ebourgebourg Reverser server which reverses all text lines demonstating high-level protocol layer. mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/0000755000175000017500000000000012162575507026135 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/client/0000755000175000017500000000000012162575507027413 5ustar ebourgebourg././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/client/ChatClientSupport.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/client/ChatClientSuppor0000644000175000017500000000760612032276035032564 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.chat.client; import java.net.SocketAddress; import javax.net.ssl.SSLContext; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.echoserver.ssl.BogusSslContextFactory; import org.apache.mina.filter.ssl.SslFilter; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.filter.logging.MdcInjectionFilter; import org.apache.mina.transport.socket.nio.NioSocketConnector; /** * A simple chat client for a given user. * * @author Apache MINA Project */ public class ChatClientSupport { private final IoHandler handler; private final String name; private IoSession session; public ChatClientSupport(String name, IoHandler handler) { if (name == null) { throw new IllegalArgumentException("Name can not be null"); } this.name = name; this.handler = handler; } public boolean connect(NioSocketConnector connector, SocketAddress address, boolean useSsl) { if (session != null && session.isConnected()) { throw new IllegalStateException( "Already connected. Disconnect first."); } try { IoFilter LOGGING_FILTER = new LoggingFilter(); IoFilter CODEC_FILTER = new ProtocolCodecFilter( new TextLineCodecFactory()); connector.getFilterChain().addLast("mdc", new MdcInjectionFilter()); connector.getFilterChain().addLast("codec", CODEC_FILTER); connector.getFilterChain().addLast("logger", LOGGING_FILTER); if (useSsl) { SSLContext sslContext = BogusSslContextFactory .getInstance(false); SslFilter sslFilter = new SslFilter(sslContext); sslFilter.setUseClientMode(true); connector.getFilterChain().addFirst("sslFilter", sslFilter); } connector.setHandler(handler); ConnectFuture future1 = connector.connect(address); future1.awaitUninterruptibly(); if (!future1.isConnected()) { return false; } session = future1.getSession(); login(); return true; } catch (Exception e) { return false; } } public void login() { session.write("LOGIN " + name); } public void broadcast(String message) { session.write("BROADCAST " + message); } public void quit() { if (session != null) { if (session.isConnected()) { session.write("QUIT"); // Wait until the chat ends. session.getCloseFuture().awaitUninterruptibly(); } session.close(true); } } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/client/SwingChatClient.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/client/SwingChatClient.0000644000175000017500000002175112032276035032436 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.chat.client; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.net.InetSocketAddress; import java.net.SocketAddress; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollBar; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.border.EmptyBorder; import org.apache.mina.example.chat.client.SwingChatClientHandler.Callback; import org.apache.mina.transport.socket.nio.NioSocketConnector; /** * Simple chat client based on Swing & MINA that implements the chat protocol. * * @author Apache MINA Project */ public class SwingChatClient extends JFrame implements Callback { private static final long serialVersionUID = 1538675161745436968L; private JTextField inputText; private JButton loginButton; private JButton quitButton; private JButton closeButton; private JTextField serverField; private JTextField nameField; private JTextArea area; private JScrollBar scroll; private ChatClientSupport client; private SwingChatClientHandler handler; private NioSocketConnector connector; public SwingChatClient() { super("Chat Client based on Apache MINA"); connector = new NioSocketConnector(); loginButton = new JButton(new LoginAction()); loginButton.setText("Connect"); quitButton = new JButton(new LogoutAction()); quitButton.setText("Disconnect"); closeButton = new JButton(new QuitAction()); closeButton.setText("Quit"); inputText = new JTextField(30); inputText.setAction(new BroadcastAction()); area = new JTextArea(10, 50); area.setLineWrap(true); area.setEditable(false); scroll = new JScrollBar(); scroll.add(area); nameField = new JTextField(10); nameField.setEditable(false); serverField = new JTextField(10); serverField.setEditable(false); JPanel h = new JPanel(); h.setLayout(new BoxLayout(h, BoxLayout.LINE_AXIS)); h.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); JLabel nameLabel = new JLabel("Name: "); JLabel serverLabel = new JLabel("Server: "); h.add(nameLabel); h.add(Box.createRigidArea(new Dimension(10, 0))); h.add(nameField); h.add(Box.createRigidArea(new Dimension(10, 0))); h.add(Box.createHorizontalGlue()); h.add(Box.createRigidArea(new Dimension(10, 0))); h.add(serverLabel); h.add(Box.createRigidArea(new Dimension(10, 0))); h.add(serverField); JPanel p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.LINE_AXIS)); p.setBorder(new EmptyBorder(10, 10, 10, 10)); JPanel left = new JPanel(); left.setLayout(new BoxLayout(left, BoxLayout.PAGE_AXIS)); left.add(area); left.add(Box.createRigidArea(new Dimension(0, 5))); left.add(Box.createHorizontalGlue()); left.add(inputText); JPanel right = new JPanel(); right.setLayout(new BoxLayout(right, BoxLayout.PAGE_AXIS)); right.add(loginButton); right.add(Box.createRigidArea(new Dimension(0, 5))); right.add(quitButton); right.add(Box.createHorizontalGlue()); right.add(Box.createRigidArea(new Dimension(0, 25))); right.add(closeButton); p.add(left); p.add(Box.createRigidArea(new Dimension(10, 0))); p.add(right); getContentPane().add(h, BorderLayout.NORTH); getContentPane().add(p); closeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { client.quit(); connector.dispose(); dispose(); } }); setLoggedOut(); setDefaultCloseOperation(EXIT_ON_CLOSE); } public class LoginAction extends AbstractAction { private static final long serialVersionUID = 3596719854773863244L; public void actionPerformed(ActionEvent e) { ConnectDialog dialog = new ConnectDialog(SwingChatClient.this); dialog.pack(); dialog.setVisible(true); if (dialog.isCancelled()) { return; } SocketAddress address = parseSocketAddress(dialog .getServerAddress()); String name = dialog.getUsername(); handler = new SwingChatClientHandler(SwingChatClient.this); client = new ChatClientSupport(name, handler); nameField.setText(name); serverField.setText(dialog.getServerAddress()); if (!client.connect(connector, address, dialog.isUseSsl())) { JOptionPane.showMessageDialog(SwingChatClient.this, "Could not connect to " + dialog.getServerAddress() + ". "); } } } private class LogoutAction extends AbstractAction { private static final long serialVersionUID = 1655297424639924560L; public void actionPerformed(ActionEvent e) { try { client.quit(); setLoggedOut(); } catch (Exception e1) { JOptionPane.showMessageDialog(SwingChatClient.this, "Session could not be closed."); } } } private class BroadcastAction extends AbstractAction { /** * */ private static final long serialVersionUID = -6276019615521905411L; public void actionPerformed(ActionEvent e) { client.broadcast(inputText.getText()); inputText.setText(""); } } private class QuitAction extends AbstractAction { private static final long serialVersionUID = -6389802816912005370L; public void actionPerformed(ActionEvent e) { if (client != null) { client.quit(); } SwingChatClient.this.dispose(); } } private void setLoggedOut() { inputText.setEnabled(false); quitButton.setEnabled(false); loginButton.setEnabled(true); } private void setLoggedIn() { area.setText(""); inputText.setEnabled(true); quitButton.setEnabled(true); loginButton.setEnabled(false); } private void append(String text) { area.append(text); } private void notifyError(String message) { JOptionPane.showMessageDialog(this, message); } private SocketAddress parseSocketAddress(String s) { s = s.trim(); int colonIndex = s.indexOf(":"); if (colonIndex > 0) { String host = s.substring(0, colonIndex); int port = parsePort(s.substring(colonIndex + 1)); return new InetSocketAddress(host, port); } else { int port = parsePort(s.substring(colonIndex + 1)); return new InetSocketAddress(port); } } private int parsePort(String s) { try { return Integer.parseInt(s); } catch (NumberFormatException nfe) { throw new IllegalArgumentException("Illegal port number: " + s); } } public void connected() { //client.login(); } public void disconnected() { append("Connection closed.\n"); setLoggedOut(); } public void error(String message) { notifyError(message + "\n"); } public void loggedIn() { setLoggedIn(); append("You have joined the chat session.\n"); } public void loggedOut() { append("You have left the chat session.\n"); setLoggedOut(); } public void messageReceived(String message) { append(message + "\n"); } public static void main(String[] args) { SwingChatClient client = new SwingChatClient(); client.pack(); client.setVisible(true); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/client/ConnectDialog.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/client/ConnectDialog.ja0000644000175000017500000000714712032276035032437 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.chat.client; import java.awt.BorderLayout; import java.awt.Frame; import java.awt.HeadlessException; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; /** * TODO Add documentation * * @author Apache MINA Project * */ public class ConnectDialog extends JDialog { private static final long serialVersionUID = 2009384520250666216L; private String serverAddress; private String username; private boolean useSsl; private boolean cancelled = false; public ConnectDialog(Frame owner) throws HeadlessException { super(owner, "Connect", true); serverAddress = "localhost:1234"; username = "user" + Math.round(Math.random() * 10); final JTextField serverAddressField = new JTextField(serverAddress); final JTextField usernameField = new JTextField(username); final JCheckBox useSslCheckBox = new JCheckBox("Use SSL", false); JPanel content = new JPanel(); content.setLayout(new BoxLayout(content, BoxLayout.PAGE_AXIS)); content.add(new JLabel("Server address")); content.add(serverAddressField); content.add(new JLabel("Username")); content.add(usernameField); content.add(useSslCheckBox); JButton okButton = new JButton(); okButton.setAction(new AbstractAction("OK") { private static final long serialVersionUID = -2292183622613960604L; public void actionPerformed(ActionEvent e) { serverAddress = serverAddressField.getText(); username = usernameField.getText(); useSsl = useSslCheckBox.isSelected(); ConnectDialog.this.dispose(); } }); JButton cancelButton = new JButton(); cancelButton.setAction(new AbstractAction("Cancel") { private static final long serialVersionUID = 6122393546173723305L; public void actionPerformed(ActionEvent e) { cancelled = true; ConnectDialog.this.dispose(); } }); JPanel buttons = new JPanel(); buttons.add(okButton); buttons.add(cancelButton); getContentPane().add(content, BorderLayout.CENTER); getContentPane().add(buttons, BorderLayout.SOUTH); } public boolean isCancelled() { return cancelled; } public String getServerAddress() { return serverAddress; } public String getUsername() { return username; } public boolean isUseSsl() { return useSsl; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/client/SwingChatClientHandler.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/client/SwingChatClientH0000644000175000017500000000543612032276035032472 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.chat.client; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.chat.ChatCommand; /** * {@link IoHandler} implementation of the client side of the simple chat protocol. * * @author Apache MINA Project */ public class SwingChatClientHandler extends IoHandlerAdapter { public interface Callback { void connected(); void loggedIn(); void loggedOut(); void disconnected(); void messageReceived(String message); void error(String message); } private final Callback callback; public SwingChatClientHandler(Callback callback) { this.callback = callback; } @Override public void sessionOpened(IoSession session) throws Exception { callback.connected(); } @Override public void messageReceived(IoSession session, Object message) throws Exception { String theMessage = (String) message; String[] result = theMessage.split(" ", 3); String status = result[1]; String theCommand = result[0]; ChatCommand command = ChatCommand.valueOf(theCommand); if ("OK".equals(status)) { switch (command.toInt()) { case ChatCommand.BROADCAST: if (result.length == 3) { callback.messageReceived(result[2]); } break; case ChatCommand.LOGIN: callback.loggedIn(); break; case ChatCommand.QUIT: callback.loggedOut(); break; } } else { if (result.length == 3) { callback.error(result[2]); } } } @Override public void sessionClosed(IoSession session) throws Exception { callback.disconnected(); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/client/package.html0000644000175000017500000000160712032276035031666 0ustar ebourgebourg Swing based chat client. ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/ChatProtocolHandler.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/ChatProtocolHandler.jav0000644000175000017500000001206512032276035032530 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.chat; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.logging.MdcInjectionFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * {@link IoHandler} implementation of a simple chat server protocol. * * @author Apache MINA Project */ public class ChatProtocolHandler extends IoHandlerAdapter { private final static Logger LOGGER = LoggerFactory.getLogger(ChatProtocolHandler.class); private final Set sessions = Collections .synchronizedSet(new HashSet()); private final Set users = Collections .synchronizedSet(new HashSet()); @Override public void exceptionCaught(IoSession session, Throwable cause) { LOGGER.warn("Unexpected exception.", cause); // Close connection when unexpected exception is caught. session.close(true); } @Override public void messageReceived(IoSession session, Object message) { Logger log = LoggerFactory.getLogger(ChatProtocolHandler.class); log.info("received: " + message); String theMessage = (String) message; String[] result = theMessage.split(" ", 2); String theCommand = result[0]; try { ChatCommand command = ChatCommand.valueOf(theCommand); String user = (String) session.getAttribute("user"); switch (command.toInt()) { case ChatCommand.QUIT: session.write("QUIT OK"); session.close(true); break; case ChatCommand.LOGIN: if (user != null) { session.write("LOGIN ERROR user " + user + " already logged in."); return; } if (result.length == 2) { user = result[1]; } else { session.write("LOGIN ERROR invalid login command."); return; } // check if the username is already used if (users.contains(user)) { session.write("LOGIN ERROR the name " + user + " is already used."); return; } sessions.add(session); session.setAttribute("user", user); MdcInjectionFilter.setProperty(session, "user", user); // Allow all users users.add(user); session.write("LOGIN OK"); broadcast("The user " + user + " has joined the chat session."); break; case ChatCommand.BROADCAST: if (result.length == 2) { broadcast(user + ": " + result[1]); } break; default: LOGGER.info("Unhandled command: " + command); break; } } catch (IllegalArgumentException e) { LOGGER.debug("Illegal argument", e); } } public void broadcast(String message) { synchronized (sessions) { for (IoSession session : sessions) { if (session.isConnected()) { session.write("BROADCAST OK " + message); } } } } @Override public void sessionClosed(IoSession session) throws Exception { String user = (String) session.getAttribute("user"); users.remove(user); sessions.remove(session); broadcast("The user " + user + " has left the chat session."); } public boolean isChatUser(String name) { return users.contains(name); } public int getNumberOfUsers() { return users.size(); } public void kick(String name) { synchronized (sessions) { for (IoSession session : sessions) { if (name.equals(session.getAttribute("user"))) { session.close(true); break; } } } } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/Main.java0000644000175000017500000000564112032276035027660 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.chat; import java.net.InetSocketAddress; import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; import org.apache.mina.example.echoserver.ssl.BogusSslContextFactory; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.filter.logging.MdcInjectionFilter; import org.apache.mina.filter.ssl.SslFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; /** * (Entry point) Chat server * * @author Apache MINA Project */ public class Main { /** Choose your favorite port number. */ private static final int PORT = 1234; /** Set this to true if you want to make the server SSL */ private static final boolean USE_SSL = false; public static void main(String[] args) throws Exception { NioSocketAcceptor acceptor = new NioSocketAcceptor(); DefaultIoFilterChainBuilder chain = acceptor.getFilterChain(); MdcInjectionFilter mdcInjectionFilter = new MdcInjectionFilter(); chain.addLast("mdc", mdcInjectionFilter); // Add SSL filter if SSL is enabled. if (USE_SSL) { addSSLSupport(chain); } chain.addLast("codec", new ProtocolCodecFilter( new TextLineCodecFactory())); addLogger(chain); // Bind acceptor.setHandler(new ChatProtocolHandler()); acceptor.bind(new InetSocketAddress(PORT)); System.out.println("Listening on port " + PORT); } private static void addSSLSupport(DefaultIoFilterChainBuilder chain) throws Exception { SslFilter sslFilter = new SslFilter(BogusSslContextFactory .getInstance(true)); chain.addLast("sslFilter", sslFilter); System.out.println("SSL ON"); } private static void addLogger(DefaultIoFilterChainBuilder chain) throws Exception { chain.addLast("logger", new LoggingFilter()); System.out.println("Logging ON"); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/package.html0000644000175000017500000000167612032276035030416 0ustar ebourgebourg Chat server which demonstates using the text line codec and Spring integration. mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/SpringMain.java0000644000175000017500000000355412032276035031044 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.chat; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.ConfigurableApplicationContext; /** * (Entry point) Chat server which uses Spring and the serverContext.xml * file to set up MINA and the server handler. * * @author Apache MINA Project */ public class SpringMain { public static void main(String[] args) throws Exception { if (System.getProperty("com.sun.management.jmxremote") != null) { System.out.println("JMX enabled."); } else { System.out .println("JMX disabled. Please set the " + "'com.sun.management.jmxremote' system property to enable JMX."); } getApplicationContext(); System.out.println("Listening ..."); } public static ConfigurableApplicationContext getApplicationContext() { return new ClassPathXmlApplicationContext("org/apache/mina/example/chat/serverContext.xml"); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/chat/ChatCommand.java0000644000175000017500000000335712032276035031154 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.chat; /** * Encapsulates a chat command. Use {@link #valueOf(String)} to create an * instance given a command string. * * @author Apache MINA Project */ public class ChatCommand { public static final int LOGIN = 0; public static final int QUIT = 1; public static final int BROADCAST = 2; private final int num; private ChatCommand(int num) { this.num = num; } public int toInt() { return num; } public static ChatCommand valueOf(String s) { s = s.toUpperCase(); if ("LOGIN".equals(s)) { return new ChatCommand(LOGIN); } if ("QUIT".equals(s)) { return new ChatCommand(QUIT); } if ("BROADCAST".equals(s)) { return new ChatCommand(BROADCAST); } throw new IllegalArgumentException("Unrecognized command: " + s); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tcp/0000755000175000017500000000000012032276036025773 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tcp/perf/0000755000175000017500000000000012162575507026740 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tcp/perf/TcpClient.java0000644000175000017500000001053312032276036031461 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tcp.perf; import java.net.InetSocketAddress; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.transport.socket.SocketSessionConfig; import org.apache.mina.transport.socket.nio.NioSocketConnector; /** * An UDP client taht just send thousands of small messages to a UdpServer. * * This class is used for performance test purposes. It does nothing at all, but send a message * repetitly to a server. * * @author Apache MINA Project */ public class TcpClient extends IoHandlerAdapter { /** The connector */ private IoConnector connector; /** The session */ private static IoSession session; private boolean received = false; /** * Create the UdpClient's instance */ public TcpClient() { connector = new NioSocketConnector(); connector.setHandler(this); SocketSessionConfig dcfg = (SocketSessionConfig) connector.getSessionConfig(); ConnectFuture connFuture = connector.connect(new InetSocketAddress("localhost", TcpServer.PORT)); connFuture.awaitUninterruptibly(); session = connFuture.getSession(); } /** * {@inheritDoc} */ @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { cause.printStackTrace(); } /** * {@inheritDoc} */ @Override public void messageReceived(IoSession session, Object message) throws Exception { received = true; } /** * {@inheritDoc} */ @Override public void messageSent(IoSession session, Object message) throws Exception { } /** * {@inheritDoc} */ @Override public void sessionClosed(IoSession session) throws Exception { } /** * {@inheritDoc} */ @Override public void sessionCreated(IoSession session) throws Exception { } /** * {@inheritDoc} */ @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { } /** * {@inheritDoc} */ @Override public void sessionOpened(IoSession session) throws Exception { } /** * The main method : instanciates a client, and send N messages. We sleep * between each K messages sent, to avoid the server saturation. * @param args * @throws Exception */ public static void main(String[] args) throws Exception { TcpClient client = new TcpClient(); long t0 = System.currentTimeMillis(); for (int i = 0; i <= TcpServer.MAX_RECEIVED; i++) { //if (i % 2 == 0) { //Thread.sleep(1); //} IoBuffer buffer = IoBuffer.allocate(4); buffer.putInt(i); buffer.flip(); WriteFuture future = session.write(buffer); while (client.received == false) { Thread.sleep(1); } client.received = false; if (i % 10000 == 0) { System.out.println("Sent " + i + " messages"); } } long t1 = System.currentTimeMillis(); System.out.println("Sent messages delay : " + (t1 - t0)); Thread.sleep(100000); client.connector.dispose(true); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tcp/perf/TcpServer.java0000644000175000017500000001063312032276036031512 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tcp.perf; import java.io.IOException; import java.net.InetSocketAddress; import java.util.concurrent.atomic.AtomicInteger; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.transport.socket.SocketSessionConfig; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; /** * An TCP server used for performance tests. * * It does nothing fancy, except receiving the messages, and counting the number of * received messages. * * @author Apache MINA Project */ public class TcpServer extends IoHandlerAdapter { /** The listening port (check that it's not already in use) */ public static final int PORT = 18567; /** The number of message to receive */ public static final int MAX_RECEIVED = 100000; /** The starting point, set when we receive the first message */ private static long t0; /** A counter incremented for every recieved message */ private AtomicInteger nbReceived = new AtomicInteger(0); /** * {@inheritDoc} */ @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { cause.printStackTrace(); session.close(true); } /** * {@inheritDoc} */ @Override public void messageReceived(IoSession session, Object message) throws Exception { int nb = nbReceived.incrementAndGet(); if (nb == 1) { t0 = System.currentTimeMillis(); } if (nb == MAX_RECEIVED) { long t1 = System.currentTimeMillis(); System.out.println("-------------> end " + (t1 - t0)); } if (nb % 10000 == 0) { System.out.println("Received " + nb + " messages"); } //System.out.println("Message : " + ((IoBuffer) message).getInt()); //((IoBuffer) message).flip(); // If we want to test the write operation, uncomment this line session.write(message); } /** * {@inheritDoc} */ @Override public void sessionClosed(IoSession session) throws Exception { System.out.println("Session closed..."); // Reinitialize the counter and expose the number of received messages System.out.println("Nb message received : " + nbReceived.get()); nbReceived.set(0); } /** * {@inheritDoc} */ @Override public void sessionCreated(IoSession session) throws Exception { System.out.println("Session created..."); } /** * {@inheritDoc} */ @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { System.out.println("Session idle..."); } /** * {@inheritDoc} */ @Override public void sessionOpened(IoSession session) throws Exception { System.out.println("Session Opened..."); } /** * Create the TCP server */ public TcpServer() throws IOException { NioSocketAcceptor acceptor = new NioSocketAcceptor(); acceptor.setHandler(this); // The logger, if needed. Commented atm //DefaultIoFilterChainBuilder chain = acceptor.getFilterChain(); //chain.addLast("logger", new LoggingFilter()); SocketSessionConfig scfg = acceptor.getSessionConfig(); acceptor.bind(new InetSocketAddress(PORT)); System.out.println("Server started..."); } /** * The entry point. */ public static void main(String[] args) throws IOException { new TcpServer(); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/0000755000175000017500000000000012162575507026776 5ustar ebourgebourg././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/AuthenticationHandler.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/AuthenticationHandl0000644000175000017500000001523612032276036032645 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tapedeck; import static org.apache.mina.statemachine.event.IoFilterEvents.*; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.session.IoSession; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.example.tapedeck.TapeDeckServer.TapeDeckContext; import org.apache.mina.statemachine.StateControl; import org.apache.mina.statemachine.annotation.IoFilterTransition; import org.apache.mina.statemachine.annotation.State; import org.apache.mina.statemachine.context.AbstractStateContext; /** * TODO Add documentation * * @author Apache MINA Project */ public class AuthenticationHandler { @State public static final String ROOT = "Root"; @State(ROOT) public static final String START = "Start"; @State(ROOT) public static final String WAIT_USER = "WaitUser"; @State(ROOT) public static final String WAIT_PASSWORD = "WaitPassword"; @State(ROOT) public static final String DONE = "Done"; @State(ROOT) public static final String FAILED = "Failed"; static class AuthenticationContext extends AbstractStateContext { public String user; public String password; public int tries = 0; } @IoFilterTransition(on = SESSION_OPENED, in = START, next = WAIT_USER) public void sendAuthRequest(NextFilter nextFilter, IoSession session) { session.write("+ Greetings from your tape deck!. Please authenticate yourself."); } @IoFilterTransition(on = MESSAGE_RECEIVED, in = WAIT_USER, next = WAIT_PASSWORD) public void user(AuthenticationContext context, NextFilter nextFilter, IoSession session, UserCommand cmd) { context.user = cmd.getUsername(); session.write("+ Give me your password (hint: try your username backwards)"); } @IoFilterTransition(on = MESSAGE_RECEIVED, in = WAIT_PASSWORD, next = DONE) public void password(AuthenticationContext context, NextFilter nextFilter, IoSession session, PasswordCommand cmd) { context.password = cmd.getPassword(); if (context.password.equals(reverse(context.user))) { session.write("+ Authentication succeeded! Your tape deck has been unlocked."); } else { context.tries++; if (context.tries < 3) { session.write("- Authentication failed! Please try again."); StateControl.breakAndGotoNext(WAIT_USER); } else { session.write("- Authentication failed too many times! Bye bye.").addListener(IoFutureListener.CLOSE); StateControl.breakAndGotoNext(FAILED); } } } @IoFilterTransition(on = MESSAGE_RECEIVED, in = ROOT) public void quit(TapeDeckContext context, IoSession session, QuitCommand cmd) { session.write("+ Bye! Please come back!").addListener(IoFutureListener.CLOSE); } private String reverse(String s) { char[] expectedPassword = new char[s.length()]; for (int i = 0; i < expectedPassword.length; i++) { expectedPassword[i] = s.charAt(s.length() - i - 1); } return new String(expectedPassword); } @IoFilterTransition(on = MESSAGE_RECEIVED, in = WAIT_USER, weight = 10) public void errorWaitingForUser(IoSession session, Command cmd) { if (cmd instanceof QuitCommand) { StateControl.breakAndContinue(); } session.write("Unexpected command '" + cmd.getName() + "'. Expected 'user '."); } @IoFilterTransition(on = MESSAGE_RECEIVED, in = WAIT_PASSWORD, weight = 10) public void errorWaitingForPassword(IoSession session, Command cmd) { if (cmd instanceof QuitCommand) { StateControl.breakAndContinue(); } session.write("Unexpected command '" + cmd.getName() + "'. Expected 'password '."); } @IoFilterTransition(on = EXCEPTION_CAUGHT, in = ROOT) public void commandSyntaxError(IoSession session, CommandSyntaxException e) { session.write("- " + e.getMessage()); } @IoFilterTransition(on = EXCEPTION_CAUGHT, in = ROOT, weight = 10) public void exceptionCaught(IoSession session, Exception e) { e.printStackTrace(); session.close(true); } // // @IoFilterTransition(on = SESSION_CREATED, in = ROOT) // public void sessionCreated(NextFilter nextFilter, IoSession session) { // nextFilter.sessionCreated(session); // } // @IoFilterTransition(on = SESSION_OPENED, in = ROOT) // public void sessionOpened(NextFilter nextFilter, IoSession session) { // nextFilter.sessionOpened(session); // } @IoFilterTransition(on = SESSION_CLOSED, in = DONE) public void sessionClosed(NextFilter nextFilter, IoSession session) { nextFilter.sessionClosed(session); } @IoFilterTransition(on = EXCEPTION_CAUGHT, in = DONE) public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) { nextFilter.exceptionCaught(session, cause); } @IoFilterTransition(on = MESSAGE_RECEIVED, in = DONE) public void messageReceived(NextFilter nextFilter, IoSession session, Object message) { nextFilter.messageReceived(session, message); } @IoFilterTransition(on = MESSAGE_SENT, in = DONE) public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) { nextFilter.messageSent(session, writeRequest); } @IoFilterTransition(on = CLOSE, in = ROOT) public void filterClose(NextFilter nextFilter, IoSession session) { nextFilter.filterClose(session); } @IoFilterTransition(on = WRITE, in = ROOT) public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) { nextFilter.filterWrite(session, writeRequest); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/Command.java0000644000175000017500000000205312032276036031206 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tapedeck; /** * The base class of all {@link Command} types. * * @author Apache MINA Project */ public abstract class Command { public abstract String getName(); } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/LoadCommand.java0000644000175000017500000000252412032276036032011 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tapedeck; /** * Represents the load <tape> command. * * @author Apache MINA Project */ public class LoadCommand extends Command { public static final String NAME = "load"; private final int tapeNumber; public LoadCommand(int tapeNumber) { this.tapeNumber = tapeNumber; } public int getTapeNumber() { return tapeNumber; } @Override public String getName() { return NAME; } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/ListCommand.java0000644000175000017500000000220712032276036032043 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tapedeck; /** * Represents the list command. * * @author Apache MINA Project */ public class ListCommand extends Command { public static final String NAME = "list"; @Override public String getName() { return NAME; } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/PauseCommand.java0000644000175000017500000000220612032276036032204 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tapedeck; /** * Represents the pause command. * * @author Apache MINA Project */ public class PauseCommand extends Command { public static final String NAME = "pause"; @Override public String getName() { return NAME; } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/CommandSyntaxException.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/CommandSyntaxExcept0000644000175000017500000000272712032276036032656 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tapedeck; import org.apache.mina.filter.codec.ProtocolDecoderException; /** * Exception thrown by {@link CommandDecoder} when a line cannot be decoded as * a {@link Command} object. * * @author Apache MINA Project */ public class CommandSyntaxException extends ProtocolDecoderException { private static final long serialVersionUID = 4903547501059093765L; private final String message; public CommandSyntaxException(String message) { super(message); this.message = message; } @Override public String getMessage() { return message; } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/CommandDecoder.java0000644000175000017500000000762612032276036032507 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tapedeck; import java.nio.charset.Charset; import java.util.LinkedList; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter.NextFilter; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import org.apache.mina.filter.codec.textline.LineDelimiter; import org.apache.mina.filter.codec.textline.TextLineDecoder; /** * MINA {@link ProtocolDecoder} which decodes bytes into {@link Command} * objects. * * @author Apache MINA Project */ public class CommandDecoder extends TextLineDecoder { public CommandDecoder() { super(Charset.forName("UTF8"), LineDelimiter.WINDOWS); } private Object parseCommand(String line) throws CommandSyntaxException { String[] temp = line.split(" +", 2); String cmd = temp[0].toLowerCase(); String arg = temp.length > 1 ? temp[1] : null; if (LoadCommand.NAME.equals(cmd)) { if (arg == null) { throw new CommandSyntaxException("No tape number specified"); } try { return new LoadCommand(Integer.parseInt(arg)); } catch (NumberFormatException nfe) { throw new CommandSyntaxException("Illegal tape number: " + arg); } } else if (PlayCommand.NAME.equals(cmd)) { return new PlayCommand(); } else if (PauseCommand.NAME.equals(cmd)) { return new PauseCommand(); } else if (StopCommand.NAME.equals(cmd)) { return new StopCommand(); } else if (ListCommand.NAME.equals(cmd)) { return new ListCommand(); } else if (EjectCommand.NAME.equals(cmd)) { return new EjectCommand(); } else if (QuitCommand.NAME.equals(cmd)) { return new QuitCommand(); } else if (InfoCommand.NAME.equals(cmd)) { return new InfoCommand(); } else if (UserCommand.NAME.equals(cmd)) { if (arg == null) { throw new CommandSyntaxException("No username specified"); } return new UserCommand(arg); } else if (PasswordCommand.NAME.equals(cmd)) { if (arg == null) { throw new CommandSyntaxException("No password specified"); } return new PasswordCommand(arg); } throw new CommandSyntaxException("Unknown command: " + cmd); } @Override public void decode(IoSession session, IoBuffer in, final ProtocolDecoderOutput out) throws Exception { final LinkedList lines = new LinkedList(); super.decode(session, in, new ProtocolDecoderOutput() { public void write(Object message) { lines.add((String) message); } public void flush(NextFilter nextFilter, IoSession session) {} }); for (String s: lines) { out.write(parseCommand(s)); } } }mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/QuitCommand.java0000644000175000017500000000220712032276036032052 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tapedeck; /** * Represents the quit command. * * @author Apache MINA Project */ public class QuitCommand extends Command { public static final String NAME = "quit"; @Override public String getName() { return NAME; } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/UserCommand.java0000644000175000017500000000252512032276036032051 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tapedeck; /** * Represents the user <username> command. * * @author Apache MINA Project */ public class UserCommand extends Command { public static final String NAME = "user"; private final String username; public UserCommand(String username) { this.username = username; } public String getUsername() { return username; } @Override public String getName() { return NAME; } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/StopCommand.java0000644000175000017500000000220312032276036032051 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tapedeck; /** * Represents the stop command. * * @author Apache MINA Project */ public class StopCommand extends Command { public static final String NAME = "stop"; @Override public String getName() { return NAME; } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/PlayCommand.java0000644000175000017500000000220312032276036032031 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tapedeck; /** * Represents the play command. * * @author Apache MINA Project */ public class PlayCommand extends Command { public static final String NAME = "play"; @Override public String getName() { return NAME; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/PasswordCommand.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/PasswordCommand.jav0000644000175000017500000000254512032276036032576 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tapedeck; /** * Represents the password <password> command. * * @author Apache MINA Project */ public class PasswordCommand extends Command { public static final String NAME = "password"; private final String password; public PasswordCommand(String password) { this.password = password; } public String getPassword() { return password; } @Override public String getName() { return NAME; } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/Main.java0000644000175000017500000000773712032276036030532 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tapedeck; import java.net.InetSocketAddress; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.service.IoHandler; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineEncoder; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.statemachine.StateMachine; import org.apache.mina.statemachine.StateMachineFactory; import org.apache.mina.statemachine.StateMachineProxyBuilder; import org.apache.mina.statemachine.annotation.IoFilterTransition; import org.apache.mina.statemachine.annotation.IoHandlerTransition; import org.apache.mina.statemachine.context.IoSessionStateContextLookup; import org.apache.mina.statemachine.context.StateContext; import org.apache.mina.statemachine.context.StateContextFactory; import org.apache.mina.transport.socket.SocketAcceptor; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; /** * Simple example demonstrating how to build a state machine for MINA's * {@link IoHandler} interface. * * @author Apache MINA Project */ public class Main { /** Choose your favorite port number. */ private static final int PORT = 12345; private static IoHandler createIoHandler() { StateMachine sm = StateMachineFactory.getInstance( IoHandlerTransition.class).create(TapeDeckServer.EMPTY, new TapeDeckServer()); return new StateMachineProxyBuilder().setStateContextLookup( new IoSessionStateContextLookup(new StateContextFactory() { public StateContext create() { return new TapeDeckServer.TapeDeckContext(); } })).create(IoHandler.class, sm); } private static IoFilter createAuthenticationIoFilter() { StateMachine sm = StateMachineFactory.getInstance( IoFilterTransition.class).create(AuthenticationHandler.START, new AuthenticationHandler()); return new StateMachineProxyBuilder().setStateContextLookup( new IoSessionStateContextLookup(new StateContextFactory() { public StateContext create() { return new AuthenticationHandler.AuthenticationContext(); } }, "authContext")).setIgnoreUnhandledEvents(true).setIgnoreStateContextLookupFailure(true).create( IoFilter.class, sm); } public static void main(String[] args) throws Exception { SocketAcceptor acceptor = new NioSocketAcceptor(); acceptor.setReuseAddress(true); ProtocolCodecFilter pcf = new ProtocolCodecFilter( new TextLineEncoder(), new CommandDecoder()); acceptor.getFilterChain().addLast("log1", new LoggingFilter("log1")); acceptor.getFilterChain().addLast("codec", pcf); // acceptor.getFilterChain().addLast("authentication", createAuthenticationIoFilter()); acceptor.getFilterChain().addLast("log2", new LoggingFilter("log2")); acceptor.setHandler(createIoHandler()); acceptor.bind(new InetSocketAddress(PORT)); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/EjectCommand.java0000644000175000017500000000221212032276036032156 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tapedeck; /** * Represents the eject command. * * @author Apache MINA Project */ public class EjectCommand extends Command { public static final String NAME = "eject"; @Override public String getName() { return NAME; } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/TapeDeckServer.java0000644000175000017500000001366212032276036032507 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tapedeck; import static org.apache.mina.statemachine.event.IoHandlerEvents.*; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.session.IoSession; import org.apache.mina.statemachine.StateControl; import org.apache.mina.statemachine.annotation.IoHandlerTransition; import org.apache.mina.statemachine.annotation.IoHandlerTransitions; import org.apache.mina.statemachine.annotation.State; import org.apache.mina.statemachine.context.AbstractStateContext; import org.apache.mina.statemachine.context.StateContext; import org.apache.mina.statemachine.event.Event; /** * The actual state machine implementation for the tape deck server. * * @author Apache MINA Project */ public class TapeDeckServer { @State public static final String ROOT = "Root"; @State(ROOT) public static final String EMPTY = "Empty"; @State(ROOT) public static final String LOADED = "Loaded"; @State(ROOT) public static final String PLAYING = "Playing"; @State(ROOT) public static final String PAUSED = "Paused"; private final String[] tapes = { "The Knife - Silent Shout", "Kings of convenience - Riot on an empty street" }; static class TapeDeckContext extends AbstractStateContext { public String tapeName; } @IoHandlerTransition(on = SESSION_OPENED, in = EMPTY) public void connect(IoSession session) { session.write("+ Greetings from your tape deck!"); } @IoHandlerTransition(on = MESSAGE_RECEIVED, in = EMPTY, next = LOADED) public void loadTape(TapeDeckContext context, IoSession session, LoadCommand cmd) { if (cmd.getTapeNumber() < 1 || cmd.getTapeNumber() > tapes.length) { session.write("- Unknown tape number: " + cmd.getTapeNumber()); StateControl.breakAndGotoNext(EMPTY); } else { context.tapeName = tapes[cmd.getTapeNumber() - 1]; session.write("+ \"" + context.tapeName + "\" loaded"); } } @IoHandlerTransitions({ @IoHandlerTransition(on = MESSAGE_RECEIVED, in = LOADED, next = PLAYING), @IoHandlerTransition(on = MESSAGE_RECEIVED, in = PAUSED, next = PLAYING) }) public void playTape(TapeDeckContext context, IoSession session, PlayCommand cmd) { session.write("+ Playing \"" + context.tapeName + "\""); } @IoHandlerTransition(on = MESSAGE_RECEIVED, in = PLAYING, next = PAUSED) public void pauseTape(TapeDeckContext context, IoSession session, PauseCommand cmd) { session.write("+ \"" + context.tapeName + "\" paused"); } @IoHandlerTransition(on = MESSAGE_RECEIVED, in = PLAYING, next = LOADED) public void stopTape(TapeDeckContext context, IoSession session, StopCommand cmd) { session.write("+ \"" + context.tapeName + "\" stopped"); } @IoHandlerTransition(on = MESSAGE_RECEIVED, in = LOADED, next = EMPTY) public void ejectTape(TapeDeckContext context, IoSession session, EjectCommand cmd) { session.write("+ \"" + context.tapeName + "\" ejected"); context.tapeName = null; } @IoHandlerTransition(on = MESSAGE_RECEIVED, in = ROOT) public void listTapes(IoSession session, ListCommand cmd) { StringBuilder response = new StringBuilder("+ ("); for (int i = 0; i < tapes.length; i++) { response.append(i + 1).append(": "); response.append('"').append(tapes[i]).append('"'); if (i < tapes.length - 1) { response.append(", "); } } response.append(')'); session.write(response); } @IoHandlerTransition(on = MESSAGE_RECEIVED, in = ROOT) public void info(TapeDeckContext context, IoSession session, InfoCommand cmd) { String state = context.getCurrentState().getId().toLowerCase(); if (context.tapeName == null) { session.write("+ Tape deck is " + state + ""); } else { session.write("+ Tape deck is " + state + ". Current tape: \"" + context.tapeName + "\""); } } @IoHandlerTransition(on = MESSAGE_RECEIVED, in = ROOT) public void quit(TapeDeckContext context, IoSession session, QuitCommand cmd) { session.write("+ Bye! Please come back!").addListener(IoFutureListener.CLOSE); } @IoHandlerTransition(on = MESSAGE_RECEIVED, in = ROOT, weight = 10) public void error(Event event, StateContext context, IoSession session, Command cmd) { session.write("- Cannot " + cmd.getName() + " while " + context.getCurrentState().getId().toLowerCase()); } @IoHandlerTransition(on = EXCEPTION_CAUGHT, in = ROOT) public void commandSyntaxError(IoSession session, CommandSyntaxException e) { session.write("- " + e.getMessage()); } @IoHandlerTransition(on = EXCEPTION_CAUGHT, in = ROOT, weight = 10) public void exceptionCaught(IoSession session, Exception e) { e.printStackTrace(); session.close(true); } @IoHandlerTransition(in = ROOT, weight = 100) public void unhandledEvent() { } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/tapedeck/InfoCommand.java0000644000175000017500000000220712032276036032023 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.tapedeck; /** * Represents the info command. * * @author Apache MINA Project */ public class InfoCommand extends Command { public static final String NAME = "info"; @Override public String getName() { return NAME; } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/0000755000175000017500000000000012032276037026617 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step3/0000755000175000017500000000000012032276037027655 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step3/server/0000755000175000017500000000000012162575507031173 5ustar ebourgebourg././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step3/server/ImageServerIoHandler.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step3/server/ImageSe0000644000175000017500000001525212032276037032425 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.imagine.step3.server; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import javax.management.MBeanServer; import javax.management.ObjectName; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.imagine.step1.ImageRequest; import org.apache.mina.example.imagine.step1.ImageResponse; import org.apache.mina.integration.jmx.IoSessionMBean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * server-side {@link org.apache.mina.core.service.IoHandler} * * @author Apache MINA Project */ public class ImageServerIoHandler extends IoHandlerAdapter { private final static String characters = "mina rocks abcdefghijklmnopqrstuvwxyz0123456789"; public static final String INDEX_KEY = ImageServerIoHandler.class.getName() + ".INDEX"; private static Logger LOGGER = LoggerFactory.getLogger(ImageServerIoHandler.class); private MBeanServer mBeanServer; /** * Creates a new instance of ImageServerIoHandler. For this step, we pass in a reference * to the MBeanServer. This instance will be used to register new IoSession objects * so that the JMX subsystem can report statistics on the sessions. * * @param mBeanServer * The JMX MBeanServer that will register the sessions */ public ImageServerIoHandler( MBeanServer mBeanServer ) { this.mBeanServer = mBeanServer; } /** * This method is called first when a new connection to the server is made. In here we will set * up the JMX session MBean. * * @see org.apache.mina.core.service.IoHandlerAdapter#sessionCreated(org.apache.mina.core.session.IoSession) */ public void sessionCreated( IoSession session ) throws Exception { // create a session MBean in order to load into the MBeanServer and allow // this session to be managed by the JMX subsystem. IoSessionMBean sessionMBean = new IoSessionMBean( session ); // create a JMX ObjectName. This has to be in a specific format. ObjectName sessionName = new ObjectName( session.getClass().getPackage().getName() + ":type=session,name=" + session.getClass().getSimpleName() + "-" + session.getId()); // register the bean on the MBeanServer. Without this line, no JMX will happen for // this session mBeanServer.registerMBean( sessionMBean, sessionName ); } /** * Called when the session is opened, which will come after the session created. * * @see org.apache.mina.core.service.IoHandlerAdapter#sessionOpened(org.apache.mina.core.session.IoSession) */ public void sessionOpened(IoSession session) throws Exception { // set the index to zero. This is used to determine how the build the // string that is sent to the client. session.setAttribute(INDEX_KEY, 0); } /** * This method will be called whenever an exception occurs. For this handler, * the logger will generate a warning message. * * @see org.apache.mina.core.service.IoHandlerAdapter#exceptionCaught(org.apache.mina.core.session.IoSession, java.lang.Throwable) */ public void exceptionCaught(IoSession session, Throwable cause) throws Exception { LOGGER.warn(cause.getMessage(), cause); } /** * Handle incoming messages. * * @see org.apache.mina.core.service.IoHandlerAdapter#messageReceived(org.apache.mina.core.session.IoSession, java.lang.Object) */ public void messageReceived(IoSession session, Object message) throws Exception { ImageRequest request = (ImageRequest) message; String text1 = generateString(session, request.getNumberOfCharacters()); String text2 = generateString(session, request.getNumberOfCharacters()); BufferedImage image1 = createImage(request, text1); BufferedImage image2 = createImage(request, text2); ImageResponse response = new ImageResponse(image1, image2); session.write(response); } /** * Create an image using the specified request and the text. * * @param request * Determines the height and width of the image * @param text * The text that is placed in the image * @return * a BufferedImage representing the text. */ private BufferedImage createImage(ImageRequest request, String text) { BufferedImage image = new BufferedImage(request.getWidth(), request.getHeight(), BufferedImage.TYPE_BYTE_INDEXED); Graphics graphics = image.createGraphics(); graphics.setColor(Color.YELLOW); graphics.fillRect(0, 0, image.getWidth(), image.getHeight()); Font serif = new Font("serif", Font.PLAIN, 30); graphics.setFont(serif); graphics.setColor(Color.BLUE); graphics.drawString(text, 10, 50); return image; } /** * Generate a string based on the 'characters' field in this class. The * characters that make up the string are based on the session * attribute "INDEX_KEY" * * @param session * The {@link IoSession} object that will provide the INDEX_KEY attribute * @param length * The length that the String will be * @return * The generated String */ private String generateString(IoSession session, int length) { Integer index = (Integer) session.getAttribute(INDEX_KEY); StringBuilder buffer = new StringBuilder(length); while (buffer.length() < length) { buffer.append(characters.charAt(index)); index++; if (index >= characters.length()) { index = 0; } } session.setAttribute(INDEX_KEY, index); return buffer.toString(); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step3/server/ImageServer.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step3/server/ImageSe0000644000175000017500000001160712032276037032425 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.imagine.step3.server; import java.lang.management.ManagementFactory; import java.net.InetSocketAddress; import java.util.concurrent.Executors; import javax.management.MBeanServer; import javax.management.ObjectName; import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; import org.apache.mina.example.imagine.step1.codec.ImageCodecFactory; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.executor.ExecutorFilter; import org.apache.mina.integration.jmx.IoFilterMBean; import org.apache.mina.integration.jmx.IoServiceMBean; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; /** * entry point for the server used in the tutorial on protocol codecs * * @author Apache MINA Project */ public class ImageServer { public static final int PORT = 33789; public static void main(String[] args) throws Exception { // create a JMX MBean Server server instance MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); // Create a class that handles sessions, incoming and outgoing data. For // this step, we will pass in the MBeanServer so that sessions can be // registered on the MBeanServer. ImageServerIoHandler handler = new ImageServerIoHandler( mBeanServer ); // This socket acceptor will handle incoming connections NioSocketAcceptor acceptor = new NioSocketAcceptor(); // create a JMX-aware bean that wraps a MINA IoService object. In this // case, a NioSocketAcceptor. IoServiceMBean acceptorMBean = new IoServiceMBean( acceptor ); // create a JMX ObjectName. This has to be in a specific format. ObjectName acceptorName = new ObjectName( acceptor.getClass().getPackage().getName() + ":type=acceptor,name=" + acceptor.getClass().getSimpleName()); // register the bean on the MBeanServer. Without this line, no JMX will happen for // this acceptor. mBeanServer.registerMBean( acceptorMBean, acceptorName ); // add an IoFilter . This class is responsible for converting the incoming and // outgoing raw data to ImageRequest and ImageResponse objects ProtocolCodecFilter protocolFilter = new ProtocolCodecFilter(new ImageCodecFactory(false)); // create a JMX-aware bean that wraps a MINA IoFilter object. In this // case, a ProtocolCodecFilter IoFilterMBean protocolFilterMBean = new IoFilterMBean( protocolFilter ); // create a JMX ObjectName. ObjectName protocolFilterName = new ObjectName( protocolFilter.getClass().getPackage().getName() + ":type=protocolfilter,name=" + protocolFilter.getClass().getSimpleName() ); // register the bean on the MBeanServer. Without this line, no JMX will happen for // this filter. mBeanServer.registerMBean( protocolFilterMBean, protocolFilterName ); // add the protocolFilter to the acceptor, otherwise no filtering of data will happen acceptor.getFilterChain().addLast("protocol", protocolFilter); // get a reference to the filter chain from the acceptor DefaultIoFilterChainBuilder filterChainBuilder = acceptor.getFilterChain(); // add an ExecutorFilter to the filter chain. The preferred order is to put the executor filter // after any protocol filters due to the fact that protocol codecs are generally CPU-bound // which is the same as I/O filters. filterChainBuilder.addLast("threadPool", new ExecutorFilter(Executors.newCachedThreadPool())); // set this NioSocketAcceptor's handler to the ImageServerHandler acceptor.setHandler(handler); // Bind to the specified address. This kicks off the listening for // incoming connections acceptor.bind(new InetSocketAddress(PORT)); System.out.println("Step 3 server is listenig at port " + PORT); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step2/0000755000175000017500000000000012032276037027654 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step2/server/0000755000175000017500000000000012162575507031172 5ustar ebourgebourg././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step2/server/ImageServer.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step2/server/ImageSe0000644000175000017500000000605712032276037032427 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.imagine.step2.server; import java.io.IOException; import java.net.InetSocketAddress; import java.util.concurrent.Executors; import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; import org.apache.mina.example.imagine.step1.codec.ImageCodecFactory; import org.apache.mina.example.imagine.step1.server.ImageServerIoHandler; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.executor.ExecutorFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; /** * entry point for the server used in the tutorial on protocol codecs * * @author Apache MINA Project */ public class ImageServer { public static final int PORT = 33789; public static void main(String[] args) throws IOException { // Create a class that handles sessions, incoming and outgoing data ImageServerIoHandler handler = new ImageServerIoHandler(); // This socket acceptor will handle incoming connections NioSocketAcceptor acceptor = new NioSocketAcceptor(); // add an IoFilter . This class is responsible for converting the incoming and // outgoing raw data to ImageRequest and ImageResponse objects acceptor.getFilterChain().addLast("protocol", new ProtocolCodecFilter(new ImageCodecFactory(false))); // get a reference to the filter chain from the acceptor DefaultIoFilterChainBuilder filterChainBuilder = acceptor.getFilterChain(); // add an ExecutorFilter to the filter chain. The preferred order is to put the executor filter // after any protocol filters due to the fact that protocol codecs are generally CPU-bound // which is the same as I/O filters. filterChainBuilder.addLast("threadPool", new ExecutorFilter(Executors.newCachedThreadPool())); // set this NioSocketAcceptor's handler to the ImageServerHandler acceptor.setHandler(handler); // Bind to the specified address. This kicks off the listening for // incoming connections acceptor.bind(new InetSocketAddress(PORT)); System.out.println("Step 2 server is listenig at port " + PORT); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/0000755000175000017500000000000012162575507027663 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/client/0000755000175000017500000000000012162575507031141 5ustar ebourgebourg././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/client/ImageListener.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/client/ImageLi0000644000175000017500000000232212032276037032362 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.imagine.step1.client; import java.awt.image.BufferedImage; /** * TODO Add documentation * * @author Apache MINA Project */ public interface ImageListener { void onImages(BufferedImage image1, BufferedImage image2); void onException(Throwable throwable); void sessionOpened(); void sessionClosed(); } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/client/ImageClient.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/client/ImageCl0000644000175000017500000000736312032276037032366 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.imagine.step1.client; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.imagine.step1.ImageRequest; import org.apache.mina.example.imagine.step1.ImageResponse; import org.apache.mina.example.imagine.step1.server.ImageServer; import org.apache.mina.example.imagine.step1.codec.ImageCodecFactory; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.transport.socket.SocketConnector; import org.apache.mina.transport.socket.nio.NioSocketConnector; import java.net.InetSocketAddress; /** * client for the {@link ImageServer} * * @author Apache MINA Project */ public class ImageClient extends IoHandlerAdapter { public static final int CONNECT_TIMEOUT = 3000; private String host; private int port; private SocketConnector connector; private IoSession session; private ImageListener imageListener; public ImageClient(String host, int port, ImageListener imageListener) { this.host = host; this.port = port; this.imageListener = imageListener; connector = new NioSocketConnector(); connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ImageCodecFactory(true))); connector.setHandler(this); } public boolean isConnected() { return (session != null && session.isConnected()); } public void connect() { ConnectFuture connectFuture = connector.connect(new InetSocketAddress(host, port)); connectFuture.awaitUninterruptibly(CONNECT_TIMEOUT); try { session = connectFuture.getSession(); } catch (RuntimeIoException e) { imageListener.onException(e); } } public void disconnect() { if (session != null) { session.close(true).awaitUninterruptibly(CONNECT_TIMEOUT); session = null; } } public void sessionOpened(IoSession session) throws Exception { imageListener.sessionOpened(); } public void sessionClosed(IoSession session) throws Exception { imageListener.sessionClosed(); } public void sendRequest(ImageRequest imageRequest) { if (session == null) { //noinspection ThrowableInstanceNeverThrown imageListener.onException(new Throwable("not connected")); } else { session.write(imageRequest); } } public void messageReceived(IoSession session, Object message) throws Exception { ImageResponse response = (ImageResponse) message; imageListener.onImages(response.getImage1(), response.getImage2()); } public void exceptionCaught(IoSession session, Throwable cause) throws Exception { imageListener.onException(cause); } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/client/GraphicalCharGenClient.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/client/Graphic0000644000175000017500000003075612032276037032444 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.imagine.step1.client; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JSpinner; import javax.swing.JTextField; import javax.swing.SpinnerNumberModel; import javax.swing.UIManager; import javax.swing.WindowConstants; import org.apache.mina.example.imagine.step1.ImageRequest; import org.apache.mina.example.imagine.step1.server.ImageServer; /** * Swing application that acts as a client of the {@link ImageServer} * * @author Apache MINA Project */ public class GraphicalCharGenClient extends JFrame implements ImageListener { private static final long serialVersionUID = 1L; public static final int PORT = 33789; public static final String HOST = "localhost"; public GraphicalCharGenClient() { initComponents(); jSpinnerHeight.setModel(spinnerHeightModel); jSpinnerWidth.setModel(spinnerWidthModel); jSpinnerChars.setModel(spinnerCharsModel); jTextFieldHost.setText(HOST); jTextFieldPort.setText(String.valueOf(PORT)); setTitle(""); } private void jButtonConnectActionPerformed() { try { setTitle("connecting..."); String host = jTextFieldHost.getText(); int port = Integer.valueOf(jTextFieldPort.getText()); if (imageClient != null) { imageClient.disconnect(); } imageClient = new ImageClient(host, port, this); imageClient.connect(); jButtonConnect.setEnabled(!imageClient.isConnected()); } catch (NumberFormatException e) { onException(e); } catch (IllegalArgumentException e) { onException(e); } } private void jButtonDisconnectActionPerformed() { setTitle("disconnecting"); imageClient.disconnect(); } private void jButtonSendRequestActionPerformed() { sendRequest(); } private void sendRequest() { int chars = spinnerCharsModel.getNumber().intValue(); int height = spinnerHeightModel.getNumber().intValue(); int width = spinnerWidthModel.getNumber().intValue(); imageClient.sendRequest(new ImageRequest(width, height, chars)); } public void onImages(BufferedImage image1, BufferedImage image2) { if (checkBoxContinuous.isSelected()) { // already request next image sendRequest(); } imagePanel1.setImages(image1, image2); } public void onException(Throwable throwable) { Throwable cause = throwable; while (cause.getCause() != null) { cause = cause.getCause(); } JOptionPane.showMessageDialog( this, cause.getMessage(), throwable.getMessage(), JOptionPane.ERROR_MESSAGE); setTitle(""); jButtonConnect.setEnabled(!imageClient.isConnected()); jButtonDisconnect.setEnabled(imageClient.isConnected()); } public void sessionOpened() { jButtonDisconnect.setEnabled(true); jButtonSendRequest.setEnabled(true); jButtonConnect.setEnabled(false); setTitle("connected"); } public void sessionClosed() { jButtonDisconnect.setEnabled(false); jButtonSendRequest.setEnabled(false); jButtonConnect.setEnabled(true); setTitle("not connected"); } @Override public void setTitle(String title) { super.setTitle("MINA - Chargen client - " + title); } private void initComponents() { JLabel jLabel1 = new JLabel(); jTextFieldHost = new JTextField(); jButtonConnect = new JButton(); JLabel jLabel3 = new JLabel(); jSpinnerWidth = new JSpinner(); JLabel label5 = new JLabel(); jSpinnerChars = new JSpinner(); checkBoxContinuous = new JCheckBox(); JLabel jLabel2 = new JLabel(); jTextFieldPort = new JTextField(); jButtonDisconnect = new JButton(); JLabel jLabel4 = new JLabel(); jSpinnerHeight = new JSpinner(); jButtonSendRequest = new JButton(); imagePanel1 = new ImagePanel(); //======== this ======== setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setMinimumSize(new Dimension(700, 300)); setPreferredSize(new Dimension(740, 600)); Container contentPane = getContentPane(); contentPane.setLayout(new GridBagLayout()); ((GridBagLayout) contentPane.getLayout()).columnWidths = new int[]{36, 167, 99, 41, 66, 75, 57, 96, 0, 0}; ((GridBagLayout) contentPane.getLayout()).rowHeights = new int[]{10, 31, 31, 256, 0}; ((GridBagLayout) contentPane.getLayout()).columnWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0E-4}; ((GridBagLayout) contentPane.getLayout()).rowWeights = new double[]{0.0, 0.0, 0.0, 1.0, 1.0E-4}; //---- jLabel1 ---- jLabel1.setText("Host"); contentPane.add(jLabel1, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 5, 5), 0, 0)); contentPane.add(jTextFieldHost, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 5, 10), 0, 0)); //---- jButtonConnect ---- jButtonConnect.setText("Connect"); jButtonConnect.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { jButtonConnectActionPerformed(); } }); contentPane.add(jButtonConnect, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 5, 10), 0, 0)); //---- jLabel3 ---- jLabel3.setText("Width"); contentPane.add(jLabel3, new GridBagConstraints(3, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 5, 5), 0, 0)); contentPane.add(jSpinnerWidth, new GridBagConstraints(4, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 5, 10), 0, 0)); //---- label5 ---- label5.setText("characters"); contentPane.add(label5, new GridBagConstraints(5, 1, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.VERTICAL, new Insets(0, 0, 5, 5), 0, 0)); contentPane.add(jSpinnerChars, new GridBagConstraints(6, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 5, 10), 0, 0)); //---- checkBoxContinuous ---- checkBoxContinuous.setText("continuous"); contentPane.add(checkBoxContinuous, new GridBagConstraints(7, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 5, 10), 0, 0)); //---- jLabel2 ---- jLabel2.setText("Port"); contentPane.add(jLabel2, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 5, 5), 0, 0)); contentPane.add(jTextFieldPort, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 5, 10), 0, 0)); //---- jButtonDisconnect ---- jButtonDisconnect.setText("Disconnect"); jButtonDisconnect.setEnabled(false); jButtonDisconnect.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { jButtonDisconnectActionPerformed(); } }); contentPane.add(jButtonDisconnect, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 5, 10), 0, 0)); //---- jLabel4 ---- jLabel4.setText("Height"); contentPane.add(jLabel4, new GridBagConstraints(3, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 5, 5), 0, 0)); contentPane.add(jSpinnerHeight, new GridBagConstraints(4, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 5, 10), 0, 0)); //---- jButtonSendRequest ---- jButtonSendRequest.setText("Send Request"); jButtonSendRequest.setEnabled(false); jButtonSendRequest.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { jButtonSendRequestActionPerformed(); } }); contentPane.add(jButtonSendRequest, new GridBagConstraints(5, 2, 2, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 5, 10), 0, 0)); //======== imagePanel1 ======== { imagePanel1.setBackground(new Color(51, 153, 255)); imagePanel1.setPreferredSize(new Dimension(500, 500)); { // compute preferred size Dimension preferredSize = new Dimension(); for (int i = 0; i < imagePanel1.getComponentCount(); i++) { Rectangle bounds = imagePanel1.getComponent(i).getBounds(); preferredSize.width = Math.max(bounds.x + bounds.width, preferredSize.width); preferredSize.height = Math.max(bounds.y + bounds.height, preferredSize.height); } Insets insets = imagePanel1.getInsets(); preferredSize.width += insets.right; preferredSize.height += insets.bottom; imagePanel1.setMinimumSize(preferredSize); imagePanel1.setPreferredSize(preferredSize); } } contentPane.add(imagePanel1, new GridBagConstraints(0, 3, 9, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(8, 5, 8, 5), 0, 0)); pack(); setLocationRelativeTo(getOwner()); } /** * @param args the command line arguments */ public static void main(String args[]) { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { // ignore } java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new GraphicalCharGenClient().setVisible(true); } }); } private JTextField jTextFieldHost; private JButton jButtonConnect; private JSpinner jSpinnerWidth; private JSpinner jSpinnerChars; private JCheckBox checkBoxContinuous; private JTextField jTextFieldPort; private JButton jButtonDisconnect; private JSpinner jSpinnerHeight; private JButton jButtonSendRequest; private ImagePanel imagePanel1; private SpinnerNumberModel spinnerHeightModel = new SpinnerNumberModel(100, 50, 600, 25); private SpinnerNumberModel spinnerWidthModel = new SpinnerNumberModel(200, 50, 1000, 25); private SpinnerNumberModel spinnerCharsModel = new SpinnerNumberModel(10, 1, 60, 1); private ImageClient imageClient = new ImageClient(HOST, PORT, this); } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/client/ImagePanel.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/client/ImagePa0000644000175000017500000000333512032276037032363 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.imagine.step1.client; import java.awt.Graphics; import java.awt.image.BufferedImage; import javax.swing.JPanel; /** * JPanel capable of drawing two {@link BufferedImage}'s * * @author Apache MINA Project */ public class ImagePanel extends JPanel { private static final long serialVersionUID = 1L; private BufferedImage image1; private BufferedImage image2; @Override public void paintComponent(Graphics g) { super.paintComponent(g); if (image1 != null) { g.drawImage(image1, 20, 20, null); if (image2 != null) { g.drawImage(image2, 20, image1.getHeight() + 80, null); } } } public void setImages(BufferedImage image1, BufferedImage image2) { this.image1 = image1; this.image2 = image2; repaint(); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/server/0000755000175000017500000000000012162575507031171 5ustar ebourgebourg././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/server/ImageServerIoHandler.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/server/ImageSe0000644000175000017500000001162612032276037032424 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.imagine.step1.server; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.imagine.step1.ImageRequest; import org.apache.mina.example.imagine.step1.ImageResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; /** * server-side {@link org.apache.mina.core.service.IoHandler} * * @author Apache MINA Project */ public class ImageServerIoHandler extends IoHandlerAdapter { private final static String characters = "mina rocks abcdefghijklmnopqrstuvwxyz0123456789"; public static final String INDEX_KEY = ImageServerIoHandler.class.getName() + ".INDEX"; private static Logger LOGGER = LoggerFactory.getLogger(ImageServerIoHandler.class); /** * Called when the session is opened, which will come after the session created. * * @see org.apache.mina.core.service.IoHandlerAdapter#sessionOpened(org.apache.mina.core.session.IoSession) */ public void sessionOpened(IoSession session) throws Exception { session.setAttribute(INDEX_KEY, 0); } /** * This method will be called whenever an exception occurs. For this handler, * the logger will generate a warning message. * * @see org.apache.mina.core.service.IoHandlerAdapter#exceptionCaught(org.apache.mina.core.session.IoSession, java.lang.Throwable) */ public void exceptionCaught(IoSession session, Throwable cause) throws Exception { LOGGER.warn(cause.getMessage(), cause); } /** * Handle incoming messages. * * @see org.apache.mina.core.service.IoHandlerAdapter#messageReceived(org.apache.mina.core.session.IoSession, java.lang.Object) */ public void messageReceived(IoSession session, Object message) throws Exception { ImageRequest request = (ImageRequest) message; String text1 = generateString(session, request.getNumberOfCharacters()); String text2 = generateString(session, request.getNumberOfCharacters()); BufferedImage image1 = createImage(request, text1); BufferedImage image2 = createImage(request, text2); ImageResponse response = new ImageResponse(image1, image2); session.write(response); } /** * Create an image using the specified request and the text. * * @param request * Determines the height and width of the image * @param text * The text that is placed in the image * @return * a BufferedImage representing the text. */ private BufferedImage createImage(ImageRequest request, String text) { BufferedImage image = new BufferedImage(request.getWidth(), request.getHeight(), BufferedImage.TYPE_BYTE_INDEXED); Graphics graphics = image.createGraphics(); graphics.setColor(Color.YELLOW); graphics.fillRect(0, 0, image.getWidth(), image.getHeight()); Font serif = new Font("serif", Font.PLAIN, 30); graphics.setFont(serif); graphics.setColor(Color.BLUE); graphics.drawString(text, 10, 50); return image; } /** * Generate a string based on the 'characters' field in this class. The * characters that make up the string are based on the session * attribute "INDEX_KEY" * * @param session * The {@link IoSession} object that will provide the INDEX_KEY attribute * @param length * The length that the String will be * @return * The generated String */ private String generateString(IoSession session, int length) { Integer index = (Integer) session.getAttribute(INDEX_KEY); StringBuffer buffer = new StringBuffer(length); while (buffer.length() < length) { buffer.append(characters.charAt(index)); index++; if (index >= characters.length()) { index = 0; } } session.setAttribute(INDEX_KEY, index); return buffer.toString(); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/server/ImageServer.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/server/ImageSe0000644000175000017500000000450412032276037032421 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.imagine.step1.server; import java.io.IOException; import java.net.InetSocketAddress; import org.apache.mina.example.imagine.step1.codec.ImageCodecFactory; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; /** * entry point for the server used in the tutorial on protocol codecs * * @author Apache MINA Project */ public class ImageServer { public static final int PORT = 33789; public static void main(String[] args) throws IOException { // Create a class that handles sessions, incoming and outgoing data ImageServerIoHandler handler = new ImageServerIoHandler(); // This socket acceptor will handle incoming connections NioSocketAcceptor acceptor = new NioSocketAcceptor(); // add an IoFilter . This class is responsible for converting the incoming and // outgoing raw data to ImageRequest and ImageResponse objects acceptor.getFilterChain().addLast("protocol", new ProtocolCodecFilter(new ImageCodecFactory(false))); // set this NioSocketAcceptor's handler to the ImageServerHandler acceptor.setHandler(handler); // Bind to the specified address. This kicks off the listening for // incoming connections acceptor.bind(new InetSocketAddress(PORT)); System.out.println("Step 1 server is listenig at port " + PORT); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/codec/0000755000175000017500000000000012162575507030740 5ustar ebourgebourg././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/codec/ImageRequestEncoder.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/codec/ImageReq0000644000175000017500000000350712032276037032352 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.imagine.step1.codec; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.imagine.step1.ImageRequest; import org.apache.mina.filter.codec.ProtocolEncoder; import org.apache.mina.filter.codec.ProtocolEncoderOutput; /** * an encoder for {@link ImageRequest} objects * * @author Apache MINA Project */ public class ImageRequestEncoder implements ProtocolEncoder { public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { ImageRequest request = (ImageRequest) message; IoBuffer buffer = IoBuffer.allocate(12, false); buffer.putInt(request.getWidth()); buffer.putInt(request.getHeight()); buffer.putInt(request.getNumberOfCharacters()); buffer.flip(); out.write(buffer); } public void dispose(IoSession session) throws Exception { // nothing to dispose } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/codec/ImageResponseEncoder.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/codec/ImageRes0000644000175000017500000000441312032276037032351 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.imagine.step1.codec; import org.apache.mina.filter.codec.ProtocolEncoderOutput; import org.apache.mina.filter.codec.ProtocolEncoderAdapter; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.imagine.step1.ImageResponse; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; /** * an encoder for {@link ImageResponse} objects * * @author Apache MINA Project */ public class ImageResponseEncoder extends ProtocolEncoderAdapter { public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { ImageResponse imageResponse = (ImageResponse) message; byte[] bytes1 = getBytes(imageResponse.getImage1()); byte[] bytes2 = getBytes(imageResponse.getImage2()); int capacity = bytes1.length + bytes2.length + 8; IoBuffer buffer = IoBuffer.allocate(capacity, false); buffer.putInt(bytes1.length); buffer.put(bytes1); buffer.putInt(bytes2.length); buffer.put(bytes2); buffer.flip(); out.write(buffer); } private byte[] getBytes(BufferedImage image) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(image, "PNG", baos); return baos.toByteArray(); } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/codec/ImageResponseDecoder.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/codec/ImageRes0000644000175000017500000000635112032276037032354 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.imagine.step1.codec; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import org.apache.mina.filter.codec.CumulativeProtocolDecoder; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.imagine.step1.ImageResponse; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.IOException; /** * a decoder for {@link ImageResponse} objects * * @author Apache MINA Project */ public class ImageResponseDecoder extends CumulativeProtocolDecoder { private static final String DECODER_STATE_KEY = ImageResponseDecoder.class.getName() + ".STATE"; public static final int MAX_IMAGE_SIZE = 5 * 1024 * 1024; private static class DecoderState { BufferedImage image1; } protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { DecoderState decoderState = (DecoderState) session.getAttribute(DECODER_STATE_KEY); if (decoderState == null) { decoderState = new DecoderState(); session.setAttribute(DECODER_STATE_KEY, decoderState); } if (decoderState.image1 == null) { // try to read first image if (in.prefixedDataAvailable(4, MAX_IMAGE_SIZE)) { decoderState.image1 = readImage(in); } else { // not enough data available to read first image return false; } } if (decoderState.image1 != null) { // try to read second image if (in.prefixedDataAvailable(4, MAX_IMAGE_SIZE)) { BufferedImage image2 = readImage(in); ImageResponse imageResponse = new ImageResponse(decoderState.image1, image2); out.write(imageResponse); decoderState.image1 = null; return true; } else { // not enough data available to read second image return false; } } return false; } private BufferedImage readImage(IoBuffer in) throws IOException { int length = in.getInt(); byte[] bytes = new byte[length]; in.get(bytes); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); return ImageIO.read(bais); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/codec/ImageCodecFactory.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/codec/ImageCod0000644000175000017500000000361112032276037032324 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.imagine.step1.codec; import org.apache.mina.filter.codec.ProtocolCodecFactory; import org.apache.mina.filter.codec.ProtocolEncoder; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.core.session.IoSession; /** * a {@link ProtocolCodecFactory} for the tutorial on how to write a protocol codec * * @author Apache MINA Project */ public class ImageCodecFactory implements ProtocolCodecFactory { private ProtocolEncoder encoder; private ProtocolDecoder decoder; public ImageCodecFactory(boolean client) { if (client) { encoder = new ImageRequestEncoder(); decoder = new ImageResponseDecoder(); } else { encoder = new ImageResponseEncoder(); decoder = new ImageRequestDecoder(); } } public ProtocolEncoder getEncoder(IoSession ioSession) throws Exception { return encoder; } public ProtocolDecoder getDecoder(IoSession ioSession) throws Exception { return decoder; } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/codec/ImageRequestDecoder.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/codec/ImageReq0000644000175000017500000000346512032276037032355 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.imagine.step1.codec; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.imagine.step1.ImageRequest; import org.apache.mina.filter.codec.CumulativeProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoderOutput; /** * a decoder for {@link ImageRequest} objects * * @author Apache MINA Project */ public class ImageRequestDecoder extends CumulativeProtocolDecoder { protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { if (in.remaining() >= 12) { int width = in.getInt(); int height = in.getInt(); int numberOfCharachters = in.getInt(); ImageRequest request = new ImageRequest(width, height, numberOfCharachters); out.write(request); return true; } else { return false; } } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/ImageRequest.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/ImageRequest.j0000644000175000017500000000275612032276037032433 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.imagine.step1; /** * represents a client's request for an image * * @author Apache MINA Project */ public class ImageRequest { private int width; private int height; private int numberOfCharacters; public ImageRequest(int width, int height, int numberOfCharacters) { this.width = width; this.height = height; this.numberOfCharacters = numberOfCharacters; } public int getWidth() { return width; } public int getHeight() { return height; } public int getNumberOfCharacters() { return numberOfCharacters; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/ImageResponse.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/imagine/step1/ImageResponse.0000644000175000017500000000265312032276037032423 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.imagine.step1; import java.awt.image.BufferedImage; /** * response sent by the server when receiving an {@link ImageRequest} * * @author Apache MINA Project */ public class ImageResponse { private BufferedImage image1; private BufferedImage image2; public ImageResponse(BufferedImage image1, BufferedImage image2) { this.image1 = image1; this.image2 = image2; } public BufferedImage getImage1() { return image1; } public BufferedImage getImage2() { return image2; } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/udp/0000755000175000017500000000000012162575507026006 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/udp/MemoryMonitor.java0000644000175000017500000000763212032276037031471 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.udp; import java.awt.BorderLayout; import java.awt.Dimension; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.concurrent.ConcurrentHashMap; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTabbedPane; import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.DatagramSessionConfig; import org.apache.mina.transport.socket.nio.NioDatagramAcceptor; /** * The class that will accept and process clients in order to properly * track the memory usage. * * @author Apache MINA Project */ public class MemoryMonitor { private static final long serialVersionUID = 1L; public static final int PORT = 18567; protected static final Dimension PANEL_SIZE = new Dimension(300, 200); private JFrame frame; private JTabbedPane tabbedPane; private ConcurrentHashMap clients; public MemoryMonitor() throws IOException { NioDatagramAcceptor acceptor = new NioDatagramAcceptor(); acceptor.setHandler(new MemoryMonitorHandler(this)); DefaultIoFilterChainBuilder chain = acceptor.getFilterChain(); chain.addLast("logger", new LoggingFilter()); DatagramSessionConfig dcfg = acceptor.getSessionConfig(); dcfg.setReuseAddress(true); frame = new JFrame("Memory monitor"); tabbedPane = new JTabbedPane(); tabbedPane.add("Welcome", createWelcomePanel()); frame.add(tabbedPane, BorderLayout.CENTER); clients = new ConcurrentHashMap(); frame.pack(); frame.setLocation(300, 300); frame.setVisible(true); acceptor.bind(new InetSocketAddress(PORT)); System.out.println("UDPServer listening on port " + PORT); } private JPanel createWelcomePanel() { JPanel panel = new JPanel(); panel.setPreferredSize(PANEL_SIZE); panel.add(new JLabel("Welcome to the Memory Monitor")); return panel; } protected void recvUpdate(SocketAddress clientAddr, long update) { ClientPanel clientPanel = clients.get(clientAddr); if (clientPanel != null) { clientPanel.updateTextField(update); } else { System.err.println("Received update from unknown client"); } } protected void addClient(SocketAddress clientAddr) { if (!containsClient(clientAddr)) { ClientPanel clientPanel = new ClientPanel(clientAddr.toString()); tabbedPane.add(clientAddr.toString(), clientPanel); clients.put(clientAddr, clientPanel); } } protected boolean containsClient(SocketAddress clientAddr) { return clients.contains(clientAddr); } protected void removeClient(SocketAddress clientAddr) { clients.remove(clientAddr); } public static void main(String[] args) throws IOException { new MemoryMonitor(); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/udp/client/0000755000175000017500000000000012162575507027264 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/udp/client/MemMonClient.java0000644000175000017500000001102712032276037032447 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.udp.client; import java.net.InetSocketAddress; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.udp.MemoryMonitor; import org.apache.mina.transport.socket.nio.NioDatagramConnector; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Sends its memory usage to the MemoryMonitor server. * * @author Apache MINA Project */ public class MemMonClient extends IoHandlerAdapter { private final static Logger LOGGER = LoggerFactory.getLogger(MemMonClient.class); private IoSession session; private IoConnector connector; /** * Default constructor. */ public MemMonClient() { LOGGER.debug("UDPClient::UDPClient"); LOGGER.debug("Created a datagram connector"); connector = new NioDatagramConnector(); LOGGER.debug("Setting the handler"); connector.setHandler(this); LOGGER.debug("About to connect to the server..."); ConnectFuture connFuture = connector.connect(new InetSocketAddress( "localhost", MemoryMonitor.PORT)); LOGGER.debug("About to wait."); connFuture.awaitUninterruptibly(); LOGGER.debug("Adding a future listener."); connFuture.addListener(new IoFutureListener() { public void operationComplete(ConnectFuture future) { if (future.isConnected()) { LOGGER.debug("...connected"); session = future.getSession(); try { sendData(); } catch (InterruptedException e) { e.printStackTrace(); } } else { LOGGER.error("Not connected...exiting"); } } }); } private void sendData() throws InterruptedException { for (int i = 0; i < 30; i++) { long free = Runtime.getRuntime().freeMemory(); IoBuffer buffer = IoBuffer.allocate(8); buffer.putLong(free); buffer.flip(); session.write(buffer); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); throw new InterruptedException(e.getMessage()); } } } @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { cause.printStackTrace(); } @Override public void messageReceived(IoSession session, Object message) throws Exception { LOGGER.debug("Session recv..."); } @Override public void messageSent(IoSession session, Object message) throws Exception { LOGGER.debug("Message sent..."); } @Override public void sessionClosed(IoSession session) throws Exception { LOGGER.debug("Session closed..."); } @Override public void sessionCreated(IoSession session) throws Exception { LOGGER.debug("Session created..."); } @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { LOGGER.debug("Session idle..."); } @Override public void sessionOpened(IoSession session) throws Exception { LOGGER.debug("Session opened..."); } public static void main(String[] args) { new MemMonClient(); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/udp/ClientPanel.java0000644000175000017500000000423012032276037031036 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.udp; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.SwingUtilities; /** * Class the represents a client connection using a JPanel * * @author Apache MINA Project */ public class ClientPanel extends JPanel { private static final long serialVersionUID = 1L; private JTextField textField; public ClientPanel(String label) { super(); setPreferredSize(MemoryMonitor.PANEL_SIZE); setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.insets = new Insets(5, 5, 5, 5); c.anchor = GridBagConstraints.CENTER; c.gridwidth = GridBagConstraints.REMAINDER; add(new JLabel(label), c); c.gridwidth = 1; add(new JLabel("Memory Used : ")); textField = new JTextField(10); textField.setEditable(false); add(textField, c); } public void updateTextField(final long val) { System.out.println("New value for textfield - " + val); SwingUtilities.invokeLater(new Runnable() { public void run() { textField.setText(String.valueOf(val)); } }); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/udp/MemoryMonitorHandler.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/udp/MemoryMonitorHandler.jav0000644000175000017500000000537612032276037032631 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.udp; import java.net.SocketAddress; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; /** * Class the extends IoHandlerAdapter in order to properly handle * connections and the data the connections send * * @author Apache MINA Project */ public class MemoryMonitorHandler extends IoHandlerAdapter { private MemoryMonitor server; public MemoryMonitorHandler(MemoryMonitor server) { this.server = server; } @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { cause.printStackTrace(); session.close(true); } @Override public void messageReceived(IoSession session, Object message) throws Exception { if (message instanceof IoBuffer) { IoBuffer buffer = (IoBuffer) message; SocketAddress remoteAddress = session.getRemoteAddress(); server.recvUpdate(remoteAddress, buffer.getLong()); } } @Override public void sessionClosed(IoSession session) throws Exception { System.out.println("Session closed..."); SocketAddress remoteAddress = session.getRemoteAddress(); server.removeClient(remoteAddress); } @Override public void sessionCreated(IoSession session) throws Exception { System.out.println("Session created..."); SocketAddress remoteAddress = session.getRemoteAddress(); server.addClient(remoteAddress); } @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { System.out.println("Session idle..."); } @Override public void sessionOpened(IoSession session) throws Exception { System.out.println("Session Opened..."); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/udp/perf/0000755000175000017500000000000012162575507026742 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/udp/perf/UdpServer.java0000644000175000017500000001046012032276037031515 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.udp.perf; import java.io.IOException; import java.net.InetSocketAddress; import java.util.concurrent.atomic.AtomicInteger; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.transport.socket.DatagramSessionConfig; import org.apache.mina.transport.socket.nio.NioDatagramAcceptor; /** * An UDP server used for performance tests. * * It does nothing fancy, except receiving the messages, and counting the number of * received messages. * * @author Apache MINA Project */ public class UdpServer extends IoHandlerAdapter { /** The listening port (check that it's not already in use) */ public static final int PORT = 18567; /** The number of message to receive */ public static final int MAX_RECEIVED = 100000; /** The starting point, set when we receive the first message */ private static long t0; /** A counter incremented for every recieved message */ private AtomicInteger nbReceived = new AtomicInteger(0); /** * {@inheritDoc} */ @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { cause.printStackTrace(); session.close(true); } /** * {@inheritDoc} */ @Override public void messageReceived(IoSession session, Object message) throws Exception { int nb = nbReceived.incrementAndGet(); if (nb == 1) { t0 = System.currentTimeMillis(); } if (nb == MAX_RECEIVED) { long t1 = System.currentTimeMillis(); System.out.println("-------------> end " + (t1 - t0)); } if (nb % 10000 == 0) { System.out.println("Received " + nb + " messages"); } // If we want to test the write operation, uncomment this line session.write(message); } /** * {@inheritDoc} */ @Override public void sessionClosed(IoSession session) throws Exception { System.out.println("Session closed..."); // Reinitialize the counter and expose the number of received messages System.out.println("Nb message received : " + nbReceived.get()); nbReceived.set(0); } /** * {@inheritDoc} */ @Override public void sessionCreated(IoSession session) throws Exception { System.out.println("Session created..."); } /** * {@inheritDoc} */ @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { System.out.println("Session idle..."); } /** * {@inheritDoc} */ @Override public void sessionOpened(IoSession session) throws Exception { System.out.println("Session Opened..."); } /** * Create the UDP server */ public UdpServer() throws IOException { NioDatagramAcceptor acceptor = new NioDatagramAcceptor(); acceptor.setHandler(this); // The logger, if needed. Commented atm //DefaultIoFilterChainBuilder chain = acceptor.getFilterChain(); //chain.addLast("logger", new LoggingFilter()); DatagramSessionConfig dcfg = acceptor.getSessionConfig(); acceptor.bind(new InetSocketAddress(PORT)); System.out.println("Server started..."); } /** * The entry point. */ public static void main(String[] args) throws IOException { new UdpServer(); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/udp/perf/UdpClient.java0000644000175000017500000001027312032276037031467 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.udp.perf; import java.net.InetSocketAddress; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.transport.socket.DatagramSessionConfig; import org.apache.mina.transport.socket.nio.NioDatagramConnector; /** * An UDP client taht just send thousands of small messages to a UdpServer. * * This class is used for performance test purposes. It does nothing at all, but send a message * repetitly to a server. * * @author Apache MINA Project */ public class UdpClient extends IoHandlerAdapter { /** The connector */ private IoConnector connector; /** The session */ private static IoSession session; /** * Create the UdpClient's instance */ public UdpClient() { connector = new NioDatagramConnector(); connector.setHandler(this); DatagramSessionConfig dcfg = (DatagramSessionConfig) connector.getSessionConfig(); ConnectFuture connFuture = connector.connect(new InetSocketAddress("localhost", UdpServer.PORT)); connFuture.awaitUninterruptibly(); session = connFuture.getSession(); } /** * {@inheritDoc} */ @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { cause.printStackTrace(); } /** * {@inheritDoc} */ @Override public void messageReceived(IoSession session, Object message) throws Exception { } /** * {@inheritDoc} */ @Override public void messageSent(IoSession session, Object message) throws Exception { } /** * {@inheritDoc} */ @Override public void sessionClosed(IoSession session) throws Exception { } /** * {@inheritDoc} */ @Override public void sessionCreated(IoSession session) throws Exception { } /** * {@inheritDoc} */ @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { } /** * {@inheritDoc} */ @Override public void sessionOpened(IoSession session) throws Exception { } /** * The main method : instanciates a client, and send N messages. We sleep * between each K messages sent, to avoid the server saturation. * @param args * @throws Exception */ public static void main(String[] args) throws Exception { UdpClient client = new UdpClient(); long t0 = System.currentTimeMillis(); for (int i = 0; i <= UdpServer.MAX_RECEIVED; i++) { //if (i % 2 == 0) { Thread.sleep(1); //} String str = Integer.toString(i); byte[] data = str.getBytes(); IoBuffer buffer = IoBuffer.allocate(data.length); buffer.put(data); buffer.flip(); session.write(buffer); if (i % 10000 == 0) { System.out.println("Sent " + i + " messages"); } } long t1 = System.currentTimeMillis(); System.out.println("Sent messages delay : " + (t1 - t0)); Thread.sleep(100000); client.connector.dispose(true); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/gettingstarted/0000755000175000017500000000000012032276036030235 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/gettingstarted/timeserver/0000755000175000017500000000000012162575507032433 5ustar ebourgebourg././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/gettingstarted/timeserver/TimeServerHandler.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/gettingstarted/timeserver/Ti0000644000175000017500000000456412032276037032733 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.gettingstarted.timeserver; import java.util.Date; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; /** * The Time Server handler : it return the current date when a message is received, * or close the session if the "quit" message is received. * * @author Apache MINA Project */ public class TimeServerHandler extends IoHandlerAdapter { /** * Trap exceptions. */ @Override public void exceptionCaught( IoSession session, Throwable cause ) throws Exception { cause.printStackTrace(); } /** * If the message is 'quit', we exit by closing the session. Otherwise, * we return the current date. */ @Override public void messageReceived( IoSession session, Object message ) throws Exception { String str = message.toString(); if( str.trim().equalsIgnoreCase("quit") ) { // "Quit" ? let's get out ... session.close(true); return; } // Send the current date back to the client Date date = new Date(); session.write( date.toString() ); System.out.println("Message written..."); } /** * On idle, we just write a message on the console */ @Override public void sessionIdle( IoSession session, IdleStatus status ) throws Exception { System.out.println( "IDLE " + session.getIdleCount( status )); } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/gettingstarted/timeserver/MinaTimeServer.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/gettingstarted/timeserver/Mi0000644000175000017500000000527312032276037032722 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.gettingstarted.timeserver; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.charset.Charset; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; /** * A minimal 'time' server, returning the current date. Opening * a telnet server, you will get the current date by typing * any string followed by a new line. * * In order to quit, just send the 'quit' message. * * @author Apache MINA Project */ public class MinaTimeServer { /** We will use a port above 1024 to be able to launch the server with a standard user */ private static final int PORT = 9123; /** * The server implementation. It's based on TCP, and uses a logging filter * plus a text line decoder. */ public static void main(String[] args) throws IOException { // Create the acceptor IoAcceptor acceptor = new NioSocketAcceptor(); // Add two filters : a logger and a codec acceptor.getFilterChain().addLast( "logger", new LoggingFilter() ); acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" )))); // Attach the business logic to the server acceptor.setHandler( new TimeServerHandler() ); // Configurate the buffer size and the iddle time acceptor.getSessionConfig().setReadBufferSize( 2048 ); acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 ); // And bind ! acceptor.bind( new InetSocketAddress(PORT) ); } }mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/0000755000175000017500000000000012162575507026367 5ustar ebourgebourg././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/ServerSessionHandler.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/ServerSessionHandler.j0000644000175000017500000000650412032276040032641 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.sumup; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.sumup.message.AddMessage; import org.apache.mina.example.sumup.message.ResultMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * {@link IoHandler} for SumUp server. * * @author Apache MINA Project */ public class ServerSessionHandler extends IoHandlerAdapter { private static final String SUM_KEY = "sum"; private final static Logger LOGGER = LoggerFactory.getLogger(ServerSessionHandler.class); @Override public void sessionOpened(IoSession session) { // set idle time to 60 seconds session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 60); // initial sum is zero session.setAttribute(SUM_KEY, new Integer(0)); } @Override public void messageReceived(IoSession session, Object message) { // client only sends AddMessage. otherwise, we will have to identify // its type using instanceof operator. AddMessage am = (AddMessage) message; // add the value to the current sum. int sum = ((Integer) session.getAttribute(SUM_KEY)).intValue(); int value = am.getValue(); long expectedSum = (long) sum + value; if (expectedSum > Integer.MAX_VALUE || expectedSum < Integer.MIN_VALUE) { // if the sum overflows or underflows, return error message ResultMessage rm = new ResultMessage(); rm.setSequence(am.getSequence()); // copy sequence rm.setOk(false); session.write(rm); } else { // sum up sum = (int) expectedSum; session.setAttribute(SUM_KEY, new Integer(sum)); // return the result message ResultMessage rm = new ResultMessage(); rm.setSequence(am.getSequence()); // copy sequence rm.setOk(true); rm.setValue(sum); session.write(rm); } } @Override public void sessionIdle(IoSession session, IdleStatus status) { LOGGER.info("Disconnecting the idle."); // disconnect an idle client session.close(true); } @Override public void exceptionCaught(IoSession session, Throwable cause) { // close the connection on exceptional situation session.close(true); } }mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/message/0000755000175000017500000000000012162575507030013 5ustar ebourgebourg././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/message/AbstractMessage.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/message/AbstractMessag0000644000175000017500000000236412032276037032636 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.sumup.message; import java.io.Serializable; /** * A base message for SumUp protocol messages. * * @author Apache MINA Project */ public abstract class AbstractMessage implements Serializable { private int sequence; public int getSequence() { return sequence; } public void setSequence(int sequence) { this.sequence = sequence; } }././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/message/ResultMessage.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/message/ResultMessage.0000644000175000017500000000321012032276037032563 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.sumup.message; /** * RESULT message in SumUp protocol. * * @author Apache MINA Project */ public class ResultMessage extends AbstractMessage { private static final long serialVersionUID = 7371210248110219946L; private boolean ok; private int value; public ResultMessage() { } public boolean isOk() { return ok; } public void setOk(boolean ok) { this.ok = ok; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } @Override public String toString() { if (ok) { return getSequence() + ":RESULT(" + value + ')'; } else { return getSequence() + ":RESULT(ERROR)"; } } }././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/message/AddMessage.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/message/AddMessage.jav0000644000175000017500000000273012032276037032504 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.sumup.message; /** * ADD message in SumUp protocol. * * @author Apache MINA Project */ public class AddMessage extends AbstractMessage { private static final long serialVersionUID = -940833727168119141L; private int value; public AddMessage() { } public int getValue() { return value; } public void setValue(int value) { this.value = value; } @Override public String toString() { // it is a good practice to create toString() method on message classes. return getSequence() + ":ADD(" + value + ')'; } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/message/package.html0000644000175000017500000000164412032276037032271 0ustar ebourgebourg Protocol mmessage classes for SumUp protocol. ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/ClientSessionHandler.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/ClientSessionHandler.j0000644000175000017500000000574512032276040032617 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.sumup; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.sumup.message.AddMessage; import org.apache.mina.example.sumup.message.ResultMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * {@link IoHandler} for SumUp client. * * @author Apache MINA Project */ public class ClientSessionHandler extends IoHandlerAdapter { private final static Logger LOGGER = LoggerFactory.getLogger(ClientSessionHandler.class); private final int[] values; private boolean finished; public ClientSessionHandler(int[] values) { this.values = values; } public boolean isFinished() { return finished; } @Override public void sessionOpened(IoSession session) { // send summation requests for (int i = 0; i < values.length; i++) { AddMessage m = new AddMessage(); m.setSequence(i); m.setValue(values[i]); session.write(m); } } @Override public void messageReceived(IoSession session, Object message) { // server only sends ResultMessage. otherwise, we will have to identify // its type using instanceof operator. ResultMessage rm = (ResultMessage) message; if (rm.isOk()) { // server returned OK code. // if received the result message which has the last sequence // number, // it is time to disconnect. if (rm.getSequence() == values.length - 1) { // print the sum and disconnect. LOGGER.info("The sum: " + rm.getValue()); session.close(true); finished = true; } } else { // seever returned error code because of overflow, etc. LOGGER.warn("Server error, disconnecting..."); session.close(true); finished = true; } } @Override public void exceptionCaught(IoSession session, Throwable cause) { session.close(true); } }mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/Client.java0000644000175000017500000000704712032276040030442 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.sumup; import java.net.InetSocketAddress; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.sumup.codec.SumUpProtocolCodecFactory; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.nio.NioSocketConnector; /** * (Entry Point) Starts SumUp client. * * @author Apache MINA Project */ public class Client { private static final String HOSTNAME = "localhost"; private static final int PORT = 8080; private static final long CONNECT_TIMEOUT = 30*1000L; // 30 seconds // Set this to false to use object serialization instead of custom codec. private static final boolean USE_CUSTOM_CODEC = true; public static void main(String[] args) throws Throwable { if (args.length == 0) { System.out.println("Please specify the list of any integers"); return; } // prepare values to sum up int[] values = new int[args.length]; for (int i = 0; i < args.length; i++) { values[i] = Integer.parseInt(args[i]); } NioSocketConnector connector = new NioSocketConnector(); // Configure the service. connector.setConnectTimeoutMillis(CONNECT_TIMEOUT); if (USE_CUSTOM_CODEC) { connector.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new SumUpProtocolCodecFactory(false))); } else { connector.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new ObjectSerializationCodecFactory())); } connector.getFilterChain().addLast("logger", new LoggingFilter()); connector.setHandler(new ClientSessionHandler(values)); IoSession session; for (;;) { try { ConnectFuture future = connector.connect(new InetSocketAddress( HOSTNAME, PORT)); future.awaitUninterruptibly(); session = future.getSession(); break; } catch (RuntimeIoException e) { System.err.println("Failed to connect."); e.printStackTrace(); Thread.sleep(5000); } } // wait until the summation is done session.getCloseFuture().awaitUninterruptibly(); connector.dispose(); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/0000755000175000017500000000000012162575507027444 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/Constants.java0000644000175000017500000000303612032276040032247 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.sumup.codec; /** * Provides SumUp protocol constants. * * @author Apache MINA Project */ public class Constants { public static final int TYPE_LEN = 2; public static final int SEQUENCE_LEN = 4; public static final int HEADER_LEN = TYPE_LEN + SEQUENCE_LEN; public static final int BODY_LEN = 12; public static final int RESULT = 0; public static final int ADD = 1; public static final int RESULT_CODE_LEN = 2; public static final int RESULT_VALUE_LEN = 4; public static final int ADD_BODY_LEN = 4; public static final int RESULT_OK = 0; public static final int RESULT_ERROR = 1; private Constants() { } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/AbstractMessageDecoder.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/AbstractMessageD0000644000175000017500000000577212032276040032540 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.sumup.codec; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.sumup.message.AbstractMessage; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import org.apache.mina.filter.codec.demux.MessageDecoder; import org.apache.mina.filter.codec.demux.MessageDecoderResult; /** * A {@link MessageDecoder} that decodes message header and forwards * the decoding of body to a subclass. * * @author Apache MINA Project */ public abstract class AbstractMessageDecoder implements MessageDecoder { private final int type; private int sequence; private boolean readHeader; protected AbstractMessageDecoder(int type) { this.type = type; } public MessageDecoderResult decodable(IoSession session, IoBuffer in) { // Return NEED_DATA if the whole header is not read yet. if (in.remaining() < Constants.HEADER_LEN) { return MessageDecoderResult.NEED_DATA; } // Return OK if type and bodyLength matches. if (type == in.getShort()) { return MessageDecoderResult.OK; } // Return NOT_OK if not matches. return MessageDecoderResult.NOT_OK; } public MessageDecoderResult decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { // Try to skip header if not read. if (!readHeader) { in.getShort(); // Skip 'type'. sequence = in.getInt(); // Get 'sequence'. readHeader = true; } // Try to decode body AbstractMessage m = decodeBody(session, in); // Return NEED_DATA if the body is not fully read. if (m == null) { return MessageDecoderResult.NEED_DATA; } else { readHeader = false; // reset readHeader for the next decode } m.setSequence(sequence); out.write(m); return MessageDecoderResult.OK; } /** * @return null if the whole body is not read yet */ protected abstract AbstractMessage decodeBody(IoSession session, IoBuffer in); } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/AbstractMessageEncoder.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/AbstractMessageE0000644000175000017500000000403512032276040032530 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.sumup.codec; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.sumup.message.AbstractMessage; import org.apache.mina.filter.codec.ProtocolEncoderOutput; import org.apache.mina.filter.codec.demux.MessageEncoder; /** * A {@link MessageEncoder} that encodes message header and forwards * the encoding of body to a subclass. * * @author Apache MINA Project */ public abstract class AbstractMessageEncoder implements MessageEncoder { private final int type; protected AbstractMessageEncoder(int type) { this.type = type; } public void encode(IoSession session, T message, ProtocolEncoderOutput out) throws Exception { IoBuffer buf = IoBuffer.allocate(16); buf.setAutoExpand(true); // Enable auto-expand for easier encoding // Encode a header buf.putShort((short) type); buf.putInt(message.getSequence()); // Encode a body encodeBody(session, message, buf); buf.flip(); out.write(buf); } protected abstract void encodeBody(IoSession session, T message, IoBuffer out); } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/SumUpProtocolCodecFactory.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/SumUpProtocolCod0000644000175000017500000000337412032276040032601 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.sumup.codec; import org.apache.mina.example.sumup.message.AddMessage; import org.apache.mina.example.sumup.message.ResultMessage; import org.apache.mina.filter.codec.ProtocolCodecFactory; import org.apache.mina.filter.codec.demux.DemuxingProtocolCodecFactory; /** * A {@link ProtocolCodecFactory} that provides a protocol codec for * SumUp protocol. * * @author Apache MINA Project */ public class SumUpProtocolCodecFactory extends DemuxingProtocolCodecFactory { public SumUpProtocolCodecFactory(boolean server) { if (server) { super.addMessageDecoder(AddMessageDecoder.class); super.addMessageEncoder(ResultMessage.class, ResultMessageEncoder.class); } else // Client { super.addMessageEncoder(AddMessage.class, AddMessageEncoder.class); super.addMessageDecoder(ResultMessageDecoder.class); } } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/ResultMessageDecoder.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/ResultMessageDec0000644000175000017500000000462412032276040032556 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.sumup.codec; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.sumup.message.AbstractMessage; import org.apache.mina.example.sumup.message.ResultMessage; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import org.apache.mina.filter.codec.demux.MessageDecoder; /** * A {@link MessageDecoder} that decodes {@link ResultMessage}. * * @author Apache MINA Project */ public class ResultMessageDecoder extends AbstractMessageDecoder { private int code; private boolean readCode; public ResultMessageDecoder() { super(Constants.RESULT); } @Override protected AbstractMessage decodeBody(IoSession session, IoBuffer in) { if (!readCode) { if (in.remaining() < Constants.RESULT_CODE_LEN) { return null; // Need more data. } code = in.getShort(); readCode = true; } if (code == Constants.RESULT_OK) { if (in.remaining() < Constants.RESULT_VALUE_LEN) { return null; } ResultMessage m = new ResultMessage(); m.setOk(true); m.setValue(in.getInt()); readCode = false; return m; } else { ResultMessage m = new ResultMessage(); m.setOk(false); readCode = false; return m; } } public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception { } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/AddMessageDecoder.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/AddMessageDecode0000644000175000017500000000351412032276040032455 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.sumup.codec; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.sumup.message.AbstractMessage; import org.apache.mina.example.sumup.message.AddMessage; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import org.apache.mina.filter.codec.demux.MessageDecoder; /** * A {@link MessageDecoder} that decodes {@link AddMessage}. * * @author Apache MINA Project */ public class AddMessageDecoder extends AbstractMessageDecoder { public AddMessageDecoder() { super(Constants.ADD); } @Override protected AbstractMessage decodeBody(IoSession session, IoBuffer in) { if (in.remaining() < Constants.ADD_BODY_LEN) { return null; } AddMessage m = new AddMessage(); m.setValue(in.getInt()); return m; } public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception { } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/ResultMessageEncoder.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/ResultMessageEnc0000644000175000017500000000334012032276040032562 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.sumup.codec; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.sumup.message.ResultMessage; import org.apache.mina.filter.codec.demux.MessageEncoder; /** * A {@link MessageEncoder} that encodes {@link ResultMessage}. * * @author Apache MINA Project */ public class ResultMessageEncoder extends AbstractMessageEncoder { public ResultMessageEncoder() { super(Constants.RESULT); } @Override protected void encodeBody(IoSession session, T message, IoBuffer out) { if (message.isOk()) { out.putShort((short) Constants.RESULT_OK); out.putInt(message.getValue()); } else { out.putShort((short) Constants.RESULT_ERROR); } } public void dispose() throws Exception { } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/AddMessageEncoder.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/AddMessageEncode0000644000175000017500000000304012032276040032461 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.sumup.codec; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.sumup.message.AddMessage; import org.apache.mina.filter.codec.demux.MessageEncoder; /** * A {@link MessageEncoder} that encodes {@link AddMessage}. * * @author Apache MINA Project */ public class AddMessageEncoder extends AbstractMessageEncoder { public AddMessageEncoder() { super(Constants.ADD); } @Override protected void encodeBody(IoSession session, T message, IoBuffer out) { out.putInt(message.getValue()); } public void dispose() throws Exception { } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/codec/package.html0000644000175000017500000000165012032276040031711 0ustar ebourgebourg Protocol codec implementation for SumUp protocol. mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/Server.java0000644000175000017500000000467012032276040030471 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.sumup; import java.net.InetSocketAddress; import org.apache.mina.example.sumup.codec.SumUpProtocolCodecFactory; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; /** * (Entry Point) Starts SumUp server. * * @author Apache MINA Project */ public class Server { private static final int SERVER_PORT = 8080; // Set this to false to use object serialization instead of custom codec. private static final boolean USE_CUSTOM_CODEC = true; public static void main(String[] args) throws Throwable { NioSocketAcceptor acceptor = new NioSocketAcceptor(); // Prepare the service configuration. if (USE_CUSTOM_CODEC) { acceptor.getFilterChain() .addLast( "codec", new ProtocolCodecFilter( new SumUpProtocolCodecFactory(true))); } else { acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new ObjectSerializationCodecFactory())); } acceptor.getFilterChain().addLast("logger", new LoggingFilter()); acceptor.setHandler(new ServerSessionHandler()); acceptor.bind(new InetSocketAddress(SERVER_PORT)); System.out.println("Listening on port " + SERVER_PORT); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/sumup/package.html0000644000175000017500000000165612032276040030642 0ustar ebourgebourg SumUp Server and Client which sums up all ADD requests. mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/netcat/0000755000175000017500000000000012162575507026474 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/netcat/Main.java0000644000175000017500000000412012032276040030202 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.netcat; import java.net.InetSocketAddress; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.transport.socket.nio.NioSocketConnector; /** * (Entry point) NetCat client. NetCat client connects to the specified * endpoint and prints out received data. NetCat client disconnects * automatically when no data is read for 10 seconds. * * @author Apache MINA Project */ public class Main { public static void main(String[] args) throws Exception { if (args.length != 2) { System.out.println(Main.class.getName() + " "); return; } // Create TCP/IP connector. NioSocketConnector connector = new NioSocketConnector(); // Set connect timeout. connector.setConnectTimeoutMillis(30*1000L); // Start communication. connector.setHandler(new NetCatProtocolHandler()); ConnectFuture cf = connector.connect( new InetSocketAddress(args[0], Integer.parseInt(args[1]))); // Wait for the connection attempt to be finished. cf.awaitUninterruptibly(); cf.getSession().getCloseFuture().awaitUninterruptibly(); connector.dispose(); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/netcat/NetCatProtocolHandler.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/netcat/NetCatProtocolHandler0000644000175000017500000000454412032276040032606 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.example.netcat; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; /** * {@link IoHandler} implementation for NetCat client. This class extended * {@link IoHandlerAdapter} for convenience. * * @author Apache MINA Project */ public class NetCatProtocolHandler extends IoHandlerAdapter { @Override public void sessionOpened(IoSession session) { // Set reader idle time to 10 seconds. // sessionIdle(...) method will be invoked when no data is read // for 10 seconds. session.getConfig().setIdleTime(IdleStatus.READER_IDLE, 10); } @Override public void sessionClosed(IoSession session) { // Print out total number of bytes read from the remote peer. System.err.println("Total " + session.getReadBytes() + " byte(s)"); } @Override public void sessionIdle(IoSession session, IdleStatus status) { // Close the connection if reader is idle. if (status == IdleStatus.READER_IDLE) { session.close(true); } } @Override public void messageReceived(IoSession session, Object message) { IoBuffer buf = (IoBuffer) message; // Print out read buffer content. while (buf.hasRemaining()) { System.out.print((char) buf.get()); } System.out.flush(); } }mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/netcat/package.html0000644000175000017500000000172512032276040030744 0ustar ebourgebourg NetCat client (Network + Unix cat command) which demonstates low-level I/O layer. mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/haiku/0000755000175000017500000000000012162575507026317 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/haiku/HaikuValidator.java0000644000175000017500000000272412032276036032065 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.mina.example.haiku; /** * @author Apache MINA Project */ public class HaikuValidator { private static final int[] SYLLABLE_COUNTS = { 5, 7, 5 }; public void validate(Haiku haiku) throws InvalidHaikuException { String[] phrases = haiku.getPhrases(); for (int i = 0; i < phrases.length; i++) { String phrase = phrases[i]; int count = PhraseUtilities.countSyllablesInPhrase(phrase); if (count != SYLLABLE_COUNTS[i]) { throw new InvalidHaikuException(i + 1, phrase, count, SYLLABLE_COUNTS[i]); } } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/haiku/HaikuValidatorIoHandler.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/haiku/HaikuValidatorIoHandle0000644000175000017500000000276512032276036032556 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.mina.example.haiku; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; /** * @author Apache MINA Project */ public class HaikuValidatorIoHandler extends IoHandlerAdapter { private final HaikuValidator validator = new HaikuValidator(); @Override public void messageReceived(IoSession session, Object message) throws Exception { Haiku haiku = (Haiku) message; try { validator.validate(haiku); session.write("HAIKU!"); } catch (InvalidHaikuException e) { session.write("NOT A HAIKU: " + e.getMessage()); } } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/haiku/HaikuValidationServer.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/haiku/HaikuValidationServer.0000644000175000017500000000415712032276036032561 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.mina.example.haiku; import java.net.InetSocketAddress; import java.nio.charset.Charset; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.filter.executor.ExecutorFilter; import org.apache.mina.transport.socket.SocketAcceptor; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; /** * @author Apache MINA Project */ public class HaikuValidationServer { public static void main(String... args) throws Exception { ExecutorService executor = Executors.newCachedThreadPool(); SocketAcceptor acceptor = new NioSocketAcceptor(Runtime.getRuntime() .availableProcessors()); acceptor.getFilterChain().addLast("executor", new ExecutorFilter(executor)); acceptor.getFilterChain().addLast( "to-string", new ProtocolCodecFilter(new TextLineCodecFactory(Charset .forName("US-ASCII")))); acceptor.getFilterChain().addLast("to-haiki", new ToHaikuIoFilter()); acceptor.setHandler(new HaikuValidatorIoHandler()); acceptor.bind(new InetSocketAddress(42458)); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/haiku/PhraseUtilities.java0000644000175000017500000000503512032276036032272 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.mina.example.haiku; /** * @author Apache MINA Project */ public class PhraseUtilities { static int countSyllablesInPhrase(String phrase) { int syllables = 0; for (String word : phrase.split("[^\\w-]+")) { if (word.length() > 0) { syllables += countSyllablesInWord(word.toLowerCase()); } } return syllables; } static int countSyllablesInWord(String word) { char[] chars = word.toCharArray(); int syllables = 0; boolean lastWasVowel = false; for (int i = 0; i < chars.length; i++) { char c = chars[i]; if (isVowel(c)) { if (!lastWasVowel || (i > 0 && isE(chars, i - 1) && isO(chars, i))) { ++syllables; lastWasVowel = true; } } else { lastWasVowel = false; } } if (word.endsWith("oned") || word.endsWith("ne") || word.endsWith("ide") || word.endsWith("ve") || word.endsWith("fe") || word.endsWith("nes") || word.endsWith("mes")) { --syllables; } return syllables; } static boolean isE(char[] chars, int position) { return isCharacter(chars, position, 'e'); } static boolean isCharacter(char[] chars, int position, char c) { return chars[position] == c; } static boolean isO(char[] chars, int position) { return isCharacter(chars, position, 'o'); } static boolean isVowel(char c) { return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'y'; } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/haiku/Haiku.java0000644000175000017500000000332412032276036030214 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.mina.example.haiku; import java.util.Arrays; /** * @author Apache MINA Project */ public class Haiku { private final String[] phrases; public Haiku(String... lines) { this.phrases = lines; if (null == lines || lines.length != 3) { throw new IllegalArgumentException("Must pass in 3 phrases of text"); } } public String[] getPhrases() { return phrases; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Haiku haiku = (Haiku) o; return Arrays.equals(phrases, haiku.phrases); } @Override public int hashCode() { return Arrays.hashCode(phrases); } @Override public String toString() { return Arrays.toString(phrases); } } mina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/haiku/ToHaikuIoFilter.java0000644000175000017500000000340512032276036032155 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.mina.example.haiku; import java.util.ArrayList; import java.util.List; import org.apache.mina.core.filterchain.IoFilterAdapter; import org.apache.mina.core.session.IoSession; /** * @author Apache MINA Project */ public class ToHaikuIoFilter extends IoFilterAdapter { @SuppressWarnings( { "unchecked" }) @Override public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception { List phrases = (List) session.getAttribute("phrases"); if (null == phrases) { phrases = new ArrayList(); session.setAttribute("phrases", phrases); } phrases.add((String) message); if (phrases.size() == 3) { session.removeAttribute("phrases"); super.messageReceived(nextFilter, session, new Haiku(phrases .toArray(new String[3]))); } } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/haiku/InvalidHaikuException.javamina2-2.0.7.orig/src/mina-example/src/main/java/org/apache/mina/example/haiku/InvalidHaikuException.0000644000175000017500000000361612032276036032544 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.mina.example.haiku; /** * @author Apache MINA Project */ public class InvalidHaikuException extends Exception { private static final long serialVersionUID = 34877739006797894L; private final int position; private final String phrase; private final int syllableCount; private final int expectedSyllableCount; public InvalidHaikuException(int position, String phrase, int syllableCount, int expectedSyllableCount) { super("phrase " + position + ", '" + phrase + "' had " + syllableCount + " syllables, not " + expectedSyllableCount); this.position = position; this.phrase = phrase; this.syllableCount = syllableCount; this.expectedSyllableCount = expectedSyllableCount; } public int getExpectedSyllableCount() { return expectedSyllableCount; } public String getPhrase() { return phrase; } public int getSyllableCount() { return syllableCount; } public int getPhrasePosition() { return position; } } mina2-2.0.7.orig/src/mina-example/src/main/java/META-INF/0000755000175000017500000000000012032276035021755 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/resources/0000755000175000017500000000000012162575507021720 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/resources/log4j.properties0000644000175000017500000000275212032276040025045 0ustar ebourgebourg############################################################################# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ############################################################################# # Please don't modify the log level until we reach to acceptable test coverage. # It's very useful when I test examples manually. log4j.rootCategory=INFO, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout #log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c] - %m%n # you could use this pattern to test the MDC with the Chat server log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %t %p %X{name} [%X{user}] [%X{remoteAddress}] [%c] - %m%nmina2-2.0.7.orig/src/mina-example/src/main/resources/org/0000755000175000017500000000000012032276040022471 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/resources/org/apache/0000755000175000017500000000000012032276040023712 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/resources/org/apache/mina/0000755000175000017500000000000012032276040024636 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/resources/org/apache/mina/example/0000755000175000017500000000000012032276040026271 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/resources/org/apache/mina/example/echoserver/0000755000175000017500000000000012032276040030436 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/resources/org/apache/mina/example/echoserver/ssl/0000755000175000017500000000000012162575507031255 5ustar ebourgebourg././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-example/src/main/resources/org/apache/mina/example/echoserver/ssl/bogus.certmina2-2.0.7.orig/src/mina-example/src/main/resources/org/apache/mina/example/echoserver/ssl/bogus.ce0000644000175000017500000000165112032276040032672 0ustar ebourgebourgbogus}Ė00 +*|a-##A֧o".FRy ֔Їf`BKZMiPо˖(-SXH:"3|'%Ne\5 IK82EW sa!F[ˈy (Ahic9+|&D[)O7؏D!ݥ ߰1ÛaE8DNc˸ꇖ(؄N v}Ѐq1YbiYAJkjK9TNe\0ܘ-R'X.50900rB,pS0  *H 0n1 0 USE10U Stockholm10U Stockholm10U  Bogus Inc10 U XXX CA10U bogus.com0 050307151635Z 150305151635Z0n1 0 USE10U Stockholm10U Stockholm10U  Bogus Inc10 U XXX CA10U bogus.com0[0  *H J0G@Z & |+mJ;X|jv>JHmK'6LAx3i o0  *H AI@Ba?>2n(9OdmiJE 5 @y |[:k#Ŧ];e8mina2-2.0.7.orig/src/mina-example/src/main/resources/org/apache/mina/example/chat/0000755000175000017500000000000012162575507027226 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-example/src/main/resources/org/apache/mina/example/chat/serverContext.xml0000644000175000017500000001357512032276040032620 0ustar ebourgebourg mina2-2.0.7.orig/src/mina-transport-serial/0000755000175000017500000000000012162575507020051 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-serial/NOTICE.txt0000644000175000017500000000034112032276011021551 0ustar ebourgebourgSerial port communication is provided by the RXTX library package, which is open source software, written by Keane Jarvi et al, and copyright by Keane Jarvi. The orifinal software is available from http://www.rxtx.org/ mina2-2.0.7.orig/src/mina-transport-serial/pom.xml.releaseBackup0000644000175000017500000000414112033674301024120 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7-SNAPSHOT mina-transport-serial Apache MINA Serial Communication support bundle ${project.groupId}.transport.serial ${project.groupId}.transport.serial ${project.groupId} mina-core ${project.version} bundle ${project.groupId} mina-integration-beans ${project.version} bundle org.rxtx rxtx 2.1.7 provided mina2-2.0.7.orig/src/mina-transport-serial/pom.xml0000644000175000017500000000413012033674306021356 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7 mina-transport-serial Apache MINA Serial Communication support bundle ${project.groupId}.transport.serial ${project.groupId}.transport.serial ${project.groupId} mina-core ${project.version} bundle ${project.groupId} mina-integration-beans ${project.version} bundle org.rxtx rxtx 2.1.7 provided mina2-2.0.7.orig/src/mina-transport-serial/src/0000755000175000017500000000000012032276011020620 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-serial/src/main/0000755000175000017500000000000012032276011021544 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-serial/src/main/java/0000755000175000017500000000000012032276011022465 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/0000755000175000017500000000000012032276011023254 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/0000755000175000017500000000000012032276011024475 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/0000755000175000017500000000000012032276011025421 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/0000755000175000017500000000000012032276011027455 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/0000755000175000017500000000000012162575507030754 5ustar ebourgebourg././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/SerialConnector.javamina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/SerialConn0000644000175000017500000001513312032276011032717 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.serial; import gnu.io.CommPortIdentifier; import gnu.io.PortInUseException; import gnu.io.SerialPort; import gnu.io.UnsupportedCommOperationException; import java.io.IOException; import java.net.SocketAddress; import java.util.Enumeration; import java.util.TooManyListenersException; import java.util.concurrent.Executor; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.DefaultConnectFuture; import org.apache.mina.core.service.AbstractIoConnector; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.core.session.IdleStatusChecker; import org.apache.mina.core.session.IoSessionInitializer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * {@link IoConnector} for serial communication transport. * * @author Apache MINA Project */ public final class SerialConnector extends AbstractIoConnector { private final Logger log; private IdleStatusChecker idleChecker; public SerialConnector() { this(null); } public SerialConnector(Executor executor) { super(new DefaultSerialSessionConfig(), executor); log = LoggerFactory.getLogger(SerialConnector.class); idleChecker = new IdleStatusChecker(); // we schedule the idle status checking task in this service exceutor // it will be woke up every seconds executeWorker(idleChecker.getNotifyingTask(), "idleStatusChecker"); } @Override protected synchronized ConnectFuture connect0(SocketAddress remoteAddress, SocketAddress localAddress, IoSessionInitializer sessionInitializer) { CommPortIdentifier portId; Enumeration portList = CommPortIdentifier.getPortIdentifiers(); SerialAddress portAddress = (SerialAddress) remoteAddress; // looping around found ports while (portList.hasMoreElements()) { portId = (CommPortIdentifier) portList.nextElement(); if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { if (log.isDebugEnabled()) { log.debug("Serial port discovered : " + portId.getName()); } if (portId.getName().equals(portAddress.getName())) { try { if (log.isDebugEnabled()) { log.debug("Serial port found : " + portId.getName()); } SerialPort serialPort = initializePort("Apache MINA", portId, portAddress); ConnectFuture future = new DefaultConnectFuture(); SerialSessionImpl session = new SerialSessionImpl(this, getListeners(), portAddress, serialPort); initSession(session, future, sessionInitializer); session.start(); return future; } catch (PortInUseException e) { if (log.isDebugEnabled()) { log.debug("Port In Use Exception : ", e); } return DefaultConnectFuture.newFailedFuture(e); } catch (UnsupportedCommOperationException e) { if (log.isDebugEnabled()) { log.debug("Comm Exception : ", e); } return DefaultConnectFuture.newFailedFuture(e); } catch (IOException e) { if (log.isDebugEnabled()) { log.debug("IOException : ", e); } return DefaultConnectFuture.newFailedFuture(e); } catch (TooManyListenersException e) { if (log.isDebugEnabled()) { log.debug("TooManyListenersException : ", e); } return DefaultConnectFuture.newFailedFuture(e); } } } } return DefaultConnectFuture.newFailedFuture(new SerialPortUnavailableException("Serial port not found")); } @Override protected void dispose0() throws Exception { // stop the idle checking task idleChecker.getNotifyingTask().cancel(); } public TransportMetadata getTransportMetadata() { return SerialSessionImpl.METADATA; } private SerialPort initializePort(String user, CommPortIdentifier portId, SerialAddress portAddress) throws UnsupportedCommOperationException, PortInUseException { SerialSessionConfig config = (SerialSessionConfig) getSessionConfig(); long connectTimeout = getConnectTimeoutMillis(); if (connectTimeout > Integer.MAX_VALUE) { connectTimeout = Integer.MAX_VALUE; } SerialPort serialPort = (SerialPort) portId.open(user, (int) connectTimeout); serialPort.setSerialPortParams(portAddress.getBauds(), portAddress.getDataBitsForRXTX(), portAddress.getStopBitsForRXTX(), portAddress.getParityForRXTX()); serialPort.setFlowControlMode(portAddress.getFLowControlForRXTX()); serialPort.notifyOnDataAvailable(true); if (config.isLowLatency()) { serialPort.setLowLatency(); } serialPort.setInputBufferSize(config.getInputBufferSize()); serialPort.setOutputBufferSize(config.getOutputBufferSize()); if (config.getReceiveThreshold() >= 0) { serialPort.enableReceiveThreshold(config.getReceiveThreshold()); } else { serialPort.disableReceiveThreshold(); } return serialPort; } IdleStatusChecker getIdleStatusChecker0() { return idleChecker; } }././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/SerialSession.javamina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/SerialSess0000644000175000017500000000372612032276011032744 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.serial; import org.apache.mina.core.session.IoSession; /** * An {@link IoSession} for serial communication transport. * * @author Apache MINA Project */ public interface SerialSession extends IoSession { SerialSessionConfig getConfig(); SerialAddress getRemoteAddress(); SerialAddress getLocalAddress(); SerialAddress getServiceAddress(); /** * Sets or clears the RTS (Request To Send) bit in the UART, if supported by the underlying implementation. * @param rts true for set RTS, false for clearing */ void setRTS(boolean rts); /** * Gets the state of the RTS (Request To Send) bit in the UART, if supported by the underlying implementation. */ boolean isRTS(); /** * Sets or clears the DTR (Data Terminal Ready) bit in the UART, if supported by the underlying implementation. * @param dtr true for set DTR, false for clearing */ void setDTR(boolean dtr); /** * Gets the state of the DTR (Data Terminal Ready) bit in the UART, if supported by the underlying implementation. */ boolean isDTR(); } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/SerialAddressEditor.javamina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/SerialAddr0000644000175000017500000001322112032276011032670 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.serial; import java.beans.PropertyEditor; import org.apache.mina.integration.beans.AbstractPropertyEditor; import org.apache.mina.transport.serial.SerialAddress.DataBits; import org.apache.mina.transport.serial.SerialAddress.FlowControl; import org.apache.mina.transport.serial.SerialAddress.Parity; import org.apache.mina.transport.serial.SerialAddress.StopBits; /** * A {@link PropertyEditor} which converts a {@link String} into a * {@link SerialAddress} and vice versa. Valid values specify 6 address * components separated by colon (e.g. COM1:9600:7:1:even:rtscts-in); * port name, bauds, data bits, stop bits, parity and flow control respectively. * * @author Apache MINA Project */ public class SerialAddressEditor extends AbstractPropertyEditor { @Override protected String toText(Object value) { SerialAddress addr = (SerialAddress) value; return addr.getName() + ':' + addr.getBauds() + ':' + toText(addr.getDataBits()) + ':' + toText(addr.getStopBits()) + ':' + toText(addr.getParity()) + ':' + toText(addr.getFlowControl()); } private String toText(DataBits bits) { switch (bits) { case DATABITS_5: return "5"; case DATABITS_6: return "6"; case DATABITS_7: return "7"; case DATABITS_8: return "8"; default: throw new IllegalArgumentException("Unknown dataBits: " + bits); } } private String toText(StopBits bits) { switch (bits) { case BITS_1: return "1"; case BITS_1_5: return "1.5"; case BITS_2: return "2"; default: throw new IllegalArgumentException("Unknown stopBits: " + bits); } } private String toText(Parity parity) { switch (parity) { case EVEN: return "even"; case ODD: return "odd"; case MARK: return "mark"; case NONE: return "none"; case SPACE: return "space"; default: throw new IllegalArgumentException("Unknown parity: " + parity); } } private String toText(FlowControl flowControl) { switch (flowControl) { case NONE: return "none"; case RTSCTS_IN: return "rtscts-in"; case RTSCTS_OUT: return "rtscts-out"; case XONXOFF_IN: return "xonxoff-in"; case XONXOFF_OUT: return "xonxoff-out"; default: throw new IllegalArgumentException("Unknown flowControl: " + flowControl); } } @Override protected Object toValue(String text) throws IllegalArgumentException { String[] components = text.split(":"); if (components.length != 6) { throw new IllegalArgumentException("SerialAddress must have 6 components separated " + "by colon: " + text); } return new SerialAddress(components[0].trim(), toBauds(components[1].trim()), toDataBits(components[2].trim()), toStopBits(components[3].trim()), toParity(components[4].trim()), toFlowControl(components[5].trim())); } private int toBauds(String text) { try { return Integer.parseInt(text); } catch (NumberFormatException e) { throw new IllegalArgumentException("bauds: " + text); } } private DataBits toDataBits(String text) { try { return DataBits.valueOf("DATABITS_" + Integer.parseInt(text)); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("dataBits: " + text); } } private StopBits toStopBits(String text) { try { return StopBits.valueOf("BITS_" + text.replace('.', '_')); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("stopBits: " + text); } } private Parity toParity(String text) { try { return Parity.valueOf(text.toUpperCase()); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("parity: " + text); } } private FlowControl toFlowControl(String text) { String normalizedText = text.toUpperCase().replaceAll("(-|_)", ""); if (normalizedText.endsWith("IN")) { normalizedText = normalizedText.substring(0, normalizedText.length() - 2) + "_IN"; } if (normalizedText.endsWith("OUT")) { normalizedText = normalizedText.substring(0, normalizedText.length() - 3) + "_OUT"; } try { return FlowControl.valueOf(normalizedText); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("flowControl: " + text); } } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootmina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/SerialPortUnavailableException.javamina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/SerialPort0000644000175000017500000000242312032276011032744 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.serial; import org.apache.mina.core.RuntimeIoException; /** * Exception thrown when the serial port can't be open because * it doesn't exists. * @author Apache MINA Project */ public class SerialPortUnavailableException extends RuntimeIoException { private static final long serialVersionUID = 1L; public SerialPortUnavailableException(String details) { super(details); } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/DefaultSerialSessionConfig.javamina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/DefaultSer0000644000175000017500000000544512032276011032725 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.serial; import org.apache.mina.core.session.AbstractIoSessionConfig; import org.apache.mina.core.session.IoSessionConfig; /** * The default configuration for a serial session {@link SerialSessionConfig}. * * @author Apache MINA Project */ class DefaultSerialSessionConfig extends AbstractIoSessionConfig implements SerialSessionConfig { private int receiveThreshold = -1; private int inputBufferSize = 8; private int outputBufferSize = 8; private boolean lowLatency = false; public DefaultSerialSessionConfig() { // All default properties were configured above. } /** * {@inheritDoc} */ @Override protected void doSetAll(IoSessionConfig config) { if (config instanceof SerialSessionConfig) { SerialSessionConfig cfg = (SerialSessionConfig) config; setInputBufferSize(cfg.getInputBufferSize()); setReceiveThreshold(cfg.getReceiveThreshold()); } } /** * {@inheritDoc} */ public int getInputBufferSize() { return inputBufferSize; } /** * {@inheritDoc} */ public boolean isLowLatency() { return lowLatency; } /** * {@inheritDoc} */ public void setInputBufferSize(int bufferSize) { inputBufferSize = bufferSize; } /** * {@inheritDoc} */ public void setLowLatency(boolean lowLatency) { this.lowLatency = lowLatency; } /** * {@inheritDoc} */ public int getReceiveThreshold() { return receiveThreshold; } /** * {@inheritDoc} */ public void setReceiveThreshold(int bytes) { receiveThreshold = bytes; } /** * {@inheritDoc} */ public int getOutputBufferSize() { return outputBufferSize; } /** * {@inheritDoc} */ public void setOutputBufferSize(int bufferSize) { outputBufferSize = bufferSize; } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/SerialSessionImpl.javamina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/SerialSess0000644000175000017500000002427212032276011032743 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.serial; import gnu.io.SerialPort; import gnu.io.SerialPortEvent; import gnu.io.SerialPortEventListener; import gnu.io.UnsupportedCommOperationException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.TooManyListenersException; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.DefaultIoFilterChain; import org.apache.mina.core.filterchain.IoFilterChain; import org.apache.mina.core.service.DefaultTransportMetadata; import org.apache.mina.core.service.IoProcessor; import org.apache.mina.core.service.IoServiceListenerSupport; import org.apache.mina.core.service.TransportMetadata; import org.apache.mina.core.session.AbstractIoSession; import org.apache.mina.core.write.WriteRequest; import org.apache.mina.core.write.WriteRequestQueue; import org.apache.mina.util.ExceptionMonitor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An imlpementation of {@link SerialSession}. * * @author Apache MINA Project */ class SerialSessionImpl extends AbstractIoSession implements SerialSession, SerialPortEventListener { static final TransportMetadata METADATA = new DefaultTransportMetadata("rxtx", "serial", false, true, SerialAddress.class, SerialSessionConfig.class, IoBuffer.class); private final IoProcessor processor = new SerialIoProcessor(); private final IoFilterChain filterChain; private final IoServiceListenerSupport serviceListeners; private final SerialAddress address; private final SerialPort port; private final Logger log; private InputStream inputStream; private OutputStream outputStream; SerialSessionImpl(SerialConnector service, IoServiceListenerSupport serviceListeners, SerialAddress address, SerialPort port) { super(service); config = new DefaultSerialSessionConfig(); this.serviceListeners = serviceListeners; filterChain = new DefaultIoFilterChain(this); this.port = port; this.address = address; log = LoggerFactory.getLogger(SerialSessionImpl.class); } public SerialSessionConfig getConfig() { return (SerialSessionConfig) config; } public IoFilterChain getFilterChain() { return filterChain; } public TransportMetadata getTransportMetadata() { return METADATA; } public SerialAddress getLocalAddress() { return null; // not applicable } public SerialAddress getRemoteAddress() { return address; } @Override public SerialAddress getServiceAddress() { return (SerialAddress) super.getServiceAddress(); } public void setDTR(boolean dtr) { port.setDTR(dtr); } public boolean isDTR() { return port.isDTR(); } public void setRTS(boolean rts) { port.setRTS(rts); } public boolean isRTS() { return port.isRTS(); } /** * start handling streams * * @throws IOException * @throws TooManyListenersException */ void start() throws IOException, TooManyListenersException { inputStream = port.getInputStream(); outputStream = port.getOutputStream(); ReadWorker w = new ReadWorker(); w.start(); port.addEventListener(this); ((SerialConnector) getService()).getIdleStatusChecker0().addSession(this); try { getService().getFilterChainBuilder().buildFilterChain(getFilterChain()); serviceListeners.fireSessionCreated(this); } catch (Throwable e) { getFilterChain().fireExceptionCaught(e); processor.remove(this); } } private final Object writeMonitor = new Object(); private WriteWorker writeWorker; private class WriteWorker extends Thread { @Override public void run() { synchronized (writeMonitor) { while (isConnected() && !isClosing()) { flushWrites(); // wait for more data try { writeMonitor.wait(); } catch (InterruptedException e) { log.error("InterruptedException", e); } } } } } private void flushWrites() { for (;;) { WriteRequest req = getCurrentWriteRequest(); if (req == null) { req = getWriteRequestQueue().poll(this); if (req == null) { break; } } IoBuffer buf = (IoBuffer) req.getMessage(); if (buf.remaining() == 0) { setCurrentWriteRequest(null); buf.reset(); this.getFilterChain().fireMessageSent(req); continue; } int writtenBytes = buf.remaining(); try { outputStream.write(buf.array(), buf.position(), writtenBytes); buf.position(buf.position() + writtenBytes); // increase written bytes increaseWrittenBytes(writtenBytes, System.currentTimeMillis()); setCurrentWriteRequest(null); buf.reset(); // fire the message sent event getFilterChain().fireMessageSent(req); } catch (IOException e) { this.getFilterChain().fireExceptionCaught(e); } } } private final Object readReadyMonitor = new Object(); private class ReadWorker extends Thread { @Override public void run() { while (isConnected() && !isClosing()) { synchronized (readReadyMonitor) { try { readReadyMonitor.wait(); } catch (InterruptedException e) { log.error("InterruptedException", e); } if (isClosing() || !isConnected()) { break; } int dataSize; try { dataSize = inputStream.available(); byte[] data = new byte[dataSize]; int readBytes = inputStream.read(data); if (readBytes > 0) { IoBuffer buf = IoBuffer.wrap(data, 0, readBytes); buf.put(data, 0, readBytes); buf.flip(); getFilterChain().fireMessageReceived(buf); } } catch (IOException e) { getFilterChain().fireExceptionCaught(e); } } } } } public void serialEvent(SerialPortEvent evt) { if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE) { synchronized (readReadyMonitor) { readReadyMonitor.notifyAll(); } } } @Override public IoProcessor getProcessor() { return processor; } private class SerialIoProcessor implements IoProcessor { public void add(SerialSessionImpl session) { // It's already added when the session is constructed. } /** * {@inheritDoc} */ public void write(SerialSessionImpl session, WriteRequest writeRequest) { WriteRequestQueue writeRequestQueue = session.getWriteRequestQueue(); writeRequestQueue.offer(session, writeRequest); if (!session.isWriteSuspended()) { session.getProcessor().flush(session); } } /** * {@inheritDoc} */ public void flush(SerialSessionImpl session) { if (writeWorker == null) { writeWorker = new WriteWorker(); writeWorker.start(); } else { synchronized (writeMonitor) { writeMonitor.notifyAll(); } } } public void remove(SerialSessionImpl session) { try { inputStream.close(); } catch (IOException e) { ExceptionMonitor.getInstance().exceptionCaught(e); } try { outputStream.close(); } catch (IOException e) { ExceptionMonitor.getInstance().exceptionCaught(e); } try { // Turn flow control off right before close to avoid deadlock port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE); } catch (UnsupportedCommOperationException e) { ExceptionMonitor.getInstance().exceptionCaught(e); } port.close(); flush(session); synchronized (readReadyMonitor) { readReadyMonitor.notifyAll(); } serviceListeners.fireSessionDestroyed(SerialSessionImpl.this); } public void updateTrafficControl(SerialSessionImpl session) { throw new UnsupportedOperationException(); } public void dispose() { // Nothing to dispose } public boolean isDisposed() { return false; } public boolean isDisposing() { return false; } } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/SerialAddress.javamina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/SerialAddr0000644000175000017500000001472412032276011032701 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.serial; import gnu.io.SerialPort; import java.net.SocketAddress; import java.security.InvalidParameterException; /** * An address for a serial port communication. * * @author Apache MINA Project */ public class SerialAddress extends SocketAddress { private static final long serialVersionUID = 1735370510442384505L; public enum DataBits { DATABITS_5, DATABITS_6, DATABITS_7, DATABITS_8 } public enum Parity { NONE, ODD, EVEN, MARK, SPACE } public enum StopBits { BITS_1, BITS_2, BITS_1_5 } public enum FlowControl { NONE, RTSCTS_IN, RTSCTS_OUT, RTSCTS_IN_OUT, XONXOFF_IN, XONXOFF_OUT, XONXOFF_IN_OUT } private final String name; private final int bauds; private final DataBits dataBits; private final StopBits stopBits; private final Parity parity; private final FlowControl flowControl; /** * Create an address for a serial communication, associating a serial interface and * various serial signal carcteristics. * @param name name of the device, COM1 COM2 for Windows, /dev/ttyS0 for Unix * @param bauds baud rate for the communication * @param dataBits number of data bits per bytes * @param stopBits number of stop bits * @param parity parity used * @param flowControl flow control used */ public SerialAddress(String name, int bauds, DataBits dataBits, StopBits stopBits, Parity parity, FlowControl flowControl) { if (name == null) { throw new IllegalArgumentException("name"); } name = name.trim(); if (name.length() == 0) { throw new IllegalArgumentException("Empty name."); } if (bauds <= 0) { throw new IllegalArgumentException("bauds: " + bauds); } if (dataBits == null) { throw new IllegalArgumentException("dataBits"); } if (stopBits == null) { throw new IllegalArgumentException("stopBits"); } if (parity == null) { throw new IllegalArgumentException("parity"); } if (flowControl == null) { throw new IllegalArgumentException("flowControl"); } this.name = name; this.bauds = bauds; this.dataBits = dataBits; this.stopBits = stopBits; this.parity = parity; this.flowControl = flowControl; } /** * Bauds rate for the communication. * @return the bauds (bits per seconds) for this serial link */ public int getBauds() { return bauds; } /** * Number of data bits for each communicated bytes. * @return the data bits */ public DataBits getDataBits() { return dataBits; } /** * The flow control policie used for this communication. * @return the flow control */ public FlowControl getFlowControl() { return flowControl; } /** * The name of the device. Can be COM1, COM2, /dev/ttyS0, /dev/ttyUSB1, etc.. * @return name */ public String getName() { return name; } /** * The parity check for this communication. * @return parity type */ public Parity getParity() { return parity; } /** * Number of stop bits used. * @return stop bits number */ public StopBits getStopBits() { return stopBits; } /** * Convert this serial address to a human readable string. */ @Override public String toString() { return name + " (bauds: " + bauds + ", dataBits: " + dataBits + ", stopBits: " + stopBits + ", parity: " + parity + ", flowControl: " + flowControl + ")"; } int getDataBitsForRXTX() { switch (dataBits) { case DATABITS_5: return SerialPort.DATABITS_5; case DATABITS_6: return SerialPort.DATABITS_6; case DATABITS_7: return SerialPort.DATABITS_7; case DATABITS_8: return SerialPort.DATABITS_8; } throw new InvalidParameterException("broken databits"); } int getStopBitsForRXTX() { switch (stopBits) { case BITS_1: return SerialPort.STOPBITS_1; case BITS_1_5: return SerialPort.STOPBITS_1_5; case BITS_2: return SerialPort.STOPBITS_2; } throw new InvalidParameterException("broken stopbits"); } int getParityForRXTX() { switch (parity) { case EVEN: return SerialPort.PARITY_EVEN; case MARK: return SerialPort.PARITY_MARK; case NONE: return SerialPort.PARITY_NONE; case ODD: return SerialPort.PARITY_ODD; case SPACE: return SerialPort.PARITY_SPACE; } throw new InvalidParameterException("broken parity"); } int getFLowControlForRXTX() { switch (flowControl) { case NONE: return SerialPort.FLOWCONTROL_NONE; case RTSCTS_IN: return SerialPort.FLOWCONTROL_RTSCTS_IN; case RTSCTS_OUT: return SerialPort.FLOWCONTROL_RTSCTS_OUT; case RTSCTS_IN_OUT: return SerialPort.FLOWCONTROL_RTSCTS_IN | SerialPort.FLOWCONTROL_RTSCTS_OUT; case XONXOFF_IN: return SerialPort.FLOWCONTROL_XONXOFF_IN; case XONXOFF_OUT: return SerialPort.FLOWCONTROL_XONXOFF_OUT; case XONXOFF_IN_OUT: return SerialPort.FLOWCONTROL_XONXOFF_IN | SerialPort.FLOWCONTROL_XONXOFF_OUT; } throw new InvalidParameterException("broken flow control"); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/SerialSessionConfig.javamina2-2.0.7.orig/src/mina-transport-serial/src/main/java/org/apache/mina/transport/serial/SerialSess0000644000175000017500000000607212032276011032741 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.transport.serial; import org.apache.mina.core.session.IoSessionConfig; /** * An {@link IoSessionConfig} for serial transport type. * All those parameters are extracted from rxtx.org API for more details : * http://www.rxtx.org * @author Apache MINA Project */ public interface SerialSessionConfig extends IoSessionConfig { /** * Gets the input buffer size. Note that this method is advisory and the underlying OS * may choose not to report correct values for the buffer size. * @return input buffer size in bytes */ int getInputBufferSize(); /** * Sets the input buffer size. Note that this is advisory and memory availability may * determine the ultimate buffer size used by the driver. * @param bufferSize the buffer size in bytes */ void setInputBufferSize(int bufferSize); /** * Gets the output buffer size. Note that this method is advisory and the underlying OS * may choose not to report correct values for the buffer size. * @return input buffer size in bytes */ int getOutputBufferSize(); /** * Sets the output buffer size. Note that this is advisory and memory availability may * determine the ultimate buffer size used by the driver. * @param bufferSize the buffer size in bytes */ void setOutputBufferSize(int bufferSize); /** * Is the low latency mode is enabled. * @return low latency on */ boolean isLowLatency(); /** * Set the low latency mode, be carefull it's not supported by all the OS/hardware. * @param lowLatency */ void setLowLatency(boolean lowLatency); /** * The current receive threshold (-1 if not enabled). Give the value of the current buffer * needed for generate a new frame. * @return the receive thresold in bytes or -1 if disabled */ int getReceiveThreshold(); /** * Set the receive threshold in byte (set it to -1 for disable). The serial port will try to * provide frame of the given minimal byte count. Be carefull some devices doesn't support it. * @param bytes minimal amount of byte before producing a new frame, or -1 if disabled */ void setReceiveThreshold(int bytes); } mina2-2.0.7.orig/src/NOTICE-bin.txt0000644000175000017500000000221612032276040016071 0ustar ebourgebourgApache MINA Copyright 2007-2012 The Apache Software Foundation. This product includes software developed at The Apache Software Foundation (http://www.apache.org/). Please refer to each LICENSE..txt file for the license terms of the components that Apache MINA depends on. Message logging is provided by the SLF4J library package, which is open source software, written by Ceki Gülcü, and copyright by SLF4J.ORG and QOS.ch. The original software is available from http://www.slf4j.org/ Data compression support is provided by the JZLib library package, which is open source software, written by JCraft, and copyright by JCraft. The original software is available from http://www.jcraft.com/jzlib/ Spring framework is provided by the Spring framework library package, which is open source software, written by Rod Johnson et al, and copyright by Springframework.org. The original software is available from http://www.springframework.org/ OGNL is provided by the OGNL library package, which is open source software, written by Drew Davidson and Luke Blanshard. The original software is available from http://www.ognl.org/ mina2-2.0.7.orig/src/mina-integration-beans/0000755000175000017500000000000012162575507020151 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-beans/pom.xml.releaseBackup0000644000175000017500000000335212033674301024223 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7-SNAPSHOT mina-integration-beans Apache MINA JavaBeans Integration bundle ${project.groupId}.integration.beans ${project.groupId}.integration.beans ${project.groupId} mina-core ${project.version} bundle mina2-2.0.7.orig/src/mina-integration-beans/pom.xml0000644000175000017500000000334112033674306021461 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7 mina-integration-beans Apache MINA JavaBeans Integration bundle ${project.groupId}.integration.beans ${project.groupId}.integration.beans ${project.groupId} mina-core ${project.version} bundle mina2-2.0.7.orig/src/mina-integration-beans/src/0000755000175000017500000000000012032276011020720 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-beans/src/test/0000755000175000017500000000000012032276011021677 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-beans/src/test/java/0000755000175000017500000000000012032276011022620 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-beans/src/test/java/org/0000755000175000017500000000000012032276011023407 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-beans/src/test/java/org/apache/0000755000175000017500000000000012032276011024630 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-beans/src/test/java/org/apache/mina/0000755000175000017500000000000012032276011025554 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-beans/src/test/java/org/apache/mina/integration/0000755000175000017500000000000012032276011030077 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-beans/src/test/java/org/apache/mina/integration/beans/0000755000175000017500000000000012162575507031207 5ustar ebourgebourg././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/test/java/org/apache/mina/integration/beans/VmPipeAddressEditorTest.javamina2-2.0.7.orig/src/mina-integration-beans/src/test/java/org/apache/mina/integration/beans/VmPipeAd0000644000175000017500000000421112032276011032555 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import org.apache.mina.transport.vmpipe.VmPipeAddress; import org.junit.Before; import org.junit.Test; /** * Tests {@link VmPipeAddressEditor}. * * @author Apache MINA Project */ public class VmPipeAddressEditorTest { VmPipeAddressEditor editor; @Before public void setUp() throws Exception { editor = new VmPipeAddressEditor(); } @Test public void testSetAsTextWithLegalValues() throws Exception { editor.setAsText("1"); assertEquals(new VmPipeAddress(1), editor.getValue()); editor.setAsText(":10"); assertEquals(new VmPipeAddress(10), editor.getValue()); editor.setAsText(":100"); assertEquals(new VmPipeAddress(100), editor.getValue()); } @Test public void testSetAsTextWithIllegalValues() throws Exception { try { editor.setAsText("bar"); fail("Illegal port number. IllegalArgumentException expected."); } catch (IllegalArgumentException iae) { } try { editor.setAsText(":foo"); fail("Illegal port number. IllegalArgumentException expected."); } catch (IllegalArgumentException iae) { } } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/test/java/org/apache/mina/integration/beans/InetAddressEditorTest.javamina2-2.0.7.orig/src/mina-integration-beans/src/test/java/org/apache/mina/integration/beans/InetAddr0000644000175000017500000000372012032276011032606 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import static org.junit.Assert.assertEquals; import java.net.InetAddress; import java.net.UnknownHostException; import org.junit.Before; import org.junit.Test; /** * Tests {@link InetAddressEditor}. * * @author Apache MINA Project */ public class InetAddressEditorTest { InetAddressEditor editor; @Before public void setUp() throws Exception { editor = new InetAddressEditor(); } @Test public void testSetAsTextWithHostName() throws Exception { try { InetAddress expected = InetAddress.getByName("www.google.com"); editor.setAsText("www.google.com"); assertEquals(expected, editor.getValue()); } catch (UnknownHostException uhe) { // No DNS. Skip the test. } editor.setAsText("localhost"); assertEquals(InetAddress.getByName("localhost"), editor.getValue()); } @Test public void testSetAsTextWithIpAddress() throws Exception { editor.setAsText("127.0.0.1"); assertEquals(InetAddress.getByName("127.0.0.1"), editor.getValue()); } } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/test/java/org/apache/mina/integration/beans/InetSocketAddressEditorTest.javamina2-2.0.7.orig/src/mina-integration-beans/src/test/java/org/apache/mina/integration/beans/InetSock0000644000175000017500000000522612032276011032636 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.net.InetSocketAddress; import org.junit.Before; import org.junit.Test; /** * Tests {@link InetSocketAddressEditor}. * * @author Apache MINA Project */ public class InetSocketAddressEditorTest { InetSocketAddressEditor editor; @Before public void setUp() throws Exception { editor = new InetSocketAddressEditor(); } @Test public void testSetAsTextWithWildcardAddress() throws Exception { editor.setAsText("1"); assertEquals(new InetSocketAddress(1), editor.getValue()); editor.setAsText(":10"); assertEquals(new InetSocketAddress(10), editor.getValue()); } @Test public void testSetAsTextWithHostName() throws Exception { editor.setAsText("www.google.com:80"); assertEquals(new InetSocketAddress("www.google.com", 80), editor.getValue()); } public void testSetAsTextWithIpAddress() throws Exception { editor.setAsText("192.168.0.1:1000"); assertEquals(new InetSocketAddress("192.168.0.1", 1000), editor.getValue()); } @Test public void testSetAsTextWithIllegalValues() throws Exception { try { editor.setAsText("bar"); fail("Illegal port number. IllegalArgumentException expected."); } catch (IllegalArgumentException iae) { } try { editor.setAsText(":foo"); fail("Illegal port number. IllegalArgumentException expected."); } catch (IllegalArgumentException iae) { } try { editor.setAsText("www.foo.com:yada"); fail("Illegal port number. IllegalArgumentException expected."); } catch (IllegalArgumentException iae) { } } } mina2-2.0.7.orig/src/mina-integration-beans/src/main/0000755000175000017500000000000012032276011021644 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/0000755000175000017500000000000012032276011022565 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/0000755000175000017500000000000012032276011023354 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/0000755000175000017500000000000012032276011024575 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/0000755000175000017500000000000012032276011025521 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/0000755000175000017500000000000012032276011030044 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/0000755000175000017500000000000012162575507031154 5ustar ebourgebourg././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/FileEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/FileEdit0000644000175000017500000000256412032276012032554 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.io.File; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link File} and vice versa. * * @author Apache MINA Project */ public class FileEditor extends AbstractPropertyEditor { @Override protected String toText(Object value) { return ((File) value).getPath(); } @Override protected Object toValue(String text) throws IllegalArgumentException { return new File(text); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/CollectionEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/Collecti0000644000175000017500000001054112032276012032617 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.util.ArrayList; import java.util.Collection; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link Collection} and vice versa. * * @author Apache MINA Project */ public class CollectionEditor extends AbstractPropertyEditor { static final Pattern ELEMENT = Pattern.compile("([,\\s]+)|" + // Delimiter "(?<=\")((?:\\\\\"|\\\\'|\\\\\\\\|\\\\ |[^\"])*)(?=\")|" + "(?<=')((?:\\\\\"|\\\\'|\\\\\\\\|\\\\ |[^'])*)(?=')|" + "((?:[^\\\\\\s'\",]|\\\\ |\\\\\"|\\\\')+)"); private final Class elementType; public CollectionEditor(Class elementType) { if (elementType == null) { throw new IllegalArgumentException("elementType"); } this.elementType = elementType; getElementEditor(); setTrimText(false); } private PropertyEditor getElementEditor() { PropertyEditor e = PropertyEditorFactory.getInstance(elementType); if (e == null) { throw new IllegalArgumentException("No " + PropertyEditor.class.getSimpleName() + " found for " + elementType.getSimpleName() + '.'); } return e; } @Override @SuppressWarnings("unchecked") protected final String toText(Object value) { StringBuilder buf = new StringBuilder(); for (Object v : (Collection) value) { if (v == null) { v = defaultElement(); } PropertyEditor e = PropertyEditorFactory.getInstance(v); if (e == null) { throw new IllegalArgumentException("No " + PropertyEditor.class.getSimpleName() + " found for " + v.getClass().getSimpleName() + '.'); } e.setValue(v); // TODO normalize. String s = e.getAsText(); buf.append(s); buf.append(", "); } // Remove the last delimiter. if (buf.length() >= 2) { buf.setLength(buf.length() - 2); } return buf.toString(); } @Override protected final Object toValue(String text) throws IllegalArgumentException { PropertyEditor e = getElementEditor(); Collection answer = newCollection(); Matcher m = ELEMENT.matcher(text); boolean matchedDelimiter = true; while (m.find()) { if (m.group(1) != null) { matchedDelimiter = true; continue; } if (!matchedDelimiter) { throw new IllegalArgumentException("No delimiter between elements: " + text); } // TODO escape here. e.setAsText(m.group()); answer.add(e.getValue()); matchedDelimiter = false; if (m.group(2) != null || m.group(3) != null) { // Skip the last '"'. m.region(m.end() + 1, m.regionEnd()); } } return answer; } protected Collection newCollection() { return new ArrayList(); } protected Object defaultElement() { PropertyEditor e = PropertyEditorFactory.getInstance(elementType); if (e == null) { return null; } if (e instanceof AbstractPropertyEditor) { return ((AbstractPropertyEditor) e).defaultValue(); } return null; } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/InetSocketAddressEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/InetSock0000644000175000017500000000575112032276012032607 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.net.InetSocketAddress; /** * A {@link PropertyEditor} which converts a {@link String} into an * {@link InetSocketAddress}. Valid values include a hostname or IP * address and a port number separated by a ':'. If the hostname or IP address * is omitted the wildcard address will be used. E.g.: * google.com:80, :22, 192.168.0.1:110. * * @author Apache MINA Project * * @see java.net.InetSocketAddress */ public class InetSocketAddressEditor extends AbstractPropertyEditor { @Override protected String toText(Object value) { InetSocketAddress addr = ((InetSocketAddress) value); String hostname; if (addr.getAddress() != null) { hostname = addr.getAddress().getHostAddress(); } else { hostname = addr.getHostName(); } if (hostname.equals("0:0:0:0:0:0:0:0") || hostname.equals("0.0.0.0") || hostname.equals("00:00:00:00:00:00:00:00")) { hostname = "*"; } return hostname + ':' + addr.getPort(); } @Override protected Object toValue(String text) throws IllegalArgumentException { if (text.length() == 0) { return defaultValue(); } int colonIndex = text.lastIndexOf(":"); if (colonIndex > 0) { String host = text.substring(0, colonIndex); if (!"*".equals(host)) { int port = parsePort(text.substring(colonIndex + 1)); return new InetSocketAddress(host, port); } } int port = parsePort(text.substring(colonIndex + 1)); return new InetSocketAddress(port); } @Override protected String defaultText() { return "*:0"; } @Override protected Object defaultValue() { return new InetSocketAddress(0); } private int parsePort(String s) { try { return Integer.parseInt(s); } catch (NumberFormatException nfe) { throw new IllegalArgumentException("Illegal port number: " + s); } } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/ArrayEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/ArrayEdi0000644000175000017500000000772512032276012032573 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; /** * A {@link PropertyEditor} which converts a {@link String} into * a one-dimensional array and vice versa. * * @author Apache MINA Project */ public class ArrayEditor extends AbstractPropertyEditor { private final Class componentType; public ArrayEditor(Class componentType) { if (componentType == null) { throw new IllegalArgumentException("componentType"); } this.componentType = componentType; getComponentEditor(); setTrimText(false); } private PropertyEditor getComponentEditor() { PropertyEditor e = PropertyEditorFactory.getInstance(componentType); if (e == null) { throw new IllegalArgumentException("No " + PropertyEditor.class.getSimpleName() + " found for " + componentType.getSimpleName() + '.'); } return e; } @Override protected String toText(Object value) { Class componentType = value.getClass().getComponentType(); if (componentType == null) { throw new IllegalArgumentException("not an array: " + value); } PropertyEditor e = PropertyEditorFactory.getInstance(componentType); if (e == null) { throw new IllegalArgumentException("No " + PropertyEditor.class.getSimpleName() + " found for " + componentType.getSimpleName() + '.'); } StringBuilder buf = new StringBuilder(); for (int i = 0; i < Array.getLength(value); i++) { e.setValue(Array.get(value, i)); // TODO normalize. String s = e.getAsText(); buf.append(s); buf.append(", "); } // Remove the last delimiter. if (buf.length() >= 2) { buf.setLength(buf.length() - 2); } return buf.toString(); } @Override protected Object toValue(String text) throws IllegalArgumentException { PropertyEditor e = getComponentEditor(); List values = new ArrayList(); Matcher m = CollectionEditor.ELEMENT.matcher(text); boolean matchedDelimiter = true; while (m.find()) { if (m.group(1) != null) { matchedDelimiter = true; continue; } if (!matchedDelimiter) { throw new IllegalArgumentException("No delimiter between elements: " + text); } // TODO escape here. e.setAsText(m.group()); values.add(e.getValue()); matchedDelimiter = false; if (m.group(2) != null || m.group(3) != null) { // Skip the last '"'. m.region(m.end() + 1, m.regionEnd()); } } Object answer = Array.newInstance(componentType, values.size()); for (int i = 0; i < Array.getLength(answer); i++) { Array.set(answer, i, values.get(i)); } return answer; } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/BooleanEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/BooleanE0000644000175000017500000000346712032276012032556 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.util.regex.Pattern; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link Character} and vice versa. * * @author Apache MINA Project */ public class BooleanEditor extends AbstractPropertyEditor { private static final Pattern TRUE = Pattern.compile("(?:true|t|yes|y|1)", Pattern.CASE_INSENSITIVE); private static final Pattern FALSE = Pattern.compile("(?:false|f|no|n|1)", Pattern.CASE_INSENSITIVE); @Override protected String toText(Object value) { return String.valueOf(value); } @Override protected Object toValue(String text) throws IllegalArgumentException { if (TRUE.matcher(text).matches()) { return Boolean.TRUE; } if (FALSE.matcher(text).matches()) { return Boolean.FALSE; } throw new IllegalArgumentException("Wrong boolean value: " + text); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/NumberEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/NumberEd0000644000175000017500000000442012032276012032561 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.util.regex.Pattern; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link Number} and vice versa. * * @author Apache MINA Project */ public class NumberEditor extends AbstractPropertyEditor { private static final Pattern DECIMAL = Pattern.compile("[-+]?[0-9]*\\.?[0-9]*(?:[Ee][-+]?[0-9]+)?"); private static final Pattern HEXADECIMAL = Pattern.compile("0x[0-9a-fA-F]+"); private static final Pattern OCTET = Pattern.compile("0[0-9][0-9]*"); @Override protected final String toText(Object value) { return (value == null ? "" : value.toString()); } @Override protected final Object toValue(String text) throws IllegalArgumentException { if (text.length() == 0) { return defaultValue(); } if (HEXADECIMAL.matcher(text).matches()) { return toValue(text.substring(2), 16); } if (OCTET.matcher(text).matches()) { return toValue(text, 8); } if (DECIMAL.matcher(text).matches()) { return toValue(text, 10); } throw new NumberFormatException("Not a number: " + text); } protected Object toValue(String text, int radix) { return Integer.parseInt(text, radix); } @Override protected Object defaultValue() { return Integer.valueOf(0); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/NullEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/NullEdit0000644000175000017500000000306012032276012032577 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; /** * A dummy {@link PropertyEditor} for null. * * @author Apache MINA Project */ public class NullEditor extends AbstractPropertyEditor { @Override protected String toText(Object value) { if (String.valueOf(value).equalsIgnoreCase("null")) { return null; } throw new IllegalArgumentException("value is not null or 'null'."); } @Override protected Object toValue(String text) throws IllegalArgumentException { if (text.equalsIgnoreCase("null")) { return null; } throw new IllegalArgumentException("text is not null or 'null'."); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/DateEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/DateEdit0000644000175000017500000000541612032276012032551 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.regex.Pattern; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link Date} and vice versa. * * @author Apache MINA Project */ public class DateEditor extends AbstractPropertyEditor { private static final Pattern MILLIS = Pattern.compile("[0-9][0-9]*"); private final DateFormat[] formats = new DateFormat[] { new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z", Locale.ENGLISH), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH), new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH), new SimpleDateFormat("yyyy-MM", Locale.ENGLISH), new SimpleDateFormat("yyyy", Locale.ENGLISH), }; public DateEditor() { for (DateFormat f : formats) { f.setLenient(true); } } @Override protected String toText(Object value) { if (value instanceof Number) { long time = ((Number) value).longValue(); if (time <= 0) { return null; } value = new Date(time); } return formats[0].format((Date) value); } @Override protected Object toValue(String text) throws IllegalArgumentException { if (MILLIS.matcher(text).matches()) { long time = Long.parseLong(text); if (time <= 0) { return null; } return new Date(time); } for (DateFormat f : formats) { try { return f.parse(text); } catch (ParseException e) { } } throw new IllegalArgumentException("Wrong date: " + text); } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/AbstractPropertyEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/Abstract0000644000175000017500000000430412032276012032624 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.beans.PropertyEditorSupport; /** * An abstract bi-directional {@link PropertyEditor}. * * @author Apache MINA Project */ public abstract class AbstractPropertyEditor extends PropertyEditorSupport { private String text; private Object value; private boolean trimText = true; protected void setTrimText(boolean trimText) { this.trimText = trimText; } @Override public String getAsText() { return text; } @Override public Object getValue() { return value; } @Override public void setAsText(String text) throws IllegalArgumentException { this.text = text; if (text == null) { value = defaultValue(); } else { value = toValue(trimText ? text.trim() : text); } } @Override public void setValue(Object value) { this.value = value; if (value == null) { text = defaultText(); } else { text = toText(value); } } protected String defaultText() { return null; } protected Object defaultValue() { return null; } protected abstract String toText(Object value); protected abstract Object toValue(String text) throws IllegalArgumentException; } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/LongEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/LongEdit0000644000175000017500000000247512032276012032575 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link Long} and vice versa. * * @author Apache MINA Project */ public class LongEditor extends NumberEditor { @Override protected Object toValue(String text, int radix) { return Long.parseLong(text, radix); } @Override protected Object defaultValue() { return Long.valueOf(0); } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/CharacterEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/Characte0000644000175000017500000000353612032276012032601 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.util.regex.Pattern; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link Character} and vice versa. * * @author Apache MINA Project */ public class CharacterEditor extends AbstractPropertyEditor { private static final Pattern UNICODE = Pattern.compile("\\\\[uU][0-9a-fA-F]+"); @Override protected String toText(Object value) { return String.valueOf(value); } @Override protected Object toValue(String text) throws IllegalArgumentException { if (text.length() == 0) { return Character.valueOf(Character.MIN_VALUE); } if (UNICODE.matcher(text).matches()) { return Character.valueOf((char) Integer.parseInt(text.substring(2))); } if (text.length() != 1) { throw new IllegalArgumentException("Too many characters: " + text); } return Character.valueOf(text.charAt(0)); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/ShortEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/ShortEdi0000644000175000017500000000251212032276012032601 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link Short} and vice versa. * * @author Apache MINA Project */ public class ShortEditor extends NumberEditor { @Override protected Object toValue(String text, int radix) { return Short.parseShort(text, radix); } @Override protected Object defaultValue() { return Short.valueOf((short) 0); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/ByteEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/ByteEdit0000644000175000017500000000250512032276012032573 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; /** * A {@link PropertyEditor} which converts a {@link String} into * an {@link Byte} and vice versa. * * @author Apache MINA Project */ public class ByteEditor extends NumberEditor { @Override protected Object toValue(String text, int radix) { return Byte.parseByte(text, radix); } @Override protected Object defaultValue() { return Byte.valueOf((byte) 0); } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/VmPipeAddressEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/VmPipeAd0000644000175000017500000000401112032276012032521 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import org.apache.mina.transport.vmpipe.VmPipeAddress; import java.beans.PropertyEditor; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link VmPipeAddress} and vice versa. Valid values specify an integer port * number optionally prefixed with a ':'. E.g.: :80, 22. * * @author Apache MINA Project * * @see VmPipeAddress */ public class VmPipeAddressEditor extends AbstractPropertyEditor { @Override protected String toText(Object value) { return ":" + ((VmPipeAddress) value).getPort(); } @Override protected String defaultText() { return ":0"; } @Override protected Object defaultValue() { return new VmPipeAddress(0); } @Override protected Object toValue(String text) throws IllegalArgumentException { if (text.startsWith(":")) { text = text.substring(1); } try { return new VmPipeAddress(Integer.parseInt(text.trim())); } catch (NumberFormatException nfe) { throw new IllegalArgumentException("Illegal VmPipeAddress: " + text); } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/MapEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/MapEdito0000644000175000017500000001472312032276012032571 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link Collection} and vice versa. * * @author Apache MINA Project */ public class MapEditor extends AbstractPropertyEditor { static final Pattern ELEMENT = Pattern.compile("([,\\s]+)|" + // Entry delimiter "(\\s*=\\s*)|" + // Key-Value delimiter "(?<=\")((?:\\\\\"|\\\\'|\\\\\\\\|\\\\ |[^\"])*)(?=\")|" + "(?<=')((?:\\\\\"|\\\\'|\\\\\\\\|\\\\ |[^'])*)(?=')|" + "((?:[^\\\\\\s'\",]|\\\\ |\\\\\"|\\\\')+)"); private final Class keyType; private final Class valueType; public MapEditor(Class keyType, Class valueType) { if (keyType == null) { throw new IllegalArgumentException("keyType"); } if (valueType == null) { throw new IllegalArgumentException("valueType"); } this.keyType = keyType; this.valueType = valueType; getKeyEditor(); getValueEditor(); setTrimText(false); } private PropertyEditor getKeyEditor() { PropertyEditor e = PropertyEditorFactory.getInstance(keyType); if (e == null) { throw new IllegalArgumentException("No key " + PropertyEditor.class.getSimpleName() + " found for " + keyType.getSimpleName() + '.'); } return e; } private PropertyEditor getValueEditor() { PropertyEditor e = PropertyEditorFactory.getInstance(valueType); if (e == null) { throw new IllegalArgumentException("No value " + PropertyEditor.class.getSimpleName() + " found for " + valueType.getSimpleName() + '.'); } return e; } @Override @SuppressWarnings("unchecked") protected final String toText(Object value) { StringBuilder buf = new StringBuilder(); for (Object o : ((Map) value).entrySet()) { Map.Entry entry = (Map.Entry) o; Object ekey = entry.getKey(); Object evalue = entry.getValue(); PropertyEditor ekeyEditor = PropertyEditorFactory.getInstance(ekey); if (ekeyEditor == null) { throw new IllegalArgumentException("No key " + PropertyEditor.class.getSimpleName() + " found for " + ekey.getClass().getSimpleName() + '.'); } ekeyEditor.setValue(ekey); PropertyEditor evalueEditor = PropertyEditorFactory.getInstance(evalue); if (evalueEditor == null) { throw new IllegalArgumentException("No value " + PropertyEditor.class.getSimpleName() + " found for " + evalue.getClass().getSimpleName() + '.'); } ekeyEditor.setValue(ekey); evalueEditor.setValue(evalue); // TODO normalize. String keyString = ekeyEditor.getAsText(); String valueString = evalueEditor.getAsText(); buf.append(keyString); buf.append(" = "); buf.append(valueString); buf.append(", "); } // Remove the last delimiter. if (buf.length() >= 2) { buf.setLength(buf.length() - 2); } return buf.toString(); } @Override protected final Object toValue(String text) throws IllegalArgumentException { PropertyEditor keyEditor = getKeyEditor(); PropertyEditor valueEditor = getValueEditor(); Map answer = newMap(); Matcher m = ELEMENT.matcher(text); TokenType lastTokenType = TokenType.ENTRY_DELIM; Object key = null; Object value = null; while (m.find()) { if (m.group(1) != null) { switch (lastTokenType) { case VALUE: case ENTRY_DELIM: break; default: throw new IllegalArgumentException("Unexpected entry delimiter: " + text); } lastTokenType = TokenType.ENTRY_DELIM; continue; } if (m.group(2) != null) { if (lastTokenType != TokenType.KEY) { throw new IllegalArgumentException("Unexpected key-value delimiter: " + text); } lastTokenType = TokenType.KEY_VALUE_DELIM; continue; } // TODO escape here. String region = m.group(); if (m.group(3) != null || m.group(4) != null) { // Skip the last '"'. m.region(m.end() + 1, m.regionEnd()); } switch (lastTokenType) { case ENTRY_DELIM: keyEditor.setAsText(region); key = keyEditor.getValue(); lastTokenType = TokenType.KEY; break; case KEY_VALUE_DELIM: valueEditor.setAsText(region); value = valueEditor.getValue(); lastTokenType = TokenType.VALUE; answer.put(key, value); break; case KEY: case VALUE: throw new IllegalArgumentException("Unexpected key or value: " + text); } } return answer; } protected Map newMap() { return new LinkedHashMap(); } private static enum TokenType { ENTRY_DELIM, KEY_VALUE_DELIM, KEY, VALUE, } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/FloatEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/FloatEdi0000644000175000017500000000266112032276012032554 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; /** * A {@link PropertyEditor} which converts a {@link String} into * an {@link Float} and vice versa. * * @author Apache MINA Project */ public class FloatEditor extends NumberEditor { @Override protected Object toValue(String text, int radix) { if (radix != 10) { return Float.valueOf(String.valueOf(Long.parseLong(text, radix))); } return Float.parseFloat(text); } @Override protected Object defaultValue() { return Float.valueOf(0f); } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/URLEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/URLEdito0000644000175000017500000000307612032276012032515 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.net.MalformedURLException; import java.net.URL; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link URL} and vice versa. * * @author Apache MINA Project */ public class URLEditor extends AbstractPropertyEditor { @Override protected String toText(Object value) { return (value == null ? "" : ((URL) value).toString()); } @Override protected Object toValue(String text) throws IllegalArgumentException { try { return new URL(text); } catch (MalformedURLException e1) { throw new IllegalArgumentException("Wrong URL: " + text); } } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/StringEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/StringEd0000644000175000017500000000304212032276012032576 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; /** * A dummy {@link PropertyEditor} for a {@link String}. * * @author Apache MINA Project */ public class StringEditor extends AbstractPropertyEditor { @Override protected String toText(Object value) { if (value instanceof String) { return (String) value; } PropertyEditor e = PropertyEditorFactory.getInstance(value); if (e == null) { return String.valueOf(value); } e.setValue(value); return e.getAsText(); } @Override protected Object toValue(String text) throws IllegalArgumentException { return text; } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/PropertiesEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/Properti0000644000175000017500000000257012032276012032670 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.util.Map; import java.util.Properties; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link Properties} and vice versa. * * @author Apache MINA Project */ public class PropertiesEditor extends MapEditor { public PropertiesEditor() { super(String.class, String.class); setTrimText(false); } @Override protected Map newMap() { return new Properties(); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/EnumEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/EnumEdit0000644000175000017500000000446112032276012032577 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.util.EnumSet; import java.util.Set; import java.util.regex.Pattern; /** * A {@link PropertyEditor} which converts a {@link String} into * an {@link Enum} and vice versa. * * @author Apache MINA Project */ @SuppressWarnings("unchecked") public class EnumEditor extends AbstractPropertyEditor { private static final Pattern ORDINAL = Pattern.compile("[0-9]+"); private final Class enumType; private final Set enums; public EnumEditor(Class enumType) { if (enumType == null) { throw new IllegalArgumentException("enumType"); } this.enumType = enumType; this.enums = EnumSet.allOf(enumType); } @Override protected String toText(Object value) { return (value == null ? "" : value.toString()); } @Override protected Object toValue(String text) throws IllegalArgumentException { if (ORDINAL.matcher(text).matches()) { int ordinal = Integer.parseInt(text); for (Enum e : enums) { if (e.ordinal() == ordinal) { return e; } } throw new IllegalArgumentException("wrong ordinal: " + ordinal); } for (Enum e : enums) { if (text.equalsIgnoreCase(e.toString())) { return e; } } return Enum.valueOf(enumType, text); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/ClassEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/ClassEdi0000644000175000017500000000330512032276012032550 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link Character} and vice versa. * * @author Apache MINA Project */ public class ClassEditor extends AbstractPropertyEditor { @Override @SuppressWarnings("unchecked") protected String toText(Object value) { return ((Class) value).getName(); } @Override protected Object toValue(String text) throws IllegalArgumentException { try { return Class.forName(text); } catch (ClassNotFoundException e) { try { return getClass().getClassLoader().loadClass(text); } catch (ClassNotFoundException e1) { throw new IllegalArgumentException("Failed to load the class: " + text); } } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/SetEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/SetEdito0000644000175000017500000000260412032276012032602 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.util.Collection; import java.util.LinkedHashSet; import java.util.Set; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link Set} and vice versa. * * @author Apache MINA Project */ public class SetEditor extends CollectionEditor { public SetEditor(Class elementType) { super(elementType); } @Override protected Collection newCollection() { return new LinkedHashSet(); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/DoubleEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/DoubleEd0000644000175000017500000000266712032276012032556 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; /** * A {@link PropertyEditor} which converts a {@link String} into * an {@link Double} and vice versa. * * @author Apache MINA Project */ public class DoubleEditor extends NumberEditor { @Override protected Object toValue(String text, int radix) { if (radix != 10) { return Double.valueOf(String.valueOf(Long.parseLong(text, radix))); } return Double.parseDouble(text); } @Override protected Object defaultValue() { return Double.valueOf(0f); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/ListEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/ListEdit0000644000175000017500000000260012032276012032577 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link List} and vice versa. * * @author Apache MINA Project */ public class ListEditor extends CollectionEditor { public ListEditor(Class elementType) { super(elementType); } @Override protected Collection newCollection() { return new ArrayList(); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/InetAddressEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/InetAddr0000644000175000017500000000472212032276012032557 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.net.InetAddress; import java.net.UnknownHostException; /** * A {@link PropertyEditor} which converts a {@link String} into an * {@link InetAddress}. * This editor simply calls {@link InetAddress#getByName(java.lang.String)} * when converting from a {@link String}, and {@link InetAddress#getHostAddress()} * when converting to a {@link String}. * * @author Apache MINA Project * * @see java.net.InetAddress */ public class InetAddressEditor extends AbstractPropertyEditor { @Override protected String toText(Object value) { String hostname = ((InetAddress) value).getHostAddress(); if (hostname.equals("0:0:0:0:0:0:0:0") || hostname.equals("0.0.0.0") || hostname.equals("00:00:00:00:00:00:00:00")) { hostname = "*"; } return hostname; } @Override protected Object toValue(String text) throws IllegalArgumentException { if (text.length() == 0 || text.equals("*")) { return defaultValue(); } try { return InetAddress.getByName(text); } catch (UnknownHostException uhe) { IllegalArgumentException iae = new IllegalArgumentException(); iae.initCause(uhe); throw iae; } } @Override protected String defaultText() { return "*"; } @Override protected Object defaultValue() { try { return InetAddress.getByName("0.0.0.0"); } catch (UnknownHostException e) { throw new InternalError(); } } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/IntegerEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/IntegerE0000644000175000017500000000251112032276012032561 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; /** * A {@link PropertyEditor} which converts a {@link String} into * an {@link Integer} and vice versa. * * @author Apache MINA Project */ public class IntegerEditor extends NumberEditor { @Override protected Object toValue(String text, int radix) { return Integer.parseInt(text, radix); } @Override protected Object defaultValue() { return Integer.valueOf(0); } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/URIEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/URIEdito0000644000175000017500000000306712032276012032512 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.net.URI; import java.net.URISyntaxException; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link URI} and vice versa. * * @author Apache MINA Project */ public class URIEditor extends AbstractPropertyEditor { @Override protected String toText(Object value) { return (value == null ? "" : ((URI) value).toString()); } @Override protected Object toValue(String text) throws IllegalArgumentException { try { return new URI(text); } catch (URISyntaxException e) { throw new IllegalArgumentException("Wrong URI: " + text); } } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/PropertyEditorFactory.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/Property0000644000175000017500000001165412032276012032713 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; /** * A factory that creates a new {@link PropertyEditor} which is appropriate for * the specified object or class. * * @author Apache MINA Project */ public final class PropertyEditorFactory { @SuppressWarnings("unchecked") public static PropertyEditor getInstance(Object object) { if (object == null) { return new NullEditor(); } if (object instanceof Collection) { Class elementType = null; for (Object e : (Collection) object) { if (e != null) { elementType = e.getClass(); break; } } if (elementType != null) { if (object instanceof Set) { return new SetEditor(elementType); } if (object instanceof List) { return new ListEditor(elementType); } return new CollectionEditor(elementType); } } if (object instanceof Map) { Class keyType = null; Class valueType = null; for (Object entry : ((Map) object).entrySet()) { Map.Entry e = (Map.Entry) entry; if (e.getKey() != null && e.getValue() != null) { keyType = e.getKey().getClass(); valueType = e.getValue().getClass(); break; } } if (keyType != null && valueType != null) { return new MapEditor(keyType, valueType); } } return getInstance(object.getClass()); } // parent type / property name / property type public static PropertyEditor getInstance(Class type) { if (type == null) { throw new IllegalArgumentException("type"); } if (type.isEnum()) { return new EnumEditor(type); } if (type.isArray()) { return new ArrayEditor(type.getComponentType()); } if (Collection.class.isAssignableFrom(type)) { if (Set.class.isAssignableFrom(type)) { return new SetEditor(String.class); } if (List.class.isAssignableFrom(type)) { return new ListEditor(String.class); } return new CollectionEditor(String.class); } if (Map.class.isAssignableFrom(type)) { return new MapEditor(String.class, String.class); } if (Properties.class.isAssignableFrom(type)) { return new PropertiesEditor(); } type = filterPrimitiveType(type); try { return (PropertyEditor) PropertyEditorFactory.class .getClassLoader() .loadClass( PropertyEditorFactory.class.getPackage().getName() + '.' + type.getSimpleName() + "Editor") .newInstance(); } catch (Exception e) { return null; } } private static Class filterPrimitiveType(Class type) { if (type.isPrimitive()) { if (type == boolean.class) { type = Boolean.class; } if (type == byte.class) { type = Byte.class; } if (type == char.class) { type = Character.class; } if (type == double.class) { type = Double.class; } if (type == float.class) { type = Float.class; } if (type == int.class) { type = Integer.class; } if (type == long.class) { type = Long.class; } if (type == short.class) { type = Short.class; } } return type; } private PropertyEditorFactory() { } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/PatternEditor.javamina2-2.0.7.orig/src/mina-integration-beans/src/main/java/org/apache/mina/integration/beans/PatternE0000644000175000017500000000261712032276012032610 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.integration.beans; import java.beans.PropertyEditor; import java.util.regex.Pattern; /** * A {@link PropertyEditor} which converts a {@link String} into * a {@link Pattern} and vice versa. * * @author Apache MINA Project */ public class PatternEditor extends AbstractPropertyEditor { @Override protected String toText(Object value) { return ((Pattern) value).pattern(); } @Override protected Object toValue(String text) throws IllegalArgumentException { return Pattern.compile(text); } } mina2-2.0.7.orig/src/mina-statemachine/0000755000175000017500000000000012162575507017205 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-statemachine/pom.xml.releaseBackup0000644000175000017500000000404512033674301023257 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7-SNAPSHOT mina-statemachine Apache MINA State Machine bundle ${project.groupId}.statemachine ${project.groupId}.statemachine ${project.groupId} ${project.version} mina-core true bundle commons-lang commons-lang com.agical.rmock rmock ${version.rmock} test mina2-2.0.7.orig/src/mina-statemachine/pom.xml0000644000175000017500000000403412033674306020515 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7 mina-statemachine Apache MINA State Machine bundle ${project.groupId}.statemachine ${project.groupId}.statemachine ${project.groupId} ${project.version} mina-core true bundle commons-lang commons-lang com.agical.rmock rmock ${version.rmock} test mina2-2.0.7.orig/src/mina-statemachine/src/0000755000175000017500000000000012032276005017757 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-statemachine/src/test/0000755000175000017500000000000012032276004020735 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-statemachine/src/test/java/0000755000175000017500000000000012032276004021656 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/0000755000175000017500000000000012032276004022445 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/apache/0000755000175000017500000000000012032276004023666 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/apache/mina/0000755000175000017500000000000012032276004024612 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/apache/mina/statemachine/0000755000175000017500000000000012162575507027275 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/apache/mina/statemachine/context/0000755000175000017500000000000012162575507030761 5ustar ebourgebourg././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/apache/mina/statemachine/context/AbstractStateContextLookupTest.javamina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/apache/mina/statemachine/context/AbstractSt0000644000175000017500000000455112032276004032745 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.context; import static org.junit.Assert.assertSame; import java.util.HashMap; import java.util.Map; import org.junit.Test; /** * Tests {@link AbstractStateContextLookup}. * * @author Apache MINA Project */ public class AbstractStateContextLookupTest { @Test public void testLookup() throws Exception { Map map = new HashMap(); AbstractStateContextLookup lookup = new AbstractStateContextLookup(new DefaultStateContextFactory()) { protected boolean supports(Class c) { return Map.class.isAssignableFrom(c); } @SuppressWarnings("unchecked") protected StateContext lookup(Object eventArg) { Map map = (Map) eventArg; return map.get("context"); } @SuppressWarnings("unchecked") protected void store(Object eventArg, StateContext context) { Map map = (Map) eventArg; map.put("context", context); } }; Object[] args1 = new Object[] { new Object(), map, new Object() }; Object[] args2 = new Object[] { map, new Object() }; StateContext sc = lookup.lookup(args1); assertSame(map.get("context"), sc); assertSame(map.get("context"), lookup.lookup(args1)); assertSame(map.get("context"), lookup.lookup(args2)); } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/apache/mina/statemachine/StateMachineProxyBuilderTest.javamina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/apache/mina/statemachine/StateMachineProxyB0000644000175000017500000002446212032276005032724 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.util.LinkedList; import org.apache.mina.statemachine.annotation.Transition; import org.apache.mina.statemachine.annotation.Transitions; import org.apache.mina.statemachine.annotation.OnEntry; import org.apache.mina.statemachine.annotation.OnExit; import org.apache.mina.statemachine.context.StateContext; import org.apache.mina.statemachine.event.Event; import org.apache.mina.statemachine.transition.MethodSelfTransition; import org.apache.mina.statemachine.transition.MethodTransition; import org.junit.Test; /** * Tests {@link StateMachineProxyBuilder}. * * @author Apache MINA Project */ public class StateMachineProxyBuilderTest { @Test public void testReentrantStateMachine() throws Exception { ReentrantStateMachineHandler handler = new ReentrantStateMachineHandler(); State s1 = new State("s1"); State s2 = new State("s2"); State s3 = new State("s3"); s1.addTransition(new MethodTransition("call1", s2, handler)); s2.addTransition(new MethodTransition("call2", s3, handler)); s3.addTransition(new MethodTransition("call3", handler)); StateMachine sm = new StateMachine(new State[] { s1, s2, s3 }, "s1"); Reentrant reentrant = new StateMachineProxyBuilder().create(Reentrant.class, sm); reentrant.call1(reentrant); assertTrue(handler.finished); } @Test public void testTapeDeckStateMachine() throws Exception { TapeDeckStateMachineHandler handler = new TapeDeckStateMachineHandler(); State parent = new State("parent"); State s1 = new State("s1", parent); State s2 = new State("s2", parent); State s3 = new State("s3", parent); State s4 = new State("s4", parent); State s5 = new State("s5", parent); parent.addTransition(new MethodTransition("*", "error", handler)); s1.addTransition(new MethodTransition("insert", s2, "inserted", handler)); s2.addTransition(new MethodTransition("start", s3, "playing", handler)); s3.addTransition(new MethodTransition("stop", s4, "stopped", handler)); s3.addTransition(new MethodTransition("pause", s5, "paused", handler)); s4.addTransition(new MethodTransition("eject", s1, "ejected", handler)); s5.addTransition(new MethodTransition("pause", s3, "playing", handler)); s2.addOnEntrySelfTransaction(new MethodSelfTransition("onEntryS2", handler)); s2.addOnExitSelfTransaction(new MethodSelfTransition("onExitS2", handler)); s3.addOnEntrySelfTransaction(new MethodSelfTransition("onEntryS3", handler)); s3.addOnExitSelfTransaction(new MethodSelfTransition("onExitS3", handler)); s4.addOnEntrySelfTransaction(new MethodSelfTransition("onEntryS4", handler)); s4.addOnExitSelfTransaction(new MethodSelfTransition("onExitS4", handler)); StateMachine sm = new StateMachine(new State[] { s1, s2, s3, s4, s5 }, "s1"); TapeDeck player = new StateMachineProxyBuilder().create(TapeDeck.class, sm); player.insert("Kings of convenience - Riot on an empty street"); player.start(); player.pause(); player.pause(); player.eject(); player.stop(); player.eject(); LinkedList messages = handler.messages; assertEquals("Tape 'Kings of convenience - Riot on an empty street' inserted", messages.removeFirst()); assertEquals("S2 entered", messages.removeFirst()); assertEquals("Playing", messages.removeFirst()); assertEquals("S2 exited", messages.removeFirst()); assertEquals("S3 entered with stateContext", messages.removeFirst()); assertEquals("Paused", messages.removeFirst()); assertEquals("S3 exited with stateContext", messages.removeFirst()); assertEquals("Playing", messages.removeFirst()); assertEquals("S3 entered with stateContext", messages.removeFirst()); assertEquals("Error: Cannot eject at this time", messages.removeFirst()); assertEquals("Stopped", messages.removeFirst()); assertEquals("S3 exited with stateContext", messages.removeFirst()); assertEquals("S4 entered with stateContext and state", messages.removeFirst()); assertEquals("Tape ejected", messages.removeFirst()); assertEquals("S4 exited with stateContext and state", messages.removeFirst()); assertTrue(messages.isEmpty()); } @Test public void testTapeDeckStateMachineAnnotations() throws Exception { TapeDeckStateMachineHandler handler = new TapeDeckStateMachineHandler(); StateMachine sm = StateMachineFactory.getInstance(Transition.class).create(TapeDeckStateMachineHandler.S1, handler); TapeDeck player = new StateMachineProxyBuilder().create(TapeDeck.class, sm); player.insert("Kings of convenience - Riot on an empty street"); player.start(); player.pause(); player.pause(); player.eject(); player.stop(); player.eject(); LinkedList messages = handler.messages; assertEquals("Tape 'Kings of convenience - Riot on an empty street' inserted", messages.removeFirst()); assertEquals("S2 entered", messages.removeFirst()); assertEquals("Playing", messages.removeFirst()); assertEquals("S2 exited", messages.removeFirst()); assertEquals("S3 entered with stateContext", messages.removeFirst()); assertEquals("Paused", messages.removeFirst()); assertEquals("S3 exited with stateContext", messages.removeFirst()); assertEquals("Playing", messages.removeFirst()); assertEquals("S3 entered with stateContext", messages.removeFirst()); assertEquals("Error: Cannot eject at this time", messages.removeFirst()); assertEquals("Stopped", messages.removeFirst()); assertEquals("S3 exited with stateContext", messages.removeFirst()); assertEquals("S4 entered with stateContext and state", messages.removeFirst()); assertEquals("Tape ejected", messages.removeFirst()); assertEquals("S4 exited with stateContext and state", messages.removeFirst()); assertTrue(messages.isEmpty()); } public interface Reentrant { void call1(Reentrant proxy); void call2(Reentrant proxy); void call3(Reentrant proxy); } public static class ReentrantStateMachineHandler { private boolean finished = false; public void call1(Reentrant proxy) { proxy.call2(proxy); } public void call2(Reentrant proxy) { proxy.call3(proxy); } public void call3(Reentrant proxy) { finished = true; } } public interface TapeDeck { void insert(String name); void eject(); void start(); void pause(); void stop(); } public static class TapeDeckStateMachineHandler { @org.apache.mina.statemachine.annotation.State public static final String PARENT = "parent"; @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S1 = "s1"; @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S2 = "s2"; @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S3 = "s3"; @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S4 = "s4"; @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S5 = "s5"; private LinkedList messages = new LinkedList(); @OnEntry(S2) public void onEntryS2() { messages.add("S2 entered"); } @OnExit(S2) public void onExitS2() { messages.add("S2 exited"); } @OnEntry(S3) public void onEntryS3(StateContext stateContext) { messages.add("S3 entered with stateContext"); } @OnExit(S3) public void onExitS3(StateContext stateContext) { messages.add("S3 exited with stateContext"); } @OnEntry(S4) public void onEntryS4(StateContext stateContext, State state) { messages.add("S4 entered with stateContext and state"); } @OnExit(S4) public void onExitS4(StateContext stateContext, State state) { messages.add("S4 exited with stateContext and state"); } @Transition(on = "insert", in = "s1", next = "s2") public void inserted(String name) { messages.add("Tape '" + name + "' inserted"); } @Transition(on = "eject", in = "s4", next = "s1") public void ejected() { messages.add("Tape ejected"); } @Transitions({ @Transition(on = "start", in = "s2", next = "s3"), @Transition(on = "pause", in = "s5", next = "s3") }) public void playing() { messages.add("Playing"); } @Transition(on = "pause", in = "s3", next = "s5") public void paused() { messages.add("Paused"); } @Transition(on = "stop", in = "s3", next = "s4") public void stopped() { messages.add("Stopped"); } @Transition(on = "*", in = "parent") public void error(Event event) { messages.add("Error: Cannot " + event.getId() + " at this time"); } } } mina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/apache/mina/statemachine/StateTest.java0000644000175000017500000000656312032276005032055 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine; import org.apache.mina.statemachine.State; import org.apache.mina.statemachine.transition.Transition; import org.junit.BeforeClass; import org.junit.Test; import com.agical.rmock.extension.junit.RMockTestCase; /** * Tests {@link State}. * * @author Apache MINA Project */ public class StateTest extends RMockTestCase { State state; Transition transition1; Transition transition2; Transition transition3; @BeforeClass protected void setUp() throws Exception { state = new State("test"); transition1 = (Transition) mock(Transition.class); transition2 = transition1; //(Transition) mock(Transition.class); transition3 = transition1; //(Transition) mock(Transition.class); } @Test public void testAddFirstTransition() throws Exception { assertTrue(state.getTransitions().isEmpty()); state.addTransition(transition1); assertFalse(state.getTransitions().isEmpty()); assertEquals(1, state.getTransitions().size()); assertSame(transition1, state.getTransitions().get(0)); } @Test public void testUnweightedTransitions() throws Exception { assertTrue(state.getTransitions().isEmpty()); state.addTransition(transition1); state.addTransition(transition2); state.addTransition(transition3); assertEquals(3, state.getTransitions().size()); assertSame(transition1, state.getTransitions().get(0)); assertSame(transition2, state.getTransitions().get(1)); assertSame(transition3, state.getTransitions().get(2)); } @Test public void testWeightedTransitions() throws Exception { assertTrue(state.getTransitions().isEmpty()); state.addTransition(transition1, 10); state.addTransition(transition2, 5); state.addTransition(transition3, 7); assertEquals(3, state.getTransitions().size()); assertSame(transition2, state.getTransitions().get(0)); assertSame(transition3, state.getTransitions().get(1)); assertSame(transition1, state.getTransitions().get(2)); } @Test public void testAddTransitionReturnsSelf() throws Exception { assertSame(state, state.addTransition(transition1)); } @Test public void testAddNullTransitionThrowsException() throws Exception { try { state.addTransition(null); fail("null transition added. IllegalArgumentException expected."); } catch (IllegalArgumentException npe) { } } } mina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/apache/mina/statemachine/transition/0000755000175000017500000000000012162575507031467 5ustar ebourgebourg././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/apache/mina/statemachine/transition/MethodTransitionTest.javamina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/apache/mina/statemachine/transition/MethodT0000644000175000017500000001400012032276004032733 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.transition; import java.lang.reflect.Method; import org.apache.mina.statemachine.State; import org.apache.mina.statemachine.context.StateContext; import org.apache.mina.statemachine.event.Event; import org.apache.mina.statemachine.transition.MethodTransition; import com.agical.rmock.extension.junit.RMockTestCase; /** * Tests {@link MethodTransition}. * * @author Apache MINA Project */ public class MethodTransitionTest extends RMockTestCase { State currentState; State nextState; TestStateContext context; Target target; Method subsetAllArgsMethod1; Method subsetAllArgsMethod2; Event noArgsEvent; Event argsEvent; Object[] args; protected void setUp() throws Exception { super.setUp(); currentState = new State("current"); nextState = new State("next"); target = (Target) mock(Target.class); subsetAllArgsMethod1 = Target.class.getMethod("subsetAllArgs", new Class[] { TestStateContext.class, B.class, A.class, Integer.TYPE }); subsetAllArgsMethod2 = Target.class.getMethod("subsetAllArgs", new Class[] { Event.class, B.class, B.class, Boolean.TYPE }); args = new Object[] { new A(), new B(), new C(), new Integer(627438), Boolean.TRUE }; context = (TestStateContext) mock(TestStateContext.class); noArgsEvent = new Event("event", context, new Object[0]); argsEvent = new Event("event", context, args); } public void testExecuteWrongEventId() throws Exception { startVerification(); MethodTransition t = new MethodTransition("otherEvent", nextState, "noArgs", target); assertFalse(t.execute(noArgsEvent)); } public void testExecuteNoArgsMethodOnNoArgsEvent() throws Exception { target.noArgs(); startVerification(); MethodTransition t = new MethodTransition("event", nextState, "noArgs", target); assertTrue(t.execute(noArgsEvent)); } public void testExecuteNoArgsMethodOnArgsEvent() throws Exception { target.noArgs(); startVerification(); MethodTransition t = new MethodTransition("event", nextState, "noArgs", target); assertTrue(t.execute(argsEvent)); } public void testExecuteExactArgsMethodOnNoArgsEvent() throws Exception { startVerification(); MethodTransition t = new MethodTransition("event", nextState, "exactArgs", target); assertFalse(t.execute(noArgsEvent)); } public void testExecuteExactArgsMethodOnArgsEvent() throws Exception { target.exactArgs((A) args[0], (B) args[1], (C) args[2], ((Integer) args[3]).intValue(), ((Boolean) args[4]).booleanValue()); startVerification(); MethodTransition t = new MethodTransition("event", nextState, "exactArgs", target); assertTrue(t.execute(argsEvent)); } public void testExecuteSubsetExactArgsMethodOnNoArgsEvent() throws Exception { startVerification(); MethodTransition t = new MethodTransition("event", nextState, "subsetExactArgs", target); assertFalse(t.execute(noArgsEvent)); } public void testExecuteSubsetExactArgsMethodOnArgsEvent() throws Exception { target.subsetExactArgs((A) args[0], (A) args[1], ((Integer) args[3]).intValue()); startVerification(); MethodTransition t = new MethodTransition("event", nextState, "subsetExactArgs", target); assertTrue(t.execute(argsEvent)); } public void testExecuteAllArgsMethodOnArgsEvent() throws Exception { target.allArgs(argsEvent, context, (A) args[0], (B) args[1], (C) args[2], ((Integer) args[3]).intValue(), ((Boolean) args[4]).booleanValue()); startVerification(); MethodTransition t = new MethodTransition("event", nextState, "allArgs", target); assertTrue(t.execute(argsEvent)); } public void testExecuteSubsetAllArgsMethod1OnArgsEvent() throws Exception { target.subsetAllArgs(context, (B) args[1], (A) args[2], ((Integer) args[3]).intValue()); startVerification(); MethodTransition t = new MethodTransition("event", nextState, subsetAllArgsMethod1, target); assertTrue(t.execute(argsEvent)); } public void testExecuteSubsetAllArgsMethod2OnArgsEvent() throws Exception { target.subsetAllArgs(argsEvent, (B) args[1], (B) args[2], ((Boolean) args[4]).booleanValue()); startVerification(); MethodTransition t = new MethodTransition("event", nextState, subsetAllArgsMethod2, target); assertTrue(t.execute(argsEvent)); } public interface Target { void noArgs(); void exactArgs(A a, B b, C c, int integer, boolean bool); void allArgs(Event event, StateContext ctxt, A a, B b, C c, int integer, boolean bool); void subsetExactArgs(A a, A b, int integer); void subsetAllArgs(TestStateContext ctxt, B b, A c, int integer); void subsetAllArgs(Event event, B b, B c, boolean bool); } public interface TestStateContext extends StateContext { } public static class A { } public static class B extends A { } public static class C extends B { } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/apache/mina/statemachine/StateMachineFactoryTest.javamina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/apache/mina/statemachine/StateMachineFactor0000644000175000017500000001437012032276005032714 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; import java.lang.reflect.Method; import java.util.List; import org.apache.mina.statemachine.annotation.Transition; import org.apache.mina.statemachine.annotation.Transitions; import org.apache.mina.statemachine.transition.MethodTransition; import org.junit.Before; import org.junit.Test; /** * Tests {@link StateMachineFactory}. * * @author Apache MINA Project */ public class StateMachineFactoryTest { Method barInA; Method error; Method fooInA; Method fooInB; Method barInC; Method fooOrBarInCOrFooInD; @Before public void setUp() throws Exception { barInA = States.class.getDeclaredMethod("barInA", new Class[0]); error = States.class.getDeclaredMethod("error", new Class[0]); fooInA = States.class.getDeclaredMethod("fooInA", new Class[0]); fooInB = States.class.getDeclaredMethod("fooInB", new Class[0]); barInC = States.class.getDeclaredMethod("barInC", new Class[0]); fooOrBarInCOrFooInD = States.class.getDeclaredMethod("fooOrBarInCOrFooInD", new Class[0]); } @Test public void testCreate() throws Exception { States states = new States(); StateMachine sm = StateMachineFactory.getInstance(Transition.class).create(States.A, states); State a = sm.getState(States.A); State b = sm.getState(States.B); State c = sm.getState(States.C); State d = sm.getState(States.D); assertEquals(States.A, a.getId()); assertNull(a.getParent()); assertEquals(States.B, b.getId()); assertSame(a, b.getParent()); assertEquals(States.C, c.getId()); assertSame(b, c.getParent()); assertEquals(States.D, d.getId()); assertSame(a, d.getParent()); List trans = null; trans = a.getTransitions(); assertEquals(3, trans.size()); assertEquals(new MethodTransition("bar", barInA, states), trans.get(0)); assertEquals(new MethodTransition("*", error, states), trans.get(1)); assertEquals(new MethodTransition("foo", b, fooInA, states), trans.get(2)); trans = b.getTransitions(); assertEquals(1, trans.size()); assertEquals(new MethodTransition("foo", c, fooInB, states), trans.get(0)); trans = c.getTransitions(); assertEquals(3, trans.size()); assertEquals(new MethodTransition("bar", a, barInC, states), trans.get(0)); assertEquals(new MethodTransition("foo", d, fooOrBarInCOrFooInD, states), trans.get(1)); assertEquals(new MethodTransition("bar", d, fooOrBarInCOrFooInD, states), trans.get(2)); trans = d.getTransitions(); assertEquals(1, trans.size()); assertEquals(new MethodTransition("foo", fooOrBarInCOrFooInD, states), trans.get(0)); } @Test public void testCreateStates() throws Exception { State[] states = StateMachineFactory.createStates(StateMachineFactory.getFields(States.class)); assertEquals(States.A, states[0].getId()); assertNull(states[0].getParent()); assertEquals(States.B, states[1].getId()); assertEquals(states[0], states[1].getParent()); assertEquals(States.C, states[2].getId()); assertEquals(states[1], states[2].getParent()); assertEquals(States.D, states[3].getId()); assertEquals(states[0], states[3].getParent()); } @Test public void testCreateStatesMissingParents() throws Exception { try { StateMachineFactory.createStates(StateMachineFactory.getFields(StatesWithMissingParents.class)); fail("Missing parents. FsmCreationException expected."); } catch (StateMachineCreationException fce) { } } public static class States { @org.apache.mina.statemachine.annotation.State protected static final String A = "a"; @org.apache.mina.statemachine.annotation.State(A) protected static final String B = "b"; @org.apache.mina.statemachine.annotation.State(B) protected static final String C = "c"; @org.apache.mina.statemachine.annotation.State(A) protected static final String D = "d"; @Transition(on = "bar", in = A) protected void barInA() { } @Transition(on = "bar", in = C, next = A) protected void barInC() { } @Transition(in = A) protected void error() { } @Transition(on = "foo", in = A, next = B) protected void fooInA() { } @Transition(on = "foo", in = B, next = C) protected void fooInB() { } @Transitions({ @Transition(on = { "foo", "bar" }, in = C, next = D), @Transition(on = "foo", in = D) }) protected void fooOrBarInCOrFooInD() { } } public static class StatesWithMissingParents { @org.apache.mina.statemachine.annotation.State("b") public static final String A = "a"; @org.apache.mina.statemachine.annotation.State("c") public static final String B = "b"; @org.apache.mina.statemachine.annotation.State("d") public static final String C = "c"; @org.apache.mina.statemachine.annotation.State("e") public static final String D = "d"; } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/apache/mina/statemachine/StateMachineTest.javamina2-2.0.7.orig/src/mina-statemachine/src/test/java/org/apache/mina/statemachine/StateMachineTest.j0000644000175000017500000001422212032276005032641 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import org.apache.mina.statemachine.context.DefaultStateContext; import org.apache.mina.statemachine.context.StateContext; import org.apache.mina.statemachine.event.Event; import org.apache.mina.statemachine.transition.AbstractSelfTransition; import org.apache.mina.statemachine.transition.AbstractTransition; import org.junit.Test; /** * Tests {@link StateMachine}. * * @author Apache MINA Project */ public class StateMachineTest { @Test public void testBreakAndContinue() throws Exception { State s1 = new State("s1"); s1.addTransition(new BreakAndContinueTransition("foo")); s1.addTransition(new SuccessTransition("foo")); StateContext context = new DefaultStateContext(); StateMachine sm = new StateMachine(new State[] { s1 }, "s1"); sm.handle(new Event("foo", context)); assertEquals(true, context.getAttribute("success")); } @Test public void testBreakAndGotoNow() throws Exception { State s1 = new State("s1"); State s2 = new State("s2"); s1.addTransition(new BreakAndGotoNowTransition("foo", "s2")); s2.addTransition(new SuccessTransition("foo")); StateContext context = new DefaultStateContext(); StateMachine sm = new StateMachine(new State[] { s1, s2 }, "s1"); sm.handle(new Event("foo", context)); assertEquals(true, context.getAttribute("success")); } @Test public void testBreakAndGotoNext() throws Exception { State s1 = new State("s1"); State s2 = new State("s2"); s1.addTransition(new BreakAndGotoNextTransition("foo", "s2")); s2.addTransition(new SuccessTransition("foo")); StateContext context = new DefaultStateContext(); StateMachine sm = new StateMachine(new State[] { s1, s2 }, "s1"); sm.handle(new Event("foo", context)); assertSame(s2, context.getCurrentState()); sm.handle(new Event("foo", context)); assertEquals(true, context.getAttribute("success")); } private static class SuccessTransition extends AbstractTransition { public SuccessTransition(Object eventId) { super(eventId); } public SuccessTransition(Object eventId, State nextState) { super(eventId, nextState); } @Override protected boolean doExecute(Event event) { event.getContext().setAttribute("success", true); return true; } } private static class BreakAndContinueTransition extends AbstractTransition { public BreakAndContinueTransition(Object eventId) { super(eventId); } public BreakAndContinueTransition(Object eventId, State nextState) { super(eventId, nextState); } @Override protected boolean doExecute(Event event) { StateControl.breakAndContinue(); return true; } } private static class BreakAndGotoNowTransition extends AbstractTransition { private final String stateId; public BreakAndGotoNowTransition(Object eventId, String stateId) { super(eventId); this.stateId = stateId; } public BreakAndGotoNowTransition(Object eventId, State nextState, String stateId) { super(eventId, nextState); this.stateId = stateId; } @Override protected boolean doExecute(Event event) { StateControl.breakAndGotoNow(stateId); return true; } } private static class BreakAndGotoNextTransition extends AbstractTransition { private final String stateId; public BreakAndGotoNextTransition(Object eventId, String stateId) { super(eventId); this.stateId = stateId; } public BreakAndGotoNextTransition(Object eventId, State nextState, String stateId) { super(eventId, nextState); this.stateId = stateId; } @Override protected boolean doExecute(Event event) { StateControl.breakAndGotoNext(stateId); return true; } } private static class SampleSelfTransition extends AbstractSelfTransition { @SuppressWarnings("unused") public SampleSelfTransition() { super(); } @Override protected boolean doExecute(StateContext stateContext, State state) { stateContext.setAttribute("SelfSuccess" + state.getId(), true); return true; } } @Test public void testOnEntry() throws Exception { State s1 = new State("s1"); State s2 = new State("s2"); s1.addTransition(new SuccessTransition("foo", s2)); s1.addOnExitSelfTransaction(new SampleSelfTransition()); s2.addOnEntrySelfTransaction(new SampleSelfTransition()); StateContext context = new DefaultStateContext(); StateMachine sm = new StateMachine(new State[] { s1, s2 }, "s1"); sm.handle(new Event("foo", context)); assertEquals(true, context.getAttribute("success")); assertEquals(true, context.getAttribute("SelfSuccess" + s1.getId())); assertEquals(true, context.getAttribute("SelfSuccess" + s2.getId())); } } mina2-2.0.7.orig/src/mina-statemachine/src/main/0000755000175000017500000000000012032276005020703 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-statemachine/src/main/java/0000755000175000017500000000000012032276005021624 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/0000755000175000017500000000000012032276005022413 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/0000755000175000017500000000000012032276005023634 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/0000755000175000017500000000000012032276005024560 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/0000755000175000017500000000000012162575507027242 5ustar ebourgebourg././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/StateMachineCreationException.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/StateMachineCreati0000644000175000017500000000314312032276010032642 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine; /** * Exception thrown by {@link StateMachineFactory} when a {@link StateMachine} * could not be constructed for some reason. * * @author Apache MINA Project */ public class StateMachineCreationException extends RuntimeException { private static final long serialVersionUID = 4103502727376992746L; /** * Creates a new instance. * * @param message the message. */ public StateMachineCreationException(String message) { super(message); } /** /** * Creates a new instance. * * @param message the message. * @param cause the cause. */ public StateMachineCreationException(String message, Throwable cause) { super(message, cause); } } mina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/0000755000175000017500000000000012162575507030726 5ustar ebourgebourg././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/StateContext.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/StateConte0000644000175000017500000000430612032276006032711 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.context; import org.apache.mina.statemachine.State; import org.apache.mina.statemachine.StateMachine; /** * {@link StateContext} objects are used to store the current {@link State} and * any application specific attributes for a specific client of a * {@link StateMachine}. Since {@link StateMachine}s are singletons and shared * by all clients using the {@link StateMachine} this is where client specific * data needs to be stored. * * @author Apache MINA Project */ public interface StateContext { /** * Returns the current {@link State}. This is only meant for internal use. * * @return the current {@link State}. */ State getCurrentState(); /** * Sets the current {@link State}. This is only meant for internal use. * Don't call it directly! * * @param state the new current {@link State}. */ void setCurrentState(State state); /** * Returns the value of the attribute with the specified key or * nullif not found. * * @param key the key. * @return the value or null. */ Object getAttribute(Object key); /** * Sets the value of the attribute with the specified key. * * @param key the key. * @param value the value. */ void setAttribute(Object key, Object value); } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/SingletonStateContextLookup.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/SingletonS0000644000175000017500000000367312032276006032733 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.context; /** * {@link StateContextLookup} implementation which always returns the same * {@link StateContext} instance. * * @author Apache MINA Project */ public class SingletonStateContextLookup implements StateContextLookup { private final StateContext context; /** * Creates a new instance which always returns the same * {@link DefaultStateContext} instance. */ public SingletonStateContextLookup() { context = new DefaultStateContext(); } /** * Creates a new instance which uses the specified {@link StateContextFactory} * to create the single instance. * * @param contextFactory the {@link StateContextFactory} to use to create * the singleton instance. */ public SingletonStateContextLookup(StateContextFactory contextFactory) { if (contextFactory == null) { throw new IllegalArgumentException("contextFactory"); } context = contextFactory.create(); } public StateContext lookup(Object[] eventArgs) { return context; } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/IoSessionStateContextLookup.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/IoSessionS0000644000175000017500000000720012032276006032672 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.context; import org.apache.mina.core.session.IoSession; /** * MINA specific {@link StateContextLookup} which uses an {@link IoSession} * attribute to store the {@link StateContextLookup}. * * @author Apache MINA Project */ public class IoSessionStateContextLookup extends AbstractStateContextLookup { /** * The default name of the {@link IoSession} attribute used to store the * {@link StateContext} object. */ public static final String DEFAULT_SESSION_ATTRIBUTE_NAME = IoSessionStateContextLookup.class.getName() + ".stateContext"; private final String sessionAttributeName; /** * Creates a new instance using a {@link DefaultStateContextFactory} to * create {@link StateContext} objects for new {@link IoSession}s. */ public IoSessionStateContextLookup() { this(new DefaultStateContextFactory(), DEFAULT_SESSION_ATTRIBUTE_NAME); } /** * Creates a new instance using a {@link DefaultStateContextFactory} to * create {@link StateContext} objects for new {@link IoSession}s. * * @param sessionAttributeName the name of the {@link IoSession} attribute * used to store the {@link StateContext} object. */ public IoSessionStateContextLookup(String sessionAttributeName) { this(new DefaultStateContextFactory(), sessionAttributeName); } /** * Creates a new instance using the specified {@link StateContextFactory} to * create {@link StateContext} objects for new {@link IoSession}s. * * @param contextFactory the {@link StateContextFactory}. */ public IoSessionStateContextLookup(StateContextFactory contextFactory) { this(contextFactory, DEFAULT_SESSION_ATTRIBUTE_NAME); } /** * Creates a new instance using the specified {@link StateContextFactory} to * create {@link StateContext} objects for new {@link IoSession}s. * * @param contextFactory the {@link StateContextFactory}. * @param sessionAttributeName the name of the {@link IoSession} attribute * used to store the {@link StateContext} object. */ public IoSessionStateContextLookup(StateContextFactory contextFactory, String sessionAttributeName) { super(contextFactory); this.sessionAttributeName = sessionAttributeName; } protected StateContext lookup(Object eventArg) { IoSession session = (IoSession) eventArg; return (StateContext) session.getAttribute(sessionAttributeName); } protected void store(Object eventArg, StateContext context) { IoSession session = (IoSession) eventArg; session.setAttribute(sessionAttributeName, context); } protected boolean supports(Class c) { return IoSession.class.isAssignableFrom(c); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/StateContextFactory.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/StateConte0000644000175000017500000000225612032276006032713 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.context; /** * Factory which creates {@link StateContext} instances. * * @author Apache MINA Project */ public interface StateContextFactory { /** * Creates a new {@link StateContext}. * * @return the newly created {@link StateContext}. */ StateContext create(); } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/AbstractStateContextLookup.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/AbstractSt0000644000175000017500000000677512032276006032726 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.context; /** * Abstract {@link StateContextLookup} implementation. The {@link #lookup(Object[])} * method will loop through the event arguments and call the {@link #supports(Class)} * method for each of them. The first argument that this method returns * true for will be passed to the abstract {@link #lookup(Object)} * method which should try to extract a {@link StateContext} from the argument. * If none is found a new {@link StateContext} will be created and stored in the * event argument using the {@link #store(Object, StateContext)} method. * * @author Apache MINA Project */ public abstract class AbstractStateContextLookup implements StateContextLookup { private final StateContextFactory contextFactory; /** * Creates a new instance which uses the specified {@link StateContextFactory} * to create {@link StateContext} objects. * * @param contextFactory the factory. */ public AbstractStateContextLookup(StateContextFactory contextFactory) { if (contextFactory == null) { throw new IllegalArgumentException("contextFactory"); } this.contextFactory = contextFactory; } public StateContext lookup(Object[] eventArgs) { for (int i = 0; i < eventArgs.length; i++) { if (supports(eventArgs[i].getClass())) { StateContext sc = lookup(eventArgs[i]); if (sc == null) { sc = contextFactory.create(); store(eventArgs[i], sc); } return sc; } } return null; } /** * Extracts a {@link StateContext} from the specified event argument which * is an instance of a class {@link #supports(Class)} returns * true for. * * @param eventArg the event argument. * @return the {@link StateContext}. */ protected abstract StateContext lookup(Object eventArg); /** * Stores a new {@link StateContext} in the specified event argument which * is an instance of a class {@link #supports(Class)} returns * true for. * * @param eventArg the event argument. * @param context the {@link StateContext} to be stored. */ protected abstract void store(Object eventArg, StateContext context); /** * Must return true for any {@link Class} that this * {@link StateContextLookup} can use to store and lookup * {@link StateContext} objects. * * @param c the class. * @return true or false. */ protected abstract boolean supports(Class c); } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/StateContextLookup.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/StateConte0000644000175000017500000000277712032276006032723 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.context; import org.apache.mina.statemachine.event.Event; /** * Lookups a {@link StateContext} from a collection of event arguments. * * @author Apache MINA Project */ public interface StateContextLookup { /** * Searches the arguments from an {@link Event} and returns a * {@link StateContext} if any of the arguments holds one. NOTE! This method * must create a new {@link StateContext} if a compatible object is in * the arguments and the next time that same object is passed to this * method the same {@link StateContext} should be returned. */ StateContext lookup(Object[] eventArgs); } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/DefaultStateContext.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/DefaultSta0000644000175000017500000000205112032276006032667 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.context; /** * Default {@link StateContext} implementation. * * @author Apache MINA Project */ public class DefaultStateContext extends AbstractStateContext { } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/AbstractStateContext.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/AbstractSt0000644000175000017500000000402312032276006032706 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.context; import java.util.HashMap; import java.util.Map; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.mina.statemachine.State; /** * Abstract {@link StateContext} which uses a {@link Map} to store the * attributes. * * @author Apache MINA Project */ public abstract class AbstractStateContext implements StateContext { private State currentState = null; private Map attributes = null; public Object getAttribute(Object key) { return getAttributes().get(key); } public State getCurrentState() { return currentState; } public void setAttribute(Object key, Object value) { getAttributes().put(key, value); } public void setCurrentState(State state) { currentState = state; } protected Map getAttributes() { if (attributes == null) { attributes = new HashMap(); } return attributes; } public String toString() { return new ToStringBuilder(this).append("currentState", currentState).append("attributes", attributes) .toString(); } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/DefaultStateContextFactory.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/context/DefaultSta0000644000175000017500000000225412032276006032674 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.context; /** * {@link StateContextFactory} which creates {@link DefaultStateContext} * objects. * * @author Apache MINA Project */ public class DefaultStateContextFactory implements StateContextFactory { public StateContext create() { return new DefaultStateContext(); } } mina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/State.java0000644000175000017500000001636212032276010031154 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.mina.statemachine.event.Event; import org.apache.mina.statemachine.transition.SelfTransition; import org.apache.mina.statemachine.transition.Transition; /** * Represents a state in a {@link StateMachine}. Normally you wouldn't create * instances of this class directly but rather use the * {@link org.apache.mina.statemachine.annotation.State} annotation to define * your states and then let {@link StateMachineFactory} create a * {@link StateMachine} for you. *

* {@link State}s inherits {@link Transition}s from * their parent. A {@link State} can override any of the parents * {@link Transition}s. When an {@link Event} is processed the {@link Transition}s * of the current {@link State} will be searched for a {@link Transition} which * can handle the event. If none is found the {@link State}'s parent will be * searched and so on. *

* * @author Apache MINA Project */ public class State { private final String id; private final State parent; private List transitionHolders = new ArrayList(); private List transitions = Collections.emptyList(); private List onEntries = new ArrayList(); private List onExits = new ArrayList(); /** * Creates a new {@link State} with the specified id. * * @param id the unique id of this {@link State}. */ public State(String id) { this(id, null); } /** * Creates a new {@link State} with the specified id and parent. * * @param id the unique id of this {@link State}. * @param parent the parent {@link State}. */ public State(String id, State parent) { this.id = id; this.parent = parent; } /** * Returns the id of this {@link State}. * * @return the id. */ public String getId() { return id; } /** * Returns the parent {@link State}. * * @return the parent or null if this {@link State} has no * parent. */ public State getParent() { return parent; } /** * Returns an unmodifiable {@link List} of {@link Transition}s going out * from this {@link State}. * * @return the {@link Transition}s. */ public List getTransitions() { return Collections.unmodifiableList(transitions); } /** * Returns an unmodifiable {@link List} of entry {@link SelfTransition}s * * @return the {@link SelfTransition}s. */ public List getOnEntrySelfTransitions() { return Collections.unmodifiableList(onEntries); } /** * Returns an unmodifiable {@link List} of exit {@link SelfTransition}s * * @return the {@link SelfTransition}s. */ public List getOnExitSelfTransitions() { return Collections.unmodifiableList(onExits); } /** * Adds an entry {@link SelfTransition} to this {@link State} * * @param selfTransition the {@link SelfTransition} to add. * @return this {@link State}. */ State addOnEntrySelfTransaction(SelfTransition onEntrySelfTransaction) { if (onEntrySelfTransaction == null) { throw new IllegalArgumentException("transition"); } onEntries.add(onEntrySelfTransaction); return this; } /** * Adds an exit {@link SelfTransition} to this {@link State} * * @param selfTransition the {@link SelfTransition} to add. * @return this {@link State}. */ State addOnExitSelfTransaction(SelfTransition onExitSelfTransaction) { if (onExitSelfTransaction == null) { throw new IllegalArgumentException("transition"); } onExits.add(onExitSelfTransaction); return this; } private void updateTransitions() { transitions = new ArrayList(transitionHolders.size()); for (TransitionHolder holder : transitionHolders) { transitions.add(holder.transition); } } /** * Adds an outgoing {@link Transition} to this {@link State} with weight 0. * * @param transition the {@link Transition} to add. * @return this {@link State}. * @see #addTransition(Transition, int) */ public State addTransition(Transition transition) { return addTransition(transition, 0); } /** * Adds an outgoing {@link Transition} to this {@link State} with the * specified weight. The higher the weight the less important a * {@link Transition} is. If two {@link Transition}s match the same * {@link Event} the {@link Transition} with the lower weight will * be executed. * * @param transition the {@link Transition} to add. * @return this {@link State}. */ public State addTransition(Transition transition, int weight) { if (transition == null) { throw new IllegalArgumentException("transition"); } transitionHolders.add(new TransitionHolder(transition, weight)); Collections.sort(transitionHolders); updateTransitions(); return this; } @Override public boolean equals(Object o) { if (!(o instanceof State)) { return false; } if (o == this) { return true; } State that = (State) o; return new EqualsBuilder().append(this.id, that.id).isEquals(); } @Override public int hashCode() { return new HashCodeBuilder(13, 33).append(this.id).toHashCode(); } @Override public String toString() { return new ToStringBuilder(this).append("id", this.id).toString(); } private static class TransitionHolder implements Comparable { Transition transition; int weight; TransitionHolder(Transition transition, int weight) { this.transition = transition; this.weight = weight; } public int compareTo(TransitionHolder o) { return (weight > o.weight) ? 1 : (weight < o.weight ? -1 : 0); } } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/BreakAndCallException.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/BreakAndCallExcept0000644000175000017500000000345612032276010032570 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine; /** * Exception used internally by {@link StateControl}. * * @author Apache MINA Project */ class BreakAndCallException extends BreakException { private static final long serialVersionUID = -5973306926764652458L; private final String stateId; private final String returnToStateId; private final boolean now; public BreakAndCallException(String stateId, boolean now) { this(stateId, null, now); } public BreakAndCallException(String stateId, String returnToStateId, boolean now) { if (stateId == null) { throw new IllegalArgumentException("stateId"); } this.stateId = stateId; this.returnToStateId = returnToStateId; this.now = now; } public boolean isNow() { return now; } public String getStateId() { return stateId; } public String getReturnToStateId() { return returnToStateId; } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/BreakAndContinueException.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/BreakAndContinueEx0000644000175000017500000000215012032276010032613 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine; /** * Exception used internally by {@link StateControl}. * * @author Apache MINA Project */ class BreakAndContinueException extends BreakException { private static final long serialVersionUID = -6166471981111377775L; } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/BreakAndReturnException.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/BreakAndReturnExce0000644000175000017500000000241712032276010032624 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine; /** * Exception used internally by {@link StateControl}. * * @author Apache MINA Project */ class BreakAndReturnException extends BreakException { private static final long serialVersionUID = -2662100444922292796L; private final boolean now; public BreakAndReturnException(boolean now) { this.now = now; } public boolean isNow() { return now; } } mina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/StateControl.java0000644000175000017500000001420112032276010032503 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine; import org.apache.mina.statemachine.event.Event; import org.apache.mina.statemachine.transition.Transition; /** * Allows for programmatic control of a state machines execution. *

* The *Now() family of methods move to a new {@link State} * immediately and let the new {@link State} handle the current {@link Event}. * The *Next() family on the other hand let the new {@link State} * handle the next {@link Event} which is generated which make these method the * programmatic equivalent of using the {@link org.apache.mina.statemachine.annotation.Transition} annotation. *

*

* Using the breakAndCall*() and breakAndReturn* methods one * can create sub state machines which behave very much like sub routines. * When calling a state the current state (or the specified returnTo * state) will be pushed on a stack. When returning from a state the last pushed * state will be popped from the stack and used as the new state. *

* * @author Apache MINA Project */ public class StateControl { /** * Breaks the execution of the current {@link Transition} and tries to * find another {@link Transition} with higher weight or a {@link Transition} * of a parent {@link State} which can handle the current {@link Event}. */ public static void breakAndContinue() { throw new BreakAndContinueException(); } /** * Breaks the execution of the current {@link Transition} and lets the * {@link State} with the specified id handle the current {@link Event}. * * @param state the id of the {@link State} to go to. */ public static void breakAndGotoNow(String state) { throw new BreakAndGotoException(state, true); } /** * Breaks the execution of the current {@link Transition} and lets the * {@link State} with the specified id handle the next {@link Event}. * Using this method is the programmatic equivalent of using the * {@link org.apache.mina.statemachine.annotation.Transition} annotation. * * @param state the id of the {@link State} to go to. */ public static void breakAndGotoNext(String state) { throw new BreakAndGotoException(state, false); } /** * Breaks the execution of the current {@link Transition} and lets the * {@link State} with the specified id handle the current {@link Event}. * Before moving to the new state the current state will be recorded. The * next call to {@link #breakAndReturnNow()} or {@link #breakAndReturnNext()} * will return to the current state. * * @param state the id of the {@link State} to call. */ public static void breakAndCallNow(String state) { throw new BreakAndCallException(state, true); } /** * Breaks the execution of the current {@link Transition} and lets the * {@link State} with the specified id handle the next {@link Event}. * Before moving to the new state the current state will be recorded. The * next call to {@link #breakAndReturnNow()} or {@link #breakAndReturnNext()} * will return to the current state. * * @param state the id of the {@link State} to call. */ public static void breakAndCallNext(String state) { throw new BreakAndCallException(state, false); } /** * Breaks the execution of the current {@link Transition} and lets the * {@link State} with the specified id handle the current {@link Event}. * Before moving to the new state the current state will be recorded. The * next call to {@link #breakAndReturnNow()} or {@link #breakAndReturnNext()} * will return to the specified returnTo state. * * @param state the id of the {@link State} to call. * @param returnTo the id of the {@link State} to return to. */ public static void breakAndCallNow(String state, String returnTo) { throw new BreakAndCallException(state, returnTo, true); } /** * Breaks the execution of the current {@link Transition} and lets the * {@link State} with the specified id handle the next {@link Event}. * Before moving to the new state the current state will be recorded. The * next call to {@link #breakAndReturnNow()} or {@link #breakAndReturnNext()} * will return to the specified returnTo state. * * @param state the id of the {@link State} to call. * @param returnTo the id of the {@link State} to return to. */ public static void breakAndCallNext(String state, String returnTo) { throw new BreakAndCallException(state, returnTo, false); } /** * Breaks the execution of the current {@link Transition} and lets the * last recorded {@link State} handle the current {@link Event}. */ public static void breakAndReturnNow() { throw new BreakAndReturnException(true); } /** * Breaks the execution of the current {@link Transition} and lets the * last recorded {@link State} handle the next {@link Event}. */ public static void breakAndReturnNext() { throw new BreakAndReturnException(false); } } mina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/StateMachine.java0000644000175000017500000003012312032276010032430 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Stack; import org.apache.mina.statemachine.context.StateContext; import org.apache.mina.statemachine.event.Event; import org.apache.mina.statemachine.event.UnhandledEventException; import org.apache.mina.statemachine.transition.SelfTransition; import org.apache.mina.statemachine.transition.Transition; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Represents a complete state machine. Contains a collection of {@link State} * objects connected by {@link Transition}s. Normally you wouldn't create * instances of this class directly but rather use the * {@link org.apache.mina.statemachine.annotation.State} annotation to define * your states and then let {@link StateMachineFactory} create a * {@link StateMachine} for you. * * @author Apache MINA Project */ public class StateMachine { private static final Logger LOGGER = LoggerFactory.getLogger(StateMachine.class); private static final String CALL_STACK = StateMachine.class.getName() + ".callStack"; private final State startState; private final Map states; private final ThreadLocal processingThreadLocal = new ThreadLocal() { protected Boolean initialValue() { return Boolean.FALSE; } }; private final ThreadLocal> eventQueueThreadLocal = new ThreadLocal>() { protected LinkedList initialValue() { return new LinkedList(); } }; /** * Creates a new instance using the specified {@link State}s and start * state. * * @param states the {@link State}s. * @param startStateId the id of the start {@link State}. */ public StateMachine(State[] states, String startStateId) { this.states = new HashMap(); for (State s : states) { this.states.put(s.getId(), s); } this.startState = getState(startStateId); } /** * Creates a new instance using the specified {@link State}s and start * state. * * @param states the {@link State}s. * @param startStateId the id of the start {@link State}. */ public StateMachine(Collection states, String startStateId) { this(states.toArray(new State[0]), startStateId); } /** * Returns the {@link State} with the specified id. * * @param id the id of the {@link State} to return. * @return the {@link State} * @throws NoSuchStateException if no matching {@link State} could be found. */ public State getState(String id) throws NoSuchStateException { State state = states.get(id); if (state == null) { throw new NoSuchStateException(id); } return state; } /** * Returns an unmodifiable {@link Collection} of all {@link State}s used by * this {@link StateMachine}. * * @return the {@link State}s. */ public Collection getStates() { return Collections.unmodifiableCollection(states.values()); } /** * Processes the specified {@link Event} through this {@link StateMachine}. * Normally you wouldn't call this directly but rather use * {@link StateMachineProxyBuilder} to create a proxy for an interface of * your choice. Any method calls on the proxy will be translated into * {@link Event} objects and then fed to the {@link StateMachine} by the * proxy using this method. * * @param event the {@link Event} to be handled. */ public void handle(Event event) { StateContext context = event.getContext(); synchronized (context) { LinkedList eventQueue = eventQueueThreadLocal.get(); eventQueue.addLast(event); if (processingThreadLocal.get()) { /* * This thread is already processing an event. Queue this * event. */ if (LOGGER.isDebugEnabled()) { LOGGER.debug("State machine called recursively. Queuing event " + event + " for later processing."); } } else { processingThreadLocal.set(true); try { if (context.getCurrentState() == null) { context.setCurrentState(startState); } processEvents(eventQueue); } finally { processingThreadLocal.set(false); } } } } private void processEvents(LinkedList eventQueue) { while (!eventQueue.isEmpty()) { Event event = eventQueue.removeFirst(); StateContext context = event.getContext(); handle(context.getCurrentState(), event); } } private void handle(State state, Event event) { StateContext context = event.getContext(); for (Transition t : state.getTransitions()) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Trying transition " + t); } try { if (t.execute(event)) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Transition " + t + " executed successfully."); } setCurrentState(context, t.getNextState()); return; } } catch (BreakAndContinueException bace) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("BreakAndContinueException thrown in " + "transition " + t + ". Continuing with next transition."); } } catch (BreakAndGotoException bage) { State newState = getState(bage.getStateId()); if (bage.isNow()) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("BreakAndGotoException thrown in " + "transition " + t + ". Moving to state " + newState.getId() + " now."); } setCurrentState(context, newState); handle(newState, event); } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug("BreakAndGotoException thrown in " + "transition " + t + ". Moving to state " + newState.getId() + " next."); } setCurrentState(context, newState); } return; } catch (BreakAndCallException bace) { State newState = getState(bace.getStateId()); Stack callStack = getCallStack(context); State returnTo = bace.getReturnToStateId() != null ? getState(bace.getReturnToStateId()) : context .getCurrentState(); callStack.push(returnTo); if (bace.isNow()) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("BreakAndCallException thrown in " + "transition " + t + ". Moving to state " + newState.getId() + " now."); } setCurrentState(context, newState); handle(newState, event); } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug("BreakAndCallException thrown in " + "transition " + t + ". Moving to state " + newState.getId() + " next."); } setCurrentState(context, newState); } return; } catch (BreakAndReturnException bare) { Stack callStack = getCallStack(context); State newState = callStack.pop(); if (bare.isNow()) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("BreakAndReturnException thrown in " + "transition " + t + ". Moving to state " + newState.getId() + " now."); } setCurrentState(context, newState); handle(newState, event); } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug("BreakAndReturnException thrown in " + "transition " + t + ". Moving to state " + newState.getId() + " next."); } setCurrentState(context, newState); } return; } } /* * No transition could handle the event. Try with the parent state if * there is one. */ if (state.getParent() != null) { handle(state.getParent(), event); } else { throw new UnhandledEventException(event); } } private Stack getCallStack(StateContext context) { @SuppressWarnings("unchecked") Stack callStack = (Stack) context.getAttribute(CALL_STACK); if (callStack == null) { callStack = new Stack(); context.setAttribute(CALL_STACK, callStack); } return callStack; } private void setCurrentState(StateContext context, State newState) { if (newState != null) { if (LOGGER.isDebugEnabled()) { if (newState != context.getCurrentState()) { LOGGER.debug("Leaving state " + context.getCurrentState().getId()); LOGGER.debug("Entering state " + newState.getId()); } } executeOnExits(context, context.getCurrentState()); executeOnEntries(context, newState); context.setCurrentState(newState); } } void executeOnExits(StateContext context, State state) { List onExits = state.getOnExitSelfTransitions(); boolean isExecuted = false; if (onExits != null) for (SelfTransition selfTransition : onExits) { selfTransition.execute(context, state); if (LOGGER.isDebugEnabled()) { isExecuted = true; LOGGER.debug("Executing onEntry action for " + state.getId()); } } if (LOGGER.isDebugEnabled() && !isExecuted) { LOGGER.debug("No onEntry action for " + state.getId()); } } void executeOnEntries(StateContext context, State state) { List onEntries = state.getOnEntrySelfTransitions(); boolean isExecuted = false; if (onEntries != null) for (SelfTransition selfTransition : onEntries) { selfTransition.execute(context, state); if (LOGGER.isDebugEnabled()) { isExecuted = true; LOGGER.debug("Executing onExit action for " + state.getId()); } } if (LOGGER.isDebugEnabled() && !isExecuted) { LOGGER.debug("No onEntry action for " + state.getId()); } } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/BreakException.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/BreakException.jav0000644000175000017500000000261312032276010032630 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine; /** * The base exception of the exceptions thrown by the methods in the * {@link StateControl} class. If you use any of the {@link StateControl} * methods to change the execution of a {@link StateMachine} you must make sure * that exceptions of this type aren't caught and swallowed by your code. * * @author Apache MINA Project */ public class BreakException extends RuntimeException { private static final long serialVersionUID = -1898782004087949199L; protected BreakException() { } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/StateMachineFactory.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/StateMachineFactor0000644000175000017500000004301612032276010032654 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.mina.statemachine.annotation.OnEntry; import org.apache.mina.statemachine.annotation.OnExit; import org.apache.mina.statemachine.annotation.Transition; import org.apache.mina.statemachine.annotation.TransitionAnnotation; import org.apache.mina.statemachine.annotation.Transitions; import org.apache.mina.statemachine.event.Event; import org.apache.mina.statemachine.transition.MethodSelfTransition; import org.apache.mina.statemachine.transition.MethodTransition; import org.apache.mina.statemachine.transition.SelfTransition; /** * Creates {@link StateMachine}s by reading {@link org.apache.mina.statemachine.annotation.State}, * {@link Transition} and {@link Transitions} (or equivalent) and {@link SelfTransition} annotations from one or more arbitrary * objects. * * * @author Apache MINA Project */ public class StateMachineFactory { private final Class transitionAnnotation; private final Class transitionsAnnotation; private final Class entrySelfTransitionsAnnotation; private final Class exitSelfTransitionsAnnotation; protected StateMachineFactory(Class transitionAnnotation, Class transitionsAnnotation, Class entrySelfTransitionsAnnotation, Class exitSelfTransitionsAnnotation) { this.transitionAnnotation = transitionAnnotation; this.transitionsAnnotation = transitionsAnnotation; this.entrySelfTransitionsAnnotation = entrySelfTransitionsAnnotation; this.exitSelfTransitionsAnnotation = exitSelfTransitionsAnnotation; } /** * Returns a new {@link StateMachineFactory} instance which creates * {@link StateMachine}s by reading the specified {@link Transition} * equivalent annotation. * * @param transitionAnnotation the {@link Transition} equivalent annotation. * @return the {@link StateMachineFactory}. */ public static StateMachineFactory getInstance(Class transitionAnnotation) { TransitionAnnotation a = transitionAnnotation.getAnnotation(TransitionAnnotation.class); if (a == null) { throw new IllegalArgumentException("The annotation class " + transitionAnnotation + " has not been annotated with the " + TransitionAnnotation.class.getName() + " annotation"); } return new StateMachineFactory(transitionAnnotation, a.value(), OnEntry.class, OnExit.class); } /** * Creates a new {@link StateMachine} from the specified handler object and * using a start state with id start. * * @param handler the object containing the annotations describing the * state machine. * @return the {@link StateMachine} object. */ public StateMachine create(Object handler) { return create(handler, new Object[0]); } /** * Creates a new {@link StateMachine} from the specified handler object and * using the {@link State} with the specified id as start state. * * @param start the id of the start {@link State} to use. * @param handler the object containing the annotations describing the * state machine. * @return the {@link StateMachine} object. */ public StateMachine create(String start, Object handler) { return create(start, handler, new Object[0]); } /** * Creates a new {@link StateMachine} from the specified handler objects and * using a start state with id start. * * @param handler the first object containing the annotations describing the * state machine. * @param handlers zero or more additional objects containing the * annotations describing the state machine. * @return the {@link StateMachine} object. */ public StateMachine create(Object handler, Object... handlers) { return create("start", handler, handlers); } /** * Creates a new {@link StateMachine} from the specified handler objects and * using the {@link State} with the specified id as start state. * * @param start the id of the start {@link State} to use. * @param handler the first object containing the annotations describing the * state machine. * @param handlers zero or more additional objects containing the * annotations describing the state machine. * @return the {@link StateMachine} object. */ public StateMachine create(String start, Object handler, Object... handlers) { Map states = new HashMap(); List handlersList = new ArrayList(1 + handlers.length); handlersList.add(handler); handlersList.addAll(Arrays.asList(handlers)); LinkedList fields = new LinkedList(); for (Object h : handlersList) { fields.addAll(getFields(h instanceof Class ? (Class) h : h.getClass())); } for (State state : createStates(fields)) { states.put(state.getId(), state); } if (!states.containsKey(start)) { throw new StateMachineCreationException("Start state '" + start + "' not found."); } setupTransitions(transitionAnnotation, transitionsAnnotation, entrySelfTransitionsAnnotation, exitSelfTransitionsAnnotation, states, handlersList); return new StateMachine(states.values(), start); } private static void setupTransitions(Class transitionAnnotation, Class transitionsAnnotation, Class onEntrySelfTransitionAnnotation, Class onExitSelfTransitionAnnotation, Map states, List handlers) { for (Object handler : handlers) { setupTransitions(transitionAnnotation, transitionsAnnotation, onEntrySelfTransitionAnnotation, onExitSelfTransitionAnnotation, states, handler); } } private static void setupSelfTransitions(Method m, Class onEntrySelfTransitionAnnotation, Class onExitSelfTransitionAnnotation, Map states, Object handler) { if (m.isAnnotationPresent(OnEntry.class)) { OnEntry onEntryAnnotation = (OnEntry) m.getAnnotation(onEntrySelfTransitionAnnotation); State state = states.get(onEntryAnnotation.value()); if (state == null) { throw new StateMachineCreationException("Error encountered " + "when processing onEntry annotation in method " + m + ". state " + onEntryAnnotation.value() + " not Found."); } state.addOnEntrySelfTransaction(new MethodSelfTransition(m, handler)); } if (m.isAnnotationPresent(OnExit.class)) { OnExit onExitAnnotation = (OnExit) m.getAnnotation(onExitSelfTransitionAnnotation); State state = states.get(onExitAnnotation.value()); if (state == null) { throw new StateMachineCreationException("Error encountered " + "when processing onExit annotation in method " + m + ". state " + onExitAnnotation.value() + " not Found."); } state.addOnExitSelfTransaction(new MethodSelfTransition(m, handler)); } } private static void setupTransitions(Class transitionAnnotation, Class transitionsAnnotation, Class onEntrySelfTransitionAnnotation, Class onExitSelfTransitionAnnotation, Map states, Object handler) { Method[] methods = handler.getClass().getDeclaredMethods(); Arrays.sort(methods, new Comparator() { public int compare(Method m1, Method m2) { return m1.toString().compareTo(m2.toString()); } }); for (Method m : methods) { setupSelfTransitions(m, onEntrySelfTransitionAnnotation, onExitSelfTransitionAnnotation, states, handler); List transitionAnnotations = new ArrayList(); if (m.isAnnotationPresent(transitionAnnotation)) { transitionAnnotations.add(new TransitionWrapper(transitionAnnotation, m .getAnnotation(transitionAnnotation))); } if (m.isAnnotationPresent(transitionsAnnotation)) { transitionAnnotations.addAll(Arrays.asList(new TransitionsWrapper(transitionAnnotation, transitionsAnnotation, m.getAnnotation(transitionsAnnotation)).value())); } if (transitionAnnotations.isEmpty()) { continue; } for (TransitionWrapper annotation : transitionAnnotations) { Object[] eventIds = annotation.on(); if (eventIds.length == 0) { throw new StateMachineCreationException("Error encountered " + "when processing method " + m + ". No event ids specified."); } if (annotation.in().length == 0) { throw new StateMachineCreationException("Error encountered " + "when processing method " + m + ". No states specified."); } State next = null; if (!annotation.next().equals(Transition.SELF)) { next = states.get(annotation.next()); if (next == null) { throw new StateMachineCreationException("Error encountered " + "when processing method " + m + ". Unknown next state: " + annotation.next() + "."); } } for (Object event : eventIds) { if (event == null) { event = Event.WILDCARD_EVENT_ID; } if (!(event instanceof String)) { event = event.toString(); } for (String in : annotation.in()) { State state = states.get(in); if (state == null) { throw new StateMachineCreationException("Error encountered " + "when processing method " + m + ". Unknown state: " + in + "."); } state.addTransition(new MethodTransition(event, next, m, handler), annotation.weight()); } } } } } static List getFields(Class clazz) { LinkedList fields = new LinkedList(); for (Field f : clazz.getDeclaredFields()) { if (!f.isAnnotationPresent(org.apache.mina.statemachine.annotation.State.class)) { continue; } if ((f.getModifiers() & Modifier.STATIC) == 0 || (f.getModifiers() & Modifier.FINAL) == 0 || !f.getType().equals(String.class)) { throw new StateMachineCreationException("Error encountered when " + "processing field " + f + ". Only static final " + "String fields can be used with the @State " + "annotation."); } if (!f.isAccessible()) { f.setAccessible(true); } fields.add(f); } return fields; } static State[] createStates(List fields) { LinkedHashMap states = new LinkedHashMap(); while (!fields.isEmpty()) { int size = fields.size(); int numStates = states.size(); for (int i = 0; i < size; i++) { Field f = fields.remove(0); String value = null; try { value = (String) f.get(null); } catch (IllegalAccessException iae) { throw new StateMachineCreationException("Error encountered when " + "processing field " + f + ".", iae); } org.apache.mina.statemachine.annotation.State stateAnnotation = f .getAnnotation(org.apache.mina.statemachine.annotation.State.class); if (stateAnnotation.value().equals(org.apache.mina.statemachine.annotation.State.ROOT)) { states.put(value, new State(value)); } else if (states.containsKey(stateAnnotation.value())) { states.put(value, new State(value, states.get(stateAnnotation.value()))); } else { // Move to the back of the list of fields for later // processing fields.add(f); } } /* * If no new states were added to states during this iteration it * means that all fields in fields specify non-existent parents. */ if (states.size() == numStates) { throw new StateMachineCreationException("Error encountered while creating " + "FSM. The following fields specify non-existing " + "parent states: " + fields); } } return states.values().toArray(new State[0]); } private static class TransitionWrapper { private final Class transitionClazz; private final Annotation annotation; public TransitionWrapper(Class transitionClazz, Annotation annotation) { this.transitionClazz = transitionClazz; this.annotation = annotation; } Object[] on() { return getParameter("on", Object[].class); } String[] in() { return getParameter("in", String[].class); } String next() { return getParameter("next", String.class); } int weight() { return getParameter("weight", Integer.TYPE); } @SuppressWarnings("unchecked") private T getParameter(String name, Class returnType) { try { Method m = transitionClazz.getMethod(name); if (!returnType.isAssignableFrom(m.getReturnType())) { throw new NoSuchMethodException(); } return (T) m.invoke(annotation); } catch (Throwable t) { throw new StateMachineCreationException("Could not get parameter '" + name + "' from Transition annotation " + transitionClazz); } } } private static class TransitionsWrapper { private final Class transitionsclazz; private final Class transitionClazz; private final Annotation annotation; public TransitionsWrapper(Class transitionClazz, Class transitionsclazz, Annotation annotation) { this.transitionClazz = transitionClazz; this.transitionsclazz = transitionsclazz; this.annotation = annotation; } TransitionWrapper[] value() { Annotation[] annos = getParameter("value", Annotation[].class); TransitionWrapper[] wrappers = new TransitionWrapper[annos.length]; for (int i = 0; i < annos.length; i++) { wrappers[i] = new TransitionWrapper(transitionClazz, annos[i]); } return wrappers; } @SuppressWarnings("unchecked") private T getParameter(String name, Class returnType) { try { Method m = transitionsclazz.getMethod(name); if (!returnType.isAssignableFrom(m.getReturnType())) { throw new NoSuchMethodException(); } return (T) m.invoke(annotation); } catch (Throwable t) { throw new StateMachineCreationException("Could not get parameter '" + name + "' from Transitions annotation " + transitionsclazz); } } } } mina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/0000755000175000017500000000000012162575507031414 5ustar ebourgebourg././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/Transition.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/Transit0000644000175000017500000000446612032276010032754 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apache.mina.statemachine.StateMachine; import org.apache.mina.statemachine.event.Event; /** * Annotation used on methods to indicate that the method handles a specific * kind of event when in a specific state. * * @author Apache MINA Project */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @TransitionAnnotation(Transitions.class) public @interface Transition { public static final String SELF = "__self__"; /** * Specifies the ids of one or more events handled by the annotated method. If * not specified the handler method will be executed for any event. */ String[] on() default Event.WILDCARD_EVENT_ID; /** * The id of the state or states that this handler applies to. Must be * specified. */ String[] in(); /** * The id of the state the {@link StateMachine} should move to next after * executing the annotated method. If not specified the {@link StateMachine} * will remain in the same state. */ String next() default SELF; /** * The weight used to order handler annotations which match the same event * in the same state. Transitions with lower weight will be matched first. The * default weight is 0. */ int weight() default 0; } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/State.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/State.j0000644000175000017500000000301312032276010032623 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation used to define the states in a state machine. Only applies to * static final String fields. The value of the string will be used * as state id. * * @author Apache MINA Project */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface State { public static final String ROOT = "__root__"; /** * Sets the id of the parent state. The default is no parent. */ String value() default ROOT; } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/IoHandlerTransition.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/IoHandl0000644000175000017500000000473412032276010032644 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apache.mina.core.service.IoHandler; import org.apache.mina.statemachine.StateMachine; import org.apache.mina.statemachine.event.IoHandlerEvents; /** * Annotation used on methods to indicate that the method handles a specific * kind of {@link IoHandlerEvents} event when in a specific state. This should * be used when creating {@link StateMachine}s for MINA's {@link IoHandler} * interface. * * @author Apache MINA Project */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @TransitionAnnotation(IoHandlerTransitions.class) public @interface IoHandlerTransition { /** * Specifies the ids of one or more events handled by the annotated method. If * not specified the handler method will be executed for any event. */ IoHandlerEvents[] on() default IoHandlerEvents.ANY; /** * The id of the state or states that this handler applies to. Must be * specified. */ String[] in(); /** * The id of the state the {@link StateMachine} should move to next after * executing the annotated method. If not specified the {@link StateMachine} * will remain in the same state. */ String next() default Transition.SELF; /** * The weight used to order handler annotations which match the same event * in the same state. Transitions with lower weight will be matched first. The * default weight is 0. */ int weight() default 0; } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/IoHandlerTransitions.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/IoHandl0000644000175000017500000000300712032276010032634 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apache.mina.core.service.IoHandler; import org.apache.mina.statemachine.StateMachine; /** * Annotation used to annotate a method with several {@link IoHandlerTransition}s. * This should be used when creating {@link StateMachine}s for MINA's * {@link IoHandler} interface. * * @author Apache MINA Project */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface IoHandlerTransitions { IoHandlerTransition[] value(); } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/IoFilterTransition.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/IoFilte0000644000175000017500000000473012032276010032655 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.statemachine.StateMachine; import org.apache.mina.statemachine.event.IoFilterEvents; /** * Annotation used on methods to indicate that the method handles a specific * kind of {@link IoFilterEvents} event when in a specific state. This should * be used when creating {@link StateMachine}s for MINA's {@link IoFilter} * interface. * * @author Apache MINA Project */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @TransitionAnnotation(IoFilterTransitions.class) public @interface IoFilterTransition { /** * Specifies the ids of one or more events handled by the annotated method. If * not specified the handler method will be executed for any event. */ IoFilterEvents[] on() default IoFilterEvents.ANY; /** * The id of the state or states that this handler applies to. Must be * specified. */ String[] in(); /** * The id of the state the {@link StateMachine} should move to next after * executing the annotated method. If not specified the {@link StateMachine} * will remain in the same state. */ String next() default Transition.SELF; /** * The weight used to order handler annotations which match the same event * in the same state. Transitions with lower weight will be matched first. The * default weight is 0. */ int weight() default 0; } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/OnExit.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/OnExit.0000644000175000017500000000256512032276010032612 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation used on methods to indicate that the method will be executed * before existing from a certain state * * @author Apache MINA Project */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface OnExit { /** * Sets the id of related state. */ String value(); } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/IoFilterTransitions.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/IoFilte0000644000175000017500000000300612032276010032650 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.statemachine.StateMachine; /** * Annotation used to annotate a method with several {@link IoFilterTransition}s. * This should be used when creating {@link StateMachine}s for MINA's * {@link IoFilter} interface. * * @author Apache MINA Project */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface IoFilterTransitions { IoFilterTransition[] value(); } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/Transitions.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/Transit0000644000175000017500000000244212032276010032744 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation used to annotate a method with several {@link Transition}s. * * @author Apache MINA Project */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Transitions { Transition[] value(); } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/OnEntry.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/OnEntry0000644000175000017500000000256112032276010032720 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation used on methods to indicate that the method will be executed * before entering a certain state * * @author Apache MINA Project */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface OnEntry { /** * Sets the id of related state. */ String value(); } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/TransitionAnnotation.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/annotation/Transit0000644000175000017500000000270512032276010032746 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.annotation; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation used to mark other annotations as being transition annotations. * The annotation used to group transition annotations must be given as * parameter. * * @author Apache MINA Project */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface TransitionAnnotation { Class value(); } mina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/0000755000175000017500000000000012162575507031434 5ustar ebourgebourg././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/AbstractTransition.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/Abstrac0000644000175000017500000000730012032276007032723 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.transition; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.mina.statemachine.State; import org.apache.mina.statemachine.StateMachine; import org.apache.mina.statemachine.event.Event; /** * Abstract {@link Transition} implementation. Takes care of matching the * current {@link Event}'s id against the id of the {@link Event} this * {@link Transition} handles. To handle any {@link Event} the id should be set * to {@link Event#WILDCARD_EVENT_ID}. * * @author Apache MINA Project */ public abstract class AbstractTransition implements Transition { private final Object eventId; private final State nextState; /** * Creates a new instance which will loopback to the same {@link State} * for the specified {@link Event} id. * * @param eventId the {@link Event} id. */ public AbstractTransition(Object eventId) { this(eventId, null); } /** * Creates a new instance with the specified {@link State} as next state * and for the specified {@link Event} id. * * @param eventId the {@link Event} id. * @param nextState the next {@link State}. */ public AbstractTransition(Object eventId, State nextState) { this.eventId = eventId; this.nextState = nextState; } public State getNextState() { return nextState; } public boolean execute(Event event) { if (!eventId.equals(Event.WILDCARD_EVENT_ID) && !eventId.equals(event.getId())) { return false; } return doExecute(event); } /** * Executes this {@link Transition}. This method doesn't have to check * if the {@link Event}'s id matches because {@link #execute(Event)} has * already made sure that that is the case. * * @param event the current {@link Event}. * @return true if the {@link Transition} has been executed * successfully and the {@link StateMachine} should move to the * next {@link State}. false otherwise. */ protected abstract boolean doExecute(Event event); public boolean equals(Object o) { if (!(o instanceof AbstractTransition)) { return false; } if (o == this) { return true; } AbstractTransition that = (AbstractTransition) o; return new EqualsBuilder().append(eventId, that.eventId).append(nextState, that.nextState).isEquals(); } public int hashCode() { return new HashCodeBuilder(11, 31).append(eventId).append(nextState).toHashCode(); } public String toString() { return new ToStringBuilder(this).append("eventId", eventId).append("nextState", nextState).toString(); } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/NoSuchMethodException.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/NoSuchM0000644000175000017500000000276012032276007032665 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.transition; /** * {@link RuntimeException} equivalent of {@link java.lang.NoSuchMethodException}. * Thrown by the constructors in {@link MethodTransition} if no method by * the specifed name can be found. * * @author Apache MINA Project */ public class NoSuchMethodException extends RuntimeException { private static final long serialVersionUID = -8877979996892420479L; /** * Creates a new instance using the specified method name as message. * * @param methodName the name of the method. */ public NoSuchMethodException(String methodName) { super(methodName); } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/AmbiguousMethodException.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/Ambiguo0000644000175000017500000000270612032276007032734 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.transition; /** * Thrown by the constructors in {@link MethodTransition} if there are several * methods with the specifed name in the target object's class. * * @author Apache MINA Project */ public class AmbiguousMethodException extends RuntimeException { private static final long serialVersionUID = -3926582218186692464L; /** * Creates a new instance using the specified method name as message. * * @param methodName the name of the method. */ public AmbiguousMethodException(String methodName) { super(methodName); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/MethodTransition.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/MethodT0000644000175000017500000002545012032276007032716 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.transition; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.mina.statemachine.State; import org.apache.mina.statemachine.StateMachine; import org.apache.mina.statemachine.StateMachineFactory; import org.apache.mina.statemachine.annotation.Transition; import org.apache.mina.statemachine.context.StateContext; import org.apache.mina.statemachine.event.Event; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * {@link Transition} which invokes a {@link Method}. The {@link Method} will * only be invoked if its argument types actually matches a subset of the * {@link Event}'s argument types. The argument types are matched in order so * you must make sure the order of the method's arguments corresponds to the * order of the event's arguments. *

* If the first method argument type matches * {@link Event} the current {@link Event} will be bound to that argument. In * the same manner the second argument (or first if the method isn't interested * in the current {@link Event}) can have the {@link StateContext} type and will * in that case be bound to the current {@link StateContext}. *

*

* Normally you wouldn't create instances of this class directly but rather use the * {@link Transition} annotation to define the methods which should be used as * transitions in your state machine and then let {@link StateMachineFactory} create a * {@link StateMachine} for you. *

* * @author Apache MINA Project */ public class MethodTransition extends AbstractTransition { private static final Logger LOGGER = LoggerFactory.getLogger(MethodTransition.class); private static final Object[] EMPTY_ARGUMENTS = new Object[0]; private final Method method; private final Object target; /** * Creates a new instance with the specified {@link State} as next state * and for the specified {@link Event} id. * * @param eventId the {@link Event} id. * @param nextState the next {@link State}. * @param method the target method. * @param target the target object. */ public MethodTransition(Object eventId, State nextState, Method method, Object target) { super(eventId, nextState); this.method = method; this.target = target; } /** * Creates a new instance which will loopback to the same {@link State} * for the specified {@link Event} id. * * @param eventId the {@link Event} id. * @param method the target method. * @param target the target object. */ public MethodTransition(Object eventId, Method method, Object target) { this(eventId, null, method, target); } /** * Creates a new instance with the specified {@link State} as next state * and for the specified {@link Event} id. The target {@link Method} will * be the method in the specified target object with the same name as the * specified {@link Event} id. * * @param eventId the {@link Event} id. * @param nextState the next {@link State}. * @param target the target object. * @throws NoSuchMethodException if no method could be found with a name * equal to the {@link Event} id. * @throws AmbiguousMethodException if more than one method was found with * a name equal to the {@link Event} id. */ public MethodTransition(Object eventId, State nextState, Object target) { this(eventId, nextState, eventId.toString(), target); } /** * Creates a new instance which will loopback to the same {@link State} * for the specified {@link Event} id. The target {@link Method} will * be the method in the specified target object with the same name as the * specified {@link Event} id. * * @param eventId the {@link Event} id. * @param target the target object. * @throws NoSuchMethodException if no method could be found with a name * equal to the {@link Event} id. * @throws AmbiguousMethodException if more than one method was found with * a name equal to the {@link Event} id. */ public MethodTransition(Object eventId, Object target) { this(eventId, eventId.toString(), target); } /** * Creates a new instance which will loopback to the same {@link State} * for the specified {@link Event} id. * * @param eventId the {@link Event} id. * @param methodName the name of the target {@link Method}. * @param target the target object. * @throws NoSuchMethodException if the method could not be found. * @throws AmbiguousMethodException if there are more than one method with * the specified name. */ public MethodTransition(Object eventId, String methodName, Object target) { this(eventId, null, methodName, target); } /** * Creates a new instance with the specified {@link State} as next state * and for the specified {@link Event} id. * * @param eventId the {@link Event} id. * @param nextState the next {@link State}. * @param methodName the name of the target {@link Method}. * @param target the target object. * @throws NoSuchMethodException if the method could not be found. * @throws AmbiguousMethodException if there are more than one method with * the specified name. */ public MethodTransition(Object eventId, State nextState, String methodName, Object target) { super(eventId, nextState); this.target = target; Method[] candidates = target.getClass().getMethods(); Method result = null; for (int i = 0; i < candidates.length; i++) { if (candidates[i].getName().equals(methodName)) { if (result != null) { throw new AmbiguousMethodException(methodName); } result = candidates[i]; } } if (result == null) { throw new NoSuchMethodException(methodName); } this.method = result; } /** * Returns the target {@link Method}. * * @return the method. */ public Method getMethod() { return method; } /** * Returns the target object. * * @return the target object. */ public Object getTarget() { return target; } public boolean doExecute(Event event) { Class[] types = method.getParameterTypes(); if (types.length == 0) { invokeMethod(EMPTY_ARGUMENTS); return true; } if (types.length > 2 + event.getArguments().length) { return false; } Object[] args = new Object[types.length]; int i = 0; if (match(types[i], event, Event.class)) { args[i++] = event; } if (i < args.length && match(types[i], event.getContext(), StateContext.class)) { args[i++] = event.getContext(); } Object[] eventArgs = event.getArguments(); for (int j = 0; i < args.length && j < eventArgs.length; j++) { if (match(types[i], eventArgs[j], Object.class)) { args[i++] = eventArgs[j]; } } if (args.length > i) { return false; } invokeMethod(args); return true; } @SuppressWarnings("unchecked") private boolean match(Class paramType, Object arg, Class argType) { if (paramType.isPrimitive()) { if (paramType.equals(Boolean.TYPE)) { return arg instanceof Boolean; } if (paramType.equals(Integer.TYPE)) { return arg instanceof Integer; } if (paramType.equals(Long.TYPE)) { return arg instanceof Long; } if (paramType.equals(Short.TYPE)) { return arg instanceof Short; } if (paramType.equals(Byte.TYPE)) { return arg instanceof Byte; } if (paramType.equals(Double.TYPE)) { return arg instanceof Double; } if (paramType.equals(Float.TYPE)) { return arg instanceof Float; } if (paramType.equals(Character.TYPE)) { return arg instanceof Character; } } return argType.isAssignableFrom(paramType) && paramType.isAssignableFrom(arg.getClass()); } private void invokeMethod(Object[] arguments) { try { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Executing method " + method + " with arguments " + Arrays.asList(arguments)); } method.invoke(target, arguments); } catch (InvocationTargetException ite) { if (ite.getCause() instanceof RuntimeException) { throw (RuntimeException) ite.getCause(); } throw new MethodInvocationException(method, ite); } catch (IllegalAccessException iae) { throw new MethodInvocationException(method, iae); } } public boolean equals(Object o) { if (!(o instanceof MethodTransition)) { return false; } if (o == this) { return true; } MethodTransition that = (MethodTransition) o; return new EqualsBuilder().appendSuper(super.equals(that)).append(method, that.method) .append(target, that.target).isEquals(); } public int hashCode() { return new HashCodeBuilder(13, 33).appendSuper(super.hashCode()).append(method).append(target).toHashCode(); } public String toString() { return new ToStringBuilder(this).appendSuper(super.toString()).append("method", method) .append("target", target).toString(); } } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/MethodInvocationException.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/MethodI0000644000175000017500000000302212032276007032672 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.transition; import java.lang.reflect.Method; /** * Thrown by {@link MethodTransition} if the target method couldn't be invoked * or threw an exception. * * @author Apache MINA Project */ public class MethodInvocationException extends RuntimeException { private static final long serialVersionUID = 4288548621384649704L; /** * Creates a new instance for the specified {@link Method} and * {@link Throwable}. * * @param method the {@link Method}. * @param cause the reason. */ public MethodInvocationException(Method method, Throwable cause) { super("Invoking method: " + method, cause); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/Transition.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/Transit0000644000175000017500000000410412032276007032767 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.transition; import org.apache.mina.statemachine.State; import org.apache.mina.statemachine.StateMachine; import org.apache.mina.statemachine.event.Event; /** * The interface implemented by classes which need to react on transitions * between states. * * @author Apache MINA Project */ public interface Transition { /** * Executes this {@link Transition}. It is the responsibility of this * {@link Transition} to determine whether it actually applies for the * specified {@link Event}. If this {@link Transition} doesn't apply * nothing should be executed and false must be returned. * * @param event the current {@link Event}. * @return true if the {@link Transition} was executed, * false otherwise. */ boolean execute(Event event); /** * Returns the {@link State} which the {@link StateMachine} should move to * if this {@link Transition} is taken and {@link #execute(Event)} returns * true. * * @return the next {@link State} or null if this * {@link Transition} is a loopback {@link Transition}. */ State getNextState(); } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/MethodSelfTransition.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/MethodS0000644000175000017500000001037012032276007032710 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.transition; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import org.apache.mina.statemachine.context.StateContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.mina.statemachine.State; /** * {@link SelfTransition} which invokes a {@link Method}. The {@link Method} can * have zero or any number of StateContext and State regarding order *

* Normally you wouldn't create instances of this class directly but rather use the * {@link SelfTransition} annotation to define the methods which should be used as * transitions in your state machine and then let {@link StateMachineFactory} create a * {@link StateMachine} for you. *

* * @author Apache MINA Project */ public class MethodSelfTransition extends AbstractSelfTransition { private static final Logger LOGGER = LoggerFactory.getLogger(MethodTransition.class); private Method method; private final Object target; private static final Object[] EMPTY_ARGUMENTS = new Object[0]; public MethodSelfTransition(Method method, Object target) { super(); this.method = method; this.target = target; } /** * Creates a new instance * * @param method the target method. * @param target the target object. */ public MethodSelfTransition(String methodName, Object target) { this.target = target; Method[] candidates = target.getClass().getMethods(); Method result = null; for (int i = 0; i < candidates.length; i++) { if (candidates[i].getName().equals(methodName)) { if (result != null) { throw new AmbiguousMethodException(methodName); } result = candidates[i]; } } if (result == null) { throw new NoSuchMethodException(methodName); } this.method = result; } /** * Returns the target {@link Method}. * * @return the method. */ public Method getMethod() { return method; } public boolean doExecute(StateContext stateContext, State state) { Class[] types = method.getParameterTypes(); if (types.length == 0) { invokeMethod(EMPTY_ARGUMENTS); return true; } if (types.length > 2) { return false; } Object[] args = new Object[types.length]; int i = 0; if (types[i].isAssignableFrom(StateContext.class)) { args[i++] = stateContext; } if (i < types.length && types[i].isAssignableFrom(State.class)) { args[i++] = state; } invokeMethod(args); return true; } private void invokeMethod(Object[] arguments) { try { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Executing method " + method + " with arguments " + Arrays.asList(arguments)); } method.invoke(target, arguments); } catch (InvocationTargetException ite) { if (ite.getCause() instanceof RuntimeException) { throw (RuntimeException) ite.getCause(); } throw new MethodInvocationException(method, ite); } catch (IllegalAccessException iae) { throw new MethodInvocationException(method, iae); } } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/AbstractSelfTransition.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/Abstrac0000644000175000017500000000320512032276007032723 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.transition; import org.apache.mina.statemachine.context.StateContext; import org.apache.mina.statemachine.State; /** * Abstract {@link SelfTransition} implementation. * * @author Apache MINA Project */ public abstract class AbstractSelfTransition implements SelfTransition { /** * Creates a new instance * */ public AbstractSelfTransition() { } /** * Executes this {@link SelfTransition}. * * @return true if the {@link SelfTransition} has been executed * successfully */ protected abstract boolean doExecute(StateContext stateContext, State state); public boolean execute(StateContext stateContext, State state) { return doExecute(stateContext, state); } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/NoopTransition.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/NoopTra0000644000175000017500000000351312032276007032730 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.transition; import org.apache.mina.statemachine.State; import org.apache.mina.statemachine.event.Event; /** * {@link Transition} implementation which does nothing but change the state. * * @author Apache MINA Project */ public class NoopTransition extends AbstractTransition { /** * Creates a new instance which will loopback to the same {@link State} * for the specified {@link Event} id. * * @param eventId the {@link Event} id. */ public NoopTransition(Object eventId) { super(eventId); } /** * Creates a new instance with the specified {@link State} as next state * and for the specified {@link Event} id. * * @param eventId the {@link Event} id. * @param nextState the next {@link State}. */ public NoopTransition(Object eventId, State nextState) { super(eventId, nextState); } protected boolean doExecute(Event event) { return true; } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/SelfTransition.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/transition/SelfTra0000644000175000017500000000263712032276007032714 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.transition; import org.apache.mina.statemachine.context.StateContext; import org.apache.mina.statemachine.State; /** * The interface implemented by classes which need to react on entering * a certain states. * * @author Apache MINA Project */ public interface SelfTransition { /** * Executes this {@link SelfTransition}. * * @return true if the {@link SelfTransition} was executed, * false otherwise. */ boolean execute(StateContext stateContext, State state); } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/NoSuchStateException.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/NoSuchStateExcepti0000644000175000017500000000264712032276010032677 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine; /** * Exception thrown by {@link StateMachine} when a transition in the state * machine references a state which doesn't exist. * * @author Apache MINA Project */ public class NoSuchStateException extends RuntimeException { private static final long serialVersionUID = -886869696039996478L; /** * Creates a new instance. * * @param stateId the id of the state which could not be found. */ public NoSuchStateException(String stateId) { super("Could not find the state with id: " + stateId); } } mina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/event/0000755000175000017500000000000012162575507030363 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/event/Event.java0000644000175000017500000000626212032276005032300 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.event; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.mina.statemachine.context.StateContext; /** * Represents an event which typically corresponds to a method call on a proxy. * An event has an id and zero or more arguments typically corresponding to * the method arguments. * * @author Apache MINA Project */ public class Event { public static final String WILDCARD_EVENT_ID = "*"; private final Object id; private final StateContext context; private final Object[] arguments; /** * Creates a new {@link Event} with the specified id and no arguments. * * @param id the event id. * @param context the {@link StateContext} the event was triggered for. */ public Event(Object id, StateContext context) { this(id, context, new Object[0]); } /** * Creates a new {@link Event} with the specified id and arguments. * * @param id the event id. * @param context the {@link StateContext} the event was triggered for. * @param arguments the event arguments. */ public Event(Object id, StateContext context, Object[] arguments) { if (id == null) { throw new IllegalArgumentException("id"); } if (context == null) { throw new IllegalArgumentException("context"); } if (arguments == null) { throw new IllegalArgumentException("arguments"); } this.id = id; this.context = context; this.arguments = arguments; } /** * Returns the {@link StateContext} this {@link Event} was triggered for. * * @return the {@link StateContext}. */ public StateContext getContext() { return context; } /** * Returns the id of this {@link Event}. * * @return the id. */ public Object getId() { return id; } /** * Returns the arguments of this {@link Event}. * * @return the arguments. Returns an empty array if this {@link Event} has * no arguments. */ public Object[] getArguments() { return arguments; } public String toString() { return new ToStringBuilder(this).append("id", id).append("context", context).append("arguments", arguments) .toString(); } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/event/EventArgumentsInterceptor.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/event/EventArgumen0000644000175000017500000000275712032276005032704 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.event; import org.apache.mina.statemachine.StateMachine; /** * Intercepts the {@link Event} arguments before the {@link Event} is passed * to the {@link StateMachine} and allows for the arguments to be modified. * This is for advanced uses only. * * @author Apache MINA Project */ public interface EventArgumentsInterceptor { /** * Modifies the specified array of event arguments. * * @param arguments the original arguments. * @return the new arguments. Should return the original array if no * modification is needed. */ Object[] modify(Object[] arguments); } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/event/EventFactory.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/event/EventFactory0000644000175000017500000000314012032276005032700 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.event; import java.lang.reflect.Method; import org.apache.mina.statemachine.StateMachineProxyBuilder; import org.apache.mina.statemachine.context.StateContext; /** * Used by {@link StateMachineProxyBuilder} to create {@link Event} objects when * methods are invoked on the proxy. * * @author Apache MINA Project */ public interface EventFactory { /** * Creates a new {@link Event} from the specified method and method * arguments. * * @param context the current {@link StateContext}. * @param method the method being invoked. * @param args the method arguments. * @return the {@link Event} object. */ Event create(StateContext context, Method method, Object[] arguments); } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/event/IoHandlerEvents.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/event/IoHandlerEve0000644000175000017500000000322512032276005032600 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.event; import org.apache.mina.core.service.IoHandler; import org.apache.mina.statemachine.annotation.IoHandlerTransition; /** * Defines all possible MINA {@link IoHandler} events for use in {@link IoHandlerTransition} * annotations. * * @author Apache MINA Project */ public enum IoHandlerEvents { ANY(Event.WILDCARD_EVENT_ID), SESSION_CREATED("sessionCreated"), SESSION_OPENED("sessionOpened"), SESSION_CLOSED( "sessionClosed"), SESSION_IDLE("sessionIdle"), MESSAGE_RECEIVED("messageReceived"), MESSAGE_SENT( "messageSent"), EXCEPTION_CAUGHT("exceptionCaught"); private final String value; private IoHandlerEvents(String value) { this.value = value; } @Override public String toString() { return value; } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/event/IoFilterEvents.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/event/IoFilterEven0000644000175000017500000000336612032276005032634 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.event; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.statemachine.annotation.IoFilterTransition; /** * Defines all possible MINA {@link IoFilter} events for use in {@link IoFilterTransition} * annotations. * * @author Apache MINA Project */ public enum IoFilterEvents { ANY(Event.WILDCARD_EVENT_ID), SESSION_CREATED("sessionCreated"), SESSION_OPENED("sessionOpened"), SESSION_CLOSED( "sessionClosed"), SESSION_IDLE("sessionIdle"), MESSAGE_RECEIVED("messageReceived"), MESSAGE_SENT( "messageSent"), EXCEPTION_CAUGHT("exceptionCaught"), CLOSE("filterClose"), WRITE("filterWrite"), SET_TRAFFIC_MASK( "filterSetTrafficMask"); private final String value; private IoFilterEvents(String value) { this.value = value; } @Override public String toString() { return value; } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/event/UnhandledEventException.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/event/UnhandledEve0000644000175000017500000000273712032276005032644 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.event; /** * Thrown when an {@link Event} passed to a state machine couldn't be handled. * * @author Apache MINA Project */ public class UnhandledEventException extends RuntimeException { private static final long serialVersionUID = -717373229954175430L; private final Event event; public UnhandledEventException(Event event) { super("Unhandled event: " + event); this.event = event; } /** * Returns the {@link Event} which couldn't be handled. * * @return the {@link Event}. */ public Event getEvent() { return event; } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/event/DefaultEventFactory.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/event/DefaultEvent0000644000175000017500000000250212032276005032656 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine.event; import java.lang.reflect.Method; import org.apache.mina.statemachine.context.StateContext; /** * Default {@link EventFactory} implementation. Uses the method's name as * event id. * * @author Apache MINA Project */ public class DefaultEventFactory implements EventFactory { public Event create(StateContext context, Method method, Object[] arguments) { return new Event(method.getName(), context, arguments); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/BreakAndGotoException.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/BreakAndGotoExcept0000644000175000017500000000300112032276010032607 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine; /** * Exception used internally by {@link StateControl}. * * @author Apache MINA Project */ class BreakAndGotoException extends BreakException { private static final long serialVersionUID = 711671882187950113L; private final String stateId; private final boolean now; public BreakAndGotoException(String stateId, boolean now) { if (stateId == null) { throw new IllegalArgumentException("stateId"); } this.stateId = stateId; this.now = now; } public boolean isNow() { return now; } public String getStateId() { return stateId; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootmina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/StateMachineProxyBuilder.javamina2-2.0.7.orig/src/mina-statemachine/src/main/java/org/apache/mina/statemachine/StateMachineProxyB0000644000175000017500000002303412032276010032657 0ustar ebourgebourg/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.mina.statemachine; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import org.apache.mina.statemachine.context.SingletonStateContextLookup; import org.apache.mina.statemachine.context.StateContext; import org.apache.mina.statemachine.context.StateContextLookup; import org.apache.mina.statemachine.event.DefaultEventFactory; import org.apache.mina.statemachine.event.Event; import org.apache.mina.statemachine.event.EventArgumentsInterceptor; import org.apache.mina.statemachine.event.EventFactory; import org.apache.mina.statemachine.event.UnhandledEventException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Used to create proxies which will forward all method calls on them to a * {@link StateMachine}. * * @author Apache MINA Project */ public class StateMachineProxyBuilder { private static final Logger log = LoggerFactory.getLogger(StateMachineProxyBuilder.class); private static final Object[] EMPTY_ARGUMENTS = new Object[0]; private StateContextLookup contextLookup = new SingletonStateContextLookup(); private EventFactory eventFactory = new DefaultEventFactory(); private EventArgumentsInterceptor interceptor = null; private boolean ignoreUnhandledEvents = false; private boolean ignoreStateContextLookupFailure = false; private String name = null; /* * The classloader to use. Iif null we will use the current thread's * context classloader. */ private ClassLoader defaultCl = null; public StateMachineProxyBuilder() { } /** * Sets the name of the proxy created by this builder. This will be used * by the proxies toString() method. If not specified a default * auto generated name will be used. * * @param name the name. * @return this {@link StateMachineProxyBuilder} for method chaining. */ public StateMachineProxyBuilder setName(String name) { this.name = name; return this; } /** * Sets the {@link StateContextLookup} to be used. The default is to use * a {@link SingletonStateContextLookup}. * * @param contextLookup the {@link StateContextLookup} to use. * @return this {@link StateMachineProxyBuilder} for method chaining. */ public StateMachineProxyBuilder setStateContextLookup(StateContextLookup contextLookup) { this.contextLookup = contextLookup; return this; } /** * Sets the {@link EventFactory} to be used. The default is to use a * {@link DefaultEventFactory}. * * @param eventFactory the {@link EventFactory} to use. * @return this {@link StateMachineProxyBuilder} for method chaining. */ public StateMachineProxyBuilder setEventFactory(EventFactory eventFactory) { this.eventFactory = eventFactory; return this; } /** * Sets the {@link EventArgumentsInterceptor} to be used. By default no * {@link EventArgumentsInterceptor} will be used. * * @param interceptor the {@link EventArgumentsInterceptor} to use. * @return this {@link StateMachineProxyBuilder} for method chaining. */ public StateMachineProxyBuilder setEventArgumentsInterceptor(EventArgumentsInterceptor interceptor) { this.interceptor = interceptor; return this; } /** * Sets whether events which have no handler in the current state will raise * an exception or be silently ignored. The default is to raise an * exception. * * @param b true to ignore context lookup failures. * @return this {@link StateMachineProxyBuilder} for method chaining. */ public StateMachineProxyBuilder setIgnoreUnhandledEvents(boolean b) { this.ignoreUnhandledEvents = b; return this; } /** * Sets whether the failure to lookup a {@link StateContext} corresponding * to a method call on the proxy produced by this builder will raise an * exception or be silently ignored. The default is to raise an exception. * * @param b true to ignore context lookup failures. * @return this {@link StateMachineProxyBuilder} for method chaining. */ public StateMachineProxyBuilder setIgnoreStateContextLookupFailure(boolean b) { this.ignoreStateContextLookupFailure = b; return this; } /** * Sets the class loader to use for instantiating proxies. The default is * to use the current threads context {@link ClassLoader} as returned by * {@link Thread#getContextClassLoader()}. * * @param cl the class loader * @return this {@link StateMachineProxyBuilder} for method chaining. */ public StateMachineProxyBuilder setClassLoader(ClassLoader cl) { this.defaultCl = cl; return this; } /** * Creates a proxy for the specified interface and which uses the specified * {@link StateMachine}. * * @param iface the interface the proxy will implement. * @param sm the {@link StateMachine} which will receive the events * generated by the method calls on the proxy. * @return the proxy object. */ @SuppressWarnings("unchecked") public T create(Class iface, StateMachine sm) { return (T) create(new Class[] { iface }, sm); } /** * Creates a proxy for the specified interfaces and which uses the specified * {@link StateMachine}. * * @param ifaces the interfaces the proxy will implement. * @param sm the {@link StateMachine} which will receive the events * generated by the method calls on the proxy. * @return the proxy object. */ public Object create(Class[] ifaces, StateMachine sm) { ClassLoader cl = defaultCl; if (cl == null) { cl = Thread.currentThread().getContextClassLoader(); } InvocationHandler handler = new MethodInvocationHandler(sm, contextLookup, interceptor, eventFactory, ignoreUnhandledEvents, ignoreStateContextLookupFailure, name); return Proxy.newProxyInstance(cl, ifaces, handler); } private static class MethodInvocationHandler implements InvocationHandler { private final StateMachine sm; private final StateContextLookup contextLookup; private final EventArgumentsInterceptor interceptor; private final EventFactory eventFactory; private final boolean ignoreUnhandledEvents; private final boolean ignoreStateContextLookupFailure; private final String name; public MethodInvocationHandler(StateMachine sm, StateContextLookup contextLookup, EventArgumentsInterceptor interceptor, EventFactory eventFactory, boolean ignoreUnhandledEvents, boolean ignoreStateContextLookupFailure, String name) { this.contextLookup = contextLookup; this.sm = sm; this.interceptor = interceptor; this.eventFactory = eventFactory; this.ignoreUnhandledEvents = ignoreUnhandledEvents; this.ignoreStateContextLookupFailure = ignoreStateContextLookupFailure; this.name = name; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("hashCode".equals(method.getName()) && args == null) { return new Integer(System.identityHashCode(proxy)); } if ("equals".equals(method.getName()) && args.length == 1) { return Boolean.valueOf(proxy == args[0]); } if ("toString".equals(method.getName()) && args == null) { return (name != null ? name : proxy.getClass().getName()) + "@" + Integer.toHexString(System.identityHashCode(proxy)); } if (log.isDebugEnabled()) { log.debug("Method invoked: " + method); } args = args == null ? EMPTY_ARGUMENTS : args; if (interceptor != null) { args = interceptor.modify(args); } StateContext context = contextLookup.lookup(args); if (context == null) { if (ignoreStateContextLookupFailure) { return null; } throw new IllegalStateException("Cannot determine state " + "context for method invocation: " + method); } Event event = eventFactory.create(context, method, args); try { sm.handle(event); } catch (UnhandledEventException uee) { if (!ignoreUnhandledEvents) { throw uee; } } return null; } } } mina2-2.0.7.orig/src/mina-legal/0000755000175000017500000000000012162575507015624 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-legal/pom.xml.releaseBackup0000644000175000017500000000557312033674301021705 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7-SNAPSHOT mina-legal Apache MINA Legal http://mina.apache.org jar true jdom jdom true org.codehaus.plexus plexus-utils ${version.plexus.utils} true org.apache.maven maven-plugin-api ${version.api.plugin} true org.apache.maven maven-model ${version.model.plugin} true org.apache.maven maven-project ${version.project.plugin} true org.apache.maven.plugins maven-shade-plugin ${version.shade.plugin} true pmd pmd mina2-2.0.7.orig/src/mina-legal/pom.xml0000644000175000017500000000556212033674306017143 0ustar ebourgebourg 4.0.0 org.apache.mina mina-parent 2.0.7 mina-legal Apache MINA Legal http://mina.apache.org jar true jdom jdom true org.codehaus.plexus plexus-utils ${version.plexus.utils} true org.apache.maven maven-plugin-api ${version.api.plugin} true org.apache.maven maven-model ${version.model.plugin} true org.apache.maven maven-project ${version.project.plugin} true org.apache.maven.plugins maven-shade-plugin ${version.shade.plugin} true pmd pmd mina2-2.0.7.orig/src/mina-legal/src/0000755000175000017500000000000012032276014016376 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-legal/src/main/0000755000175000017500000000000012032276014017322 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-legal/src/main/resources/0000755000175000017500000000000012162575507021351 5ustar ebourgebourgmina2-2.0.7.orig/src/mina-legal/src/main/resources/notices.xml0000644000175000017500000000616112032276014023526 0ustar ebourgebourg ognl ognl OGNL :: Object-Graph Notation Language The OpenSymphony Group http://www.opensymphony.com The OpenSymphony Software License, Version 1.1 http://www.opensymphony.com/ognl/license.action org.slf4j slf4j-api SLF4J API Module QOS.ch http://www.qos.ch MIT style http://www.slf4j.org/license.html org.slf4j slf4j-jdk14 SLF4J JDK14 Binding QOS.ch http://www.qos.ch MIT style http://www.slf4j.org/license.html org.slf4j jcl-over-slf4j SLF4J JDK14 Binding QOS.ch http://www.qos.ch MIT style http://www.slf4j.org/license.html org.slf4j slf4j-log4j12 SLF4J JDK14 Binding QOS.ch http://www.qos.ch MIT style http://www.slf4j.org/license.html mina2-2.0.7.orig/NOTICE-bin.txt0000644000175000017500000000221612032276040015302 0ustar ebourgebourgApache MINA Copyright 2007-2012 The Apache Software Foundation. This product includes software developed at The Apache Software Foundation (http://www.apache.org/). Please refer to each LICENSE..txt file for the license terms of the components that Apache MINA depends on. Message logging is provided by the SLF4J library package, which is open source software, written by Ceki Gülcü, and copyright by SLF4J.ORG and QOS.ch. The original software is available from http://www.slf4j.org/ Data compression support is provided by the JZLib library package, which is open source software, written by JCraft, and copyright by JCraft. The original software is available from http://www.jcraft.com/jzlib/ Spring framework is provided by the Spring framework library package, which is open source software, written by Rod Johnson et al, and copyright by Springframework.org. The original software is available from http://www.springframework.org/ OGNL is provided by the OGNL library package, which is open source software, written by Drew Davidson and Luke Blanshard. The original software is available from http://www.ognl.org/ mina2-2.0.7.orig/LICENSE.txt0000644000175000017500000002367612032276040014652 0ustar ebourgebourg Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS mina2-2.0.7.orig/docs/0000755000175000017500000000000012162575507013757 5ustar ebourgebourg