You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by mw...@apache.org on 2007/08/28 02:00:46 UTC
svn commit: r570271 -
/mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/
Author: mwebb
Date: Mon Aug 27 17:00:46 2007
New Revision: 570271
URL: http://svn.apache.org/viewvc?rev=570271&view=rev
Log:
initial check-in. much is left to do in the commenting section. This will at least get the ball rolling and allow others to make updates.
Added:
mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/Cookie.java
mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpDecoder.java
mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpMessage.java
mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpProtocolCodecFactory.java
mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpRequestEncoder.java
mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpRequestMessage.java
mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpResponseDecoder.java
mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpResponseMessage.java
Added: mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/Cookie.java
URL: http://svn.apache.org/viewvc/mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/Cookie.java?rev=570271&view=auto
==============================================================================
--- mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/Cookie.java (added)
+++ mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/Cookie.java Mon Aug 27 17:00:46 2007
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.codec;
+
+
+import java.util.Date;
+
+
+/**
+ * TODO Cookie.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class Cookie
+{
+
+ private String comment;
+ private String domain;
+ private String name;
+ private String value;
+ private String path;
+ private boolean secure;
+ private int version = 0;
+ private Date expires;
+
+
+ public Cookie( String name, String value )
+ {
+ this.name = name;
+ this.value = value;
+ }
+
+
+ public String getComment()
+ {
+ return comment;
+ }
+
+
+ public void setComment( String comment )
+ {
+ this.comment = comment;
+ }
+
+
+ public String getDomain()
+ {
+ return domain;
+ }
+
+
+ public void setDomain( String domain )
+ {
+ this.domain = domain;
+ }
+
+
+ public String getName()
+ {
+ return name;
+ }
+
+
+ public void setName( String name )
+ {
+ this.name = name;
+ }
+
+
+ public String getValue()
+ {
+ return value;
+ }
+
+
+ public void setValue( String value )
+ {
+ this.value = value;
+ }
+
+
+ public String getPath()
+ {
+ return path;
+ }
+
+
+ public void setPath( String path )
+ {
+ this.path = path;
+ }
+
+
+ public boolean isSecure()
+ {
+ return secure;
+ }
+
+
+ public void setSecure( boolean secure )
+ {
+ this.secure = secure;
+ }
+
+
+ public int getVersion()
+ {
+ return version;
+ }
+
+
+ public void setVersion( int version )
+ {
+ this.version = version;
+ }
+
+
+ public Date getExpires()
+ {
+ return expires;
+ }
+
+
+ public void setExpires( Date expires )
+ {
+ this.expires = expires;
+ }
+}
Added: mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpDecoder.java
URL: http://svn.apache.org/viewvc/mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpDecoder.java?rev=570271&view=auto
==============================================================================
--- mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpDecoder.java (added)
+++ mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpDecoder.java Mon Aug 27 17:00:46 2007
@@ -0,0 +1,250 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.codec;
+
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.util.Date;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.http.util.DateUtil;
+
+
+/**
+ * TODO HttpDecoder.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HttpDecoder
+{
+ /**
+ * Carriage return character
+ */
+ private static final byte CR = 13;
+
+ /**
+ * Line feed character
+ */
+ private static final byte LF = 10;
+
+ public final static String COOKIE_COMMENT = "comment";
+ public final static String COOKIE_DOMAIN = "domain";
+ public final static String COOKIE_EXPIRES = "expires";
+ public final static String COOKIE_MAX_AGE = "max-age";
+ public final static String COOKIE_PATH = "path";
+ public final static String COOKIE_SECURE = "secure";
+ public final static String COOKIE_VERSION = "version";
+
+ public final static String SET_COOKIE = "Set-Cookie";
+ public final static String TRANSFER_ENCODING = "Transfer-Encoding";
+ public final static String CHUNKED = "chunked";
+
+ private CharsetDecoder decoder = Charset.defaultCharset().newDecoder();
+
+
+ public String decodeLine( ByteBuffer in ) throws Exception
+ {
+ int beginPos = in.position();
+ int limit = in.limit();
+ boolean lastIsCR = false;
+ 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;
+ }
+ }
+
+ //Check if we don't have enough data to process or found a full readable line
+ if ( terminatorPos == -1 )
+ return null;
+
+ String result = null;
+ if ( terminatorPos > 1 )
+ {
+ ByteBuffer line = in.slice();
+ line.limit( terminatorPos - beginPos - 1 );
+ result = line.getString( decoder );
+ }
+
+ in.position( terminatorPos + 1 );
+
+ return result;
+ }
+
+
+ public void decodeStatus( String line, HttpResponseMessage msg ) throws Exception
+ {
+ String magic = line.substring( 0, 8 );
+ if ( !magic.equals( "HTTP/1.1" ) && !magic.equals( "HTTP/1.0" ) )
+ throw new IOException( "Invalid HTTP response" );
+
+ String status = line.substring( 9, 12 );
+ msg.setStatusCode( Integer.parseInt( status ) );
+ msg.setStatusMessage( line.substring( 13 ) );
+ }
+
+
+ public void decodeHeader( String line, HttpResponseMessage msg ) throws Exception
+ {
+ int pos = line.indexOf( ": " );
+ String name = line.substring( 0, pos );
+ String value = line.substring( pos + 2 );
+ msg.addHeader( name, value );
+
+ if ( name.equalsIgnoreCase( SET_COOKIE ) )
+ {
+ Cookie cookie = decodeCookie( value );
+ if ( cookie != null )
+ msg.addCookie( cookie );
+ }
+
+ if ( name.equalsIgnoreCase( HttpMessage.CONTENT_TYPE ) )
+ {
+ msg.setContentType( value );
+ }
+
+ if ( name.equalsIgnoreCase( HttpMessage.CONTENT_LENGTH ) )
+ {
+ msg.setContentLength( Integer.parseInt( value ) );
+ }
+
+ if ( name.equalsIgnoreCase( TRANSFER_ENCODING ) && value != null && value.equalsIgnoreCase( CHUNKED ) )
+ {
+ msg.setChunked( true );
+ }
+
+ }
+
+
+ public int decodeSize( String line ) throws Exception
+ {
+ String strippedLine = line.trim().toLowerCase();
+ for ( int i = 0; i < strippedLine.length(); i++ )
+ {
+ char ch = strippedLine.charAt( i );
+ //Once we hit a non-numeric character, parse the number we have
+ if ( ( ch < '0' || ( ch > '9' && ch < 'a' ) || ch > 'f' ) )
+ {
+ return Integer.parseInt( strippedLine.substring( 0, i ), 16 );
+ }
+ }
+
+ //We got here, so the entire line passes
+ return Integer.parseInt( strippedLine, 16 );
+ }
+
+
+ public void decodeContent( ByteBuffer in, HttpResponseMessage msg ) throws Exception
+ {
+ byte content[] = new byte[msg.getContentLength()];
+ in.get( content );
+ msg.addContent( content );
+ }
+
+
+ public void decodeChunkedContent( ByteBuffer in, HttpResponseMessage msg ) throws Exception
+ {
+ int toRead = msg.getExpectedToRead();
+ if ( ( in.get( in.position() + toRead ) != CR ) && ( in.get( in.position() + toRead + 1 ) != LF ) )
+ {
+ throw new IOException( "Invalid HTTP response - chunk does not end with CRLF" );
+
+ }
+ byte content[] = new byte[toRead];
+ in.get( content );
+ msg.addContent( content );
+
+ //Pop the CRLF
+ in.get();
+ in.get();
+ }
+
+
+ public Cookie decodeCookie( String cookieStr ) throws Exception
+ {
+
+ Cookie cookie = null;
+
+ String pairs[] = cookieStr.split( ";" );
+ for ( int i = 0; i < pairs.length; i++ )
+ {
+ String nameValue[] = pairs[i].trim().split( "=" );
+ String name = nameValue[0].trim();
+
+ //First one is the cookie name/value pair
+ if ( i == 0 )
+ {
+ cookie = new Cookie( name, nameValue[1].trim() );
+ continue;
+ }
+
+ if ( name.equalsIgnoreCase( COOKIE_COMMENT ) )
+ {
+ cookie.setComment( nameValue[1].trim() );
+ continue;
+ }
+
+ if ( name.equalsIgnoreCase( COOKIE_PATH ) )
+ {
+ cookie.setPath( nameValue[1].trim() );
+ }
+
+ if ( name.equalsIgnoreCase( COOKIE_SECURE ) )
+ {
+ cookie.setSecure( true );
+ }
+
+ if ( name.equalsIgnoreCase( COOKIE_VERSION ) )
+ {
+ cookie.setVersion( Integer.parseInt( nameValue[1] ) );
+ }
+
+ if ( name.equalsIgnoreCase( COOKIE_MAX_AGE ) )
+ {
+ int age = Integer.parseInt( nameValue[1] );
+ cookie.setExpires( new Date( System.currentTimeMillis() + age * 1000L ) );
+ }
+
+ if ( name.equalsIgnoreCase( COOKIE_EXPIRES ) )
+ {
+ cookie.setExpires( DateUtil.parseDate( nameValue[1] ) );
+ }
+
+ }
+
+ return cookie;
+ }
+}
Added: mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpMessage.java
URL: http://svn.apache.org/viewvc/mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpMessage.java?rev=570271&view=auto
==============================================================================
--- mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpMessage.java (added)
+++ mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpMessage.java Mon Aug 27 17:00:46 2007
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.codec;
+
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.mina.http.util.NameValuePair;
+
+
+/**
+ * TODO HttpMessage.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HttpMessage
+{
+
+ public final static String CONTENT_TYPE = "Content-Type";
+ public final static String CONTENT_LENGTH = "Content-Length";
+
+ protected List<NameValuePair> headers = new ArrayList<NameValuePair>();
+ protected List<Cookie> cookies = new ArrayList<Cookie>();
+ protected String contentType;
+ protected int contentLength;
+ protected ByteArrayOutputStream content;
+
+
+ public String getStringContent()
+ {
+ if ( content == null )
+ return null;
+
+ return new String( content.toByteArray() );
+ }
+
+
+ public byte[] getContent()
+ {
+ if ( content == null )
+ return null;
+
+ return content.toByteArray();
+ }
+
+
+ public void addContent( byte[] content ) throws IOException
+ {
+ if ( this.content == null )
+ this.content = new ByteArrayOutputStream();
+
+ this.content.write( content );
+ }
+
+
+ public List<Cookie> getCookies()
+ {
+ return cookies;
+ }
+
+
+ public void setCookies( List<Cookie> cookies )
+ {
+ this.cookies = cookies;
+ }
+
+
+ public void addCookie( Cookie cookie )
+ {
+ this.cookies.add( cookie );
+ }
+
+
+ public List<NameValuePair> getHeaders()
+ {
+ return headers;
+ }
+
+
+ public void setHeaders( List<NameValuePair> headers )
+ {
+ this.headers = headers;
+ }
+
+
+ public void addHeader( NameValuePair header )
+ {
+ headers.add( header );
+ }
+
+
+ public void addHeader( String name, String value )
+ {
+ headers.add( new NameValuePair( name, value ) );
+ }
+
+
+ public String getContentType()
+ {
+ return contentType;
+ }
+
+
+ public void setContentType( String contentType )
+ {
+ this.contentType = contentType;
+ }
+
+
+ public int getContentLength()
+ {
+ return contentLength;
+ }
+
+
+ public void setContentLength( int contentLength )
+ {
+ this.contentLength = contentLength;
+ }
+
+}
Added: mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpProtocolCodecFactory.java
URL: http://svn.apache.org/viewvc/mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpProtocolCodecFactory.java?rev=570271&view=auto
==============================================================================
--- mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpProtocolCodecFactory.java (added)
+++ mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpProtocolCodecFactory.java Mon Aug 27 17:00:46 2007
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.codec;
+
+
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+
+import java.net.URL;
+
+
+/**
+ * TODO HttpProtocolCodecFactory.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HttpProtocolCodecFactory implements ProtocolCodecFactory
+{
+
+ private final ProtocolEncoder encoder;
+ private final ProtocolDecoder decoder;
+
+
+ public HttpProtocolCodecFactory( URL url )
+ {
+ encoder = new HttpRequestEncoder( url );
+ decoder = new HttpResponseDecoder();
+ }
+
+
+ public ProtocolEncoder getEncoder() throws Exception
+ {
+ return encoder;
+ }
+
+
+ public ProtocolDecoder getDecoder() throws Exception
+ {
+ return decoder;
+ }
+}
Added: mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpRequestEncoder.java
URL: http://svn.apache.org/viewvc/mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpRequestEncoder.java?rev=570271&view=auto
==============================================================================
--- mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpRequestEncoder.java (added)
+++ mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpRequestEncoder.java Mon Aug 27 17:00:46 2007
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.codec;
+
+
+import java.net.URL;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+import org.apache.mina.http.util.EncodingUtil;
+import org.apache.mina.http.util.NameValuePair;
+
+
+/**
+ * TODO HttpRequestEncoder.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HttpRequestEncoder extends ProtocolEncoderAdapter
+{
+ private static final Set<Class<HttpRequestMessage>> TYPES;
+ private static final byte[] CRLF = new byte[]
+ { 0x0D, 0x0A };
+ private static final String POST_CONTENT_TYPE = "application/x-www-form-urlencoded";
+ private URL url;
+
+ static
+ {
+ Set<Class<HttpRequestMessage>> types = new HashSet<Class<HttpRequestMessage>>();
+ types.add( HttpRequestMessage.class );
+ TYPES = Collections.unmodifiableSet( types );
+ }
+
+
+ public HttpRequestEncoder( URL url )
+ {
+ this.url = url;
+ }
+
+
+ Set<Class<HttpRequestMessage>> getMessageTypes()
+ {
+ return TYPES;
+ }
+
+
+ public void encode( IoSession ioSession, Object message, ProtocolEncoderOutput out ) throws Exception
+ {
+ HttpRequestMessage msg = ( HttpRequestMessage ) message;
+
+ ByteBuffer buf = ByteBuffer.allocate( 256 );
+
+ // Enable auto-expand for easier encoding
+ buf.setAutoExpand( true );
+
+ try
+ {
+ //If we have content, lets create the query string
+ int attrCount = msg.getParameters().size();
+ String urlAttrs = "";
+ if ( attrCount > 0 )
+ {
+ NameValuePair attrs[] = new NameValuePair[attrCount];
+ Set<Map.Entry<String, String>> set = msg.getParameters().entrySet();
+ int i = 0;
+ for ( Map.Entry<String, String> entry : set )
+ {
+ attrs[i++] = new NameValuePair( entry.getKey(), entry.getValue() );
+ }
+ urlAttrs = EncodingUtil.formUrlEncode( attrs, Charset.defaultCharset().toString() );
+ }
+
+ CharsetEncoder encoder = Charset.defaultCharset().newEncoder();
+ buf.putString( msg.getRequestMethod(), encoder );
+ buf.putString( " ", encoder );
+ buf.putString( msg.getPath(), encoder );
+ //If its a GET, append the attributes
+ if ( msg.getRequestMethod().equals( HttpRequestMessage.REQUEST_GET ) && attrCount > 0 )
+ {
+ //If there is not already a ? in the query, append one, otherwise append a &
+ if ( !msg.getPath().contains( "?" ) )
+ {
+ buf.putString( "?", encoder );
+ }
+ else
+ {
+ buf.putString( "&", encoder );
+ }
+ buf.putString( urlAttrs, encoder );
+ }
+ buf.putString( " HTTP/1.1", encoder );
+ buf.put( CRLF );
+
+ //This header is required for HTTP/1.1
+ buf.putString( "Host: ", encoder );
+ buf.putString( url.getHost(), encoder );
+ buf.putString( ":", encoder );
+ buf.putString( url.getPort() + "", encoder );
+ buf.put( CRLF );
+
+ //Process any headers we have
+ List<NameValuePair> headers = msg.getHeaders();
+ for ( NameValuePair header : headers )
+ {
+ String name = header.getName();
+ String value = header.getValue();
+
+ buf.putString( name, encoder );
+ buf.putString( ": ", encoder );
+ buf.putString( value, encoder );
+ buf.put( CRLF );
+ }
+
+ //Process cookies
+ //NOTE: I am just passing the name value pairs and not doing management of the expiration or path
+ //As that will be left up to the user. A possible enhancement is to make use of a CookieManager
+ //to handle these issues for the request
+ List<Cookie> cookies = msg.getCookies();
+ if ( cookies.size() > 0 )
+ {
+ buf.putString( "Cookie: ", encoder );
+ for ( Cookie cookie : cookies )
+ {
+ String name = cookie.getName();
+ String value = cookie.getValue();
+
+ buf.putString( name, encoder );
+ buf.putString( "=", encoder );
+ buf.putString( value, encoder );
+ buf.putString( "; ", encoder );
+ }
+ buf.put( CRLF );
+ }
+
+ //If this is a POST, then we need a content length and type
+ if ( msg.getRequestMethod().equals( HttpRequestMessage.REQUEST_POST ) )
+ {
+ byte content[] = urlAttrs.getBytes();
+
+ //Type
+ buf.putString( HttpMessage.CONTENT_TYPE, encoder );
+ buf.putString( ": ", encoder );
+ buf.putString( POST_CONTENT_TYPE, encoder );
+ buf.put( CRLF );
+
+ //Length
+ buf.putString( HttpMessage.CONTENT_LENGTH, encoder );
+ buf.putString( ": ", encoder );
+ buf.putString( content.length + "", encoder );
+ buf.put( CRLF );
+ //Blank line
+ buf.put( CRLF );
+ buf.put( content );
+ }
+ else
+ {
+ //Blank line
+ buf.put( CRLF );
+ }
+
+ }
+ catch ( CharacterCodingException ex )
+ {
+ ex.printStackTrace();
+ }
+
+ buf.flip();
+ out.write( buf );
+
+ }
+
+}
Added: mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpRequestMessage.java
URL: http://svn.apache.org/viewvc/mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpRequestMessage.java?rev=570271&view=auto
==============================================================================
--- mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpRequestMessage.java (added)
+++ mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpRequestMessage.java Mon Aug 27 17:00:46 2007
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.codec;
+
+
+import java.net.ProtocolException;
+import java.util.Map;
+import java.util.HashMap;
+
+
+/**
+ * TODO HttpRequestMessage.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HttpRequestMessage extends HttpMessage
+{
+
+ public static String REQUEST_GET = "GET";
+ public static String REQUEST_POST = "POST";
+ public static String REQUEST_HEAD = "HEAD";
+ public static String REQUEST_OPTIONS = "OPTIONS";
+ public static String REQUEST_PUT = "PUT";
+ public static String REQUEST_DELETE = "DELETE";
+ public static String REQUEST_TRACE = "TRACE";
+
+ private String requestMethod = REQUEST_GET;
+ private String path;
+ private Map<String, String> parameters = new HashMap<String, String>();
+
+
+ public HttpRequestMessage( String path )
+ {
+ this.path = path;
+ }
+
+
+ public String getRequestMethod()
+ {
+ return requestMethod;
+ }
+
+
+ public void setRequestMethod( String requestMethod ) throws ProtocolException
+ {
+ if ( requestMethod.equals( REQUEST_GET ) || requestMethod.equals( REQUEST_POST )
+ || requestMethod.equals( REQUEST_HEAD ) || requestMethod.equals( REQUEST_OPTIONS )
+ || requestMethod.equals( REQUEST_PUT ) || requestMethod.equals( REQUEST_DELETE )
+ || requestMethod.equals( REQUEST_TRACE ) )
+ {
+ this.requestMethod = requestMethod;
+ return;
+ }
+
+ throw new ProtocolException( "Invalid request method type." );
+ }
+
+
+ public String getPath()
+ {
+ return path;
+ }
+
+
+ public void setPath( String path )
+ {
+ if ( path == null || path.trim().length() == 0 )
+ path = "/";
+ this.path = path;
+ }
+
+
+ public String getParameter( String name )
+ {
+ return parameters.get( name );
+ }
+
+
+ public Map<String, String> getParameters()
+ {
+ return parameters;
+ }
+
+
+ public void setParameters( Map<String, String> parameters )
+ {
+ this.parameters.putAll( parameters );
+ }
+
+
+ public void setParameter( String name, String value )
+ {
+ parameters.put( name, value );
+ }
+}
Added: mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpResponseDecoder.java
URL: http://svn.apache.org/viewvc/mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpResponseDecoder.java?rev=570271&view=auto
==============================================================================
--- mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpResponseDecoder.java (added)
+++ mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpResponseDecoder.java Mon Aug 27 17:00:46 2007
@@ -0,0 +1,242 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.codec;
+
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+
+
+/**
+ * TODO HttpResponseDecoder.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HttpResponseDecoder extends CumulativeProtocolDecoder
+{
+
+ public final static String CURRENT_RESPONSE = "CURRENT_RESPONSE";
+
+ private HttpDecoder httpDecoder = new HttpDecoder();
+
+
+ protected boolean doDecode( IoSession ioSession, ByteBuffer in, ProtocolDecoderOutput out ) throws Exception
+ {
+
+ HttpResponseMessage response = ( HttpResponseMessage ) ioSession.getAttribute( CURRENT_RESPONSE );
+ if ( response == null )
+ {
+ response = new HttpResponseMessage();
+ ioSession.setAttribute( CURRENT_RESPONSE, response );
+ }
+
+ //Test if we need the response...
+ if ( response.getState() == HttpResponseMessage.STATE_START )
+ {
+
+ if ( !processStatus( response, in ) )
+ {
+ return false;
+ }
+
+ //Handle HTTP/1.1 100 Continue
+ if ( response.getStatusCode() == 100 )
+ {
+ response.setState( HttpResponseMessage.STATE_STATUS_CONTINUE );
+ }
+ else
+ {
+ response.setState( HttpResponseMessage.STATE_STATUS_READ );
+ }
+ }
+
+ //If we are in a 100 Continue, read until we get the real header
+ if ( response.getState() == HttpResponseMessage.STATE_STATUS_CONTINUE )
+ {
+ //Continue reading until we get a blank line
+ while ( true )
+ {
+ String line = httpDecoder.decodeLine( in );
+
+ //Check if the entire response has been read
+ if ( line == null )
+ return false;
+
+ //Check if the entire response headers have been read
+ if ( line.length() == 0 )
+ {
+ response.setState( HttpResponseMessage.STATE_STATUS_READ );
+
+ //The next line should be a header
+ if ( !processStatus( response, in ) )
+ {
+ return false;
+ }
+ break;
+ }
+ }
+ }
+
+ //Are we reading headers?
+ if ( response.getState() == HttpResponseMessage.STATE_STATUS_READ )
+ {
+ if ( processHeaders( response, in ) == false )
+ return false;
+ }
+
+ //Are we reading content?
+ if ( response.getState() == HttpResponseMessage.STATE_HEADERS_READ )
+ {
+ if ( processContent( response, in ) == false )
+ return false;
+ }
+
+ //If we are chunked and we have read all the content, then read the footers if there are any
+ if ( response.isChunked() && response.getState() == HttpResponseMessage.STATE_CONTENT_READ )
+ {
+ if ( processFooters( response, in ) == false )
+ return false;
+ }
+
+ response.setState( HttpResponseMessage.STATE_FINISHED );
+
+ out.write( response );
+
+ ioSession.removeAttribute( CURRENT_RESPONSE );
+
+ return true;
+ }
+
+
+ private boolean processHeaders( HttpResponseMessage response, ByteBuffer in ) throws Exception
+ {
+ if ( !findHeaders( response, in ) )
+ return false;
+
+ response.setState( HttpResponseMessage.STATE_HEADERS_READ );
+ return true;
+ }
+
+
+ private boolean processFooters( HttpResponseMessage response, ByteBuffer in ) throws Exception
+ {
+ if ( !findHeaders( response, in ) )
+ return false;
+
+ response.setState( HttpResponseMessage.STATE_FOOTERS_READ );
+ return true;
+ }
+
+
+ private boolean findHeaders( HttpResponseMessage response, ByteBuffer in ) throws Exception
+ {
+ //Read the headers and process them
+ while ( true )
+ {
+ String line = httpDecoder.decodeLine( in );
+
+ //Check if the entire response has been read
+ if ( line == null )
+ return false;
+
+ //Check if the entire response headers have been read
+ if ( line.length() == 0 )
+ {
+ break;
+ }
+
+ httpDecoder.decodeHeader( line, response );
+ }
+ return true;
+ }
+
+
+ private boolean processContent( HttpResponseMessage response, ByteBuffer in ) throws Exception
+ {
+ if ( response.isChunked() )
+ {
+ while ( true )
+ {
+ //Check what kind of record we are reading (content or size)
+ if ( response.getExpectedToRead() == HttpResponseMessage.EXPECTED_NOT_READ )
+ {
+ //We haven't read the size, so we are expecting a size
+ String line = httpDecoder.decodeLine( in );
+
+ //Check if the entire line has been read
+ if ( line == null )
+ return false;
+
+ response.setExpectedToRead( httpDecoder.decodeSize( line ) );
+
+ //Are we done reading the chunked content? (A zero means we are done)
+ if ( response.getExpectedToRead() == 0 )
+ {
+ break;
+ }
+ }
+
+ //Now read the content chunk
+
+ //Be sure all of the data is there for us to retrieve + the CRLF...
+ if ( response.getExpectedToRead() + 2 > in.remaining() )
+ {
+ //Need more data
+ return false;
+ }
+
+ //Read the content
+ httpDecoder.decodeChunkedContent( in, response );
+
+ //Flag that it's time to read a size record
+ response.setExpectedToRead( HttpResponseMessage.EXPECTED_NOT_READ );
+
+ }
+
+ }
+ else if ( response.getContentLength() > 0 )
+ {
+ //Do we have enough data?
+ if ( ( response.getContentLength() ) > in.remaining() )
+ return false;
+ httpDecoder.decodeContent( in, response );
+ }
+
+ response.setState( HttpResponseMessage.STATE_CONTENT_READ );
+
+ return true;
+ }
+
+
+ private boolean processStatus( HttpResponseMessage response, ByteBuffer in ) throws Exception
+ {
+ //Read the status header
+ String header = httpDecoder.decodeLine( in );
+ if ( header == null )
+ return false;
+
+ httpDecoder.decodeStatus( header, response );
+
+ return true;
+ }
+}
Added: mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpResponseMessage.java
URL: http://svn.apache.org/viewvc/mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpResponseMessage.java?rev=570271&view=auto
==============================================================================
--- mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpResponseMessage.java (added)
+++ mina/trunk/mina-filter-codec-http/src/main/java/org/apache/mina/http/codec/HttpResponseMessage.java Mon Aug 27 17:00:46 2007
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.codec;
+
+
+/**
+ * TODO HttpResponseMessage.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HttpResponseMessage extends HttpMessage
+{
+
+ static final int EXPECTED_NOT_READ = -1;
+
+ static final int STATE_START = 0;
+ static final int STATE_STATUS_CONTINUE = 1;
+ static final int STATE_STATUS_READ = 2;
+ static final int STATE_HEADERS_READ = 3;
+ static final int STATE_CONTENT_READ = 4;
+ static final int STATE_FOOTERS_READ = 5;
+ static final int STATE_FINISHED = 6;
+
+ private int statusCode;
+ private String statusMessage;
+
+ private boolean chunked = false;
+ private int expectedToRead = -1;
+ private int state = STATE_START;
+
+
+ public int getStatusCode()
+ {
+ return statusCode;
+ }
+
+
+ public void setStatusCode( int statusCode )
+ {
+ this.statusCode = statusCode;
+ }
+
+
+ public String getStatusMessage()
+ {
+ return statusMessage;
+ }
+
+
+ public void setStatusMessage( String statusMessage )
+ {
+ this.statusMessage = statusMessage;
+ }
+
+
+ boolean isChunked()
+ {
+ return chunked;
+ }
+
+
+ void setChunked( boolean chunked )
+ {
+ this.chunked = chunked;
+ }
+
+
+ int getExpectedToRead()
+ {
+ return expectedToRead;
+ }
+
+
+ void setExpectedToRead( int expectedToRead )
+ {
+ this.expectedToRead = expectedToRead;
+ }
+
+
+ int getState()
+ {
+ return state;
+ }
+
+
+ void setState( int state )
+ {
+ this.state = state;
+ }
+
+}