javacommons/gcfprotocols/http/javasrc.s60/com/nokia/mj/impl/http/HttpConnectionNative.java
branchRCL_3
changeset 19 04becd199f91
child 24 0fd27995241b
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 package com.nokia.mj.impl.http;
       
    20 
       
    21 import java.io.ByteArrayOutputStream;
       
    22 import java.io.DataInputStream;
       
    23 import java.io.DataOutputStream;
       
    24 import java.io.IOException;
       
    25 import java.io.InputStream;
       
    26 import java.io.OutputStream;
       
    27 import java.util.Enumeration;
       
    28 import java.util.Hashtable;
       
    29 import java.util.Vector;
       
    30 import javax.microedition.io.HttpConnection;
       
    31 import com.nokia.mj.impl.gcf.utils.URI;
       
    32 import com.nokia.mj.impl.rt.support.Jvm;
       
    33 import com.nokia.mj.impl.utils.Logger;
       
    34 import com.nokia.mj.impl.gcf.utils.DateUtil;
       
    35 import com.nokia.mj.impl.gcf.utils.NativeError;
       
    36 import com.nokia.mj.impl.http.BlockingOperation;
       
    37 import com.nokia.mj.impl.rt.support.Finalizer;
       
    38 import com.nokia.mj.impl.connectionmanager.ConnectionManager;
       
    39 import com.nokia.mj.impl.connectionmanager.AccessPoint;
       
    40 import com.nokia.mj.impl.rt.support.ApplicationUtils;
       
    41 import com.nokia.mj.impl.rt.support.ApplicationInfo;
       
    42 import com.nokia.mj.impl.rt.support.ShutdownListener;
       
    43 
       
    44 /**
       
    45  * An HttpConection class implementing an HTTP 1.1 client connection using the
       
    46  * native symbian http client ap
       
    47  *
       
    48  */
       
    49 public class HttpConnectionNative implements HttpConnection,
       
    50         NativeHttpByteSource
       
    51 {
       
    52     protected int iMode;
       
    53     protected int iState;
       
    54     protected boolean iClosed;
       
    55     protected URI iUri;
       
    56     protected String iRef;
       
    57     protected String iRequestMethod;
       
    58     protected Hashtable iRequestProperties;
       
    59     protected int iResponseCode;
       
    60     protected String iResponseMessage;
       
    61     protected Hashtable iReplyHeaders;
       
    62     protected Vector iReplyHeaderKeys;
       
    63     protected long iLength;
       
    64     protected DataInputStream iInputStream;
       
    65     protected boolean iInputStreamOpened = false;
       
    66     protected NativeHttpInputStream iNativeHttpInputStream;
       
    67     protected ByteArrayOutputStream iPostedDataStream;
       
    68     protected DataOutputStream iOutputStream;
       
    69     protected boolean iOutputStreamOpened = false;
       
    70     protected char[] iLineBuffer;
       
    71     protected int iLineBufferLength;
       
    72     protected int iLineLength;
       
    73 
       
    74     // States
       
    75     protected final static int INVALID_STATE = 0;
       
    76     protected final static int SETUP = 1;
       
    77     protected final static int CONNECTED = 2;
       
    78     protected final static int REQUEST_HEADERS_SENT = 3;
       
    79     protected final static int REQUEST_SENT = 4;
       
    80     protected final static int REPLY_RECEIVED = 5;
       
    81 
       
    82     // Character constants
       
    83     protected final static char HASH = '#';
       
    84     protected final static int QUESTION_MARK = 63;
       
    85     protected final static int CR = 13;
       
    86     protected final static int LF = 10;
       
    87     protected final static int SP = 32;
       
    88     protected final static int EOF = -1;
       
    89 
       
    90     // Misc. Constants
       
    91     protected final static byte[] CRLF = { CR, LF };
       
    92     protected final static int DEFAULT_LINE_BUFFER_SIZE = 128;
       
    93     protected final static String VERSION_1_1 = "1.1";
       
    94     protected final static String VERSION_1_0 = "1.0";
       
    95     protected final static String NATIVESEPERATOR = ";;";
       
    96     protected final static String DEFAULT_PATH = "/"; // NOI8N
       
    97     protected final static int DEFAULT_PORT = 80;
       
    98     protected final static String PROTOCOL_SUFFIX = "://";
       
    99 
       
   100     // 'Well-known' Header names
       
   101     protected final static String CONNECTION = "Connection"; // NOI8N
       
   102     protected final static String CONTENT_ENCODING = "Content-Encoding"; // NOI8N
       
   103     protected final static String CONTENT_LENGTH = "Content-Length"; // NOI8N
       
   104     protected final static String CONTENT_TYPE = "Content-Type"; // NOI8N
       
   105     protected final static String DATE = "Date"; // NOI8N
       
   106     protected final static String HOST = "Host"; // NOI8N
       
   107     protected final static String LAST_MODIFIED = "Last-Modified"; // NOI8N
       
   108     protected final static String EXPIRES = "Expires"; // NOI8N
       
   109     protected final static String TRANSFER_ENCODING = "Transfer-Encoding"; // NOI8N
       
   110     protected final static String USER_AGENT = "User-Agent";
       
   111 
       
   112     // 'Well-known' Header values
       
   113     protected final static String UNTRUSTED_1_0 = "UNTRUSTED/1.0";
       
   114 
       
   115     // Connection value
       
   116     protected final static String CLOSE = "close"; // NOI8N
       
   117 
       
   118     // Http-native handle
       
   119     private static int iNativeHttpSessionHandle = 0;
       
   120 
       
   121     protected int iNativeTransactionHande = 0;
       
   122     final BlockingOperation iTransactionBlock;
       
   123 
       
   124     // Custom lock for synchronizing all read operations.
       
   125     protected final BlockingOperation iNativeDataReadyForRead;
       
   126 
       
   127     private Finalizer iFinalizer;
       
   128     protected ConnectionManager iCmInstance = null;
       
   129     protected AccessPoint iApn = null;
       
   130     private static boolean iIsSessionDeleted = false;
       
   131     private boolean iTrustedSuite = true;
       
   132     private int iRespTimeOut = -1;
       
   133     private int iRetries = 0;
       
   134 
       
   135     static
       
   136     {
       
   137         try
       
   138         {
       
   139             Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
   140                        "loading http from HttpConnectionNative.java");
       
   141             Jvm.loadSystemLibrary("javahttp");
       
   142             Logger.LOG(Logger.ESOCKET, Logger.EInfo, "javahttp loaded");
       
   143         }
       
   144         catch (Exception e)
       
   145         {
       
   146             Logger.ELOG(Logger.ESOCKET, e.toString());
       
   147         }
       
   148     }
       
   149 
       
   150     public HttpConnectionNative(int aNativeHttpSessionHandle, String aName,
       
   151                                 int aMode, boolean aTimeouts, ConnectionManager cm,
       
   152                                 AccessPoint apnInfo, int aResponseTimeout) throws IOException
       
   153     {
       
   154         Logger.PLOG(Logger.ESOCKET, "New HTTP connection to URL: " + aName);
       
   155         Logger.ILOG(Logger.ESOCKET, "+++++ HttpConnectionNative new, this ="
       
   156                     + this);
       
   157 
       
   158         int index;
       
   159         iCmInstance = cm;
       
   160         iApn = apnInfo;
       
   161         index = aName.indexOf(HASH);
       
   162         iRespTimeOut = aResponseTimeout; // setting of timeout value for http response.
       
   163         // specific scenario identified in case of java installer.
       
   164 
       
   165         // Handle to shared native RHttpSession
       
   166         if (iNativeHttpSessionHandle == 0)
       
   167         {
       
   168             // only one session per application
       
   169             creatHttpSession();
       
   170         }
       
   171 
       
   172         if (index != -1)
       
   173         {
       
   174             iRef = aName.substring(index + 1);
       
   175             aName = aName.substring(0, index);
       
   176         }
       
   177 
       
   178         iUri = new URI(aName);
       
   179         final String host = iUri.getHost();
       
   180         if (host == null || host.equals(""))
       
   181         {
       
   182             throw new IllegalArgumentException("Invalid url: " + aName);
       
   183         }
       
   184 
       
   185         iMode = aMode;
       
   186         iState = SETUP;
       
   187         iRequestMethod = GET;
       
   188         iRequestProperties = new Hashtable();
       
   189         iReplyHeaders = new Hashtable();
       
   190         iReplyHeaderKeys = new Vector();
       
   191         iLength = -1;
       
   192 
       
   193         // Blocking operations to allow async native transactions
       
   194         iTransactionBlock = new BlockingOperation();
       
   195         iNativeDataReadyForRead = new BlockingOperation();
       
   196         iNativeDataReadyForRead.setResult(BlockingOperation.BLOCKED);
       
   197         iFinalizer = registerForFinalization();        
       
   198         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- HttpConnectionNative new ");
       
   199 
       
   200         ApplicationInfo appInfo = ApplicationInfo.getInstance();
       
   201         String runtime = appInfo.getRuntimeType();
       
   202         boolean  midpRuntime = true;
       
   203 
       
   204         if (runtime == ApplicationInfo.RUNTIME_INSTALLER)
       
   205         {
       
   206             midpRuntime = false;
       
   207         }
       
   208         else
       
   209         {
       
   210             // add the untrusted header for untrusted midlet suite
       
   211             if ((ApplicationInfo.getInstance().getProtectionDomain()
       
   212                     .equals(ApplicationInfo.UNIDENTIFIED_THIRD_PARTY_DOMAIN)) == true)
       
   213             {
       
   214                 iTrustedSuite = false;
       
   215                 iRequestProperties.put(USER_AGENT, UNTRUSTED_1_0);
       
   216             }
       
   217         }
       
   218         // get the default User-Agent headers and add to hashtable
       
   219         final String agent = _getUserAgentHeaderValue(midpRuntime);
       
   220         if (agent != null)
       
   221         {
       
   222             if (iTrustedSuite == false)
       
   223             {
       
   224                 String result = agent + ' ' + UNTRUSTED_1_0;
       
   225                 iRequestProperties.put(USER_AGENT, result);
       
   226             }
       
   227             else
       
   228             {
       
   229                 iRequestProperties.put(USER_AGENT, agent);
       
   230             }
       
   231         }
       
   232     }
       
   233 
       
   234     Finalizer registerForFinalization()
       
   235     {
       
   236         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
   237                    "++HttpConnectionNative::registerForFinalization ");
       
   238         return new Finalizer()
       
   239         {
       
   240             public void finalizeImpl()
       
   241             {
       
   242                 doFinalize();
       
   243             }
       
   244         };
       
   245     }
       
   246 
       
   247 
       
   248     public void doFinalize()
       
   249     {
       
   250         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
   251                    "++HttpConnectionNative::doFinalize ");
       
   252         try
       
   253         {
       
   254             close();
       
   255         }
       
   256         catch(Exception e)
       
   257         {
       
   258  	
       
   259         }
       
   260         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
   261                    "--HttpConnectionNative::doFinalize ");
       
   262     }
       
   263 
       
   264     public void creatHttpSession() throws IOException
       
   265     {
       
   266         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
   267                    "++HttpConnectionNative::creatHttpSession()");
       
   268         int[] retval = new int[2];
       
   269         int handle;
       
   270         int err;
       
   271         if (iApn != null)
       
   272         {
       
   273             handle = _createHttpSession(0, iApn.getType(), iApn.getNapId(),
       
   274                                         retval);
       
   275         }
       
   276         else
       
   277         {
       
   278             handle = _createHttpSession(0, -1, -1, retval);
       
   279         }
       
   280         iNativeHttpSessionHandle = NativeError.check(handle);
       
   281         if (retval[0] < 0)
       
   282         {
       
   283             throw new IOException(
       
   284                 "Unable to open http connection.Creation of Native peer failed.");
       
   285         }
       
   286         if (retval[1] < 0)
       
   287         {
       
   288             // reset connection manager
       
   289             iCmInstance.reset();
       
   290         }
       
   291 
       
   292         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
   293                    "--HttpConnectionNative::creatHttpSession()");
       
   294     }
       
   295 
       
   296     /**
       
   297      * Please refer to Jsr 118
       
   298      */
       
   299     public synchronized void close() throws IOException
       
   300     {
       
   301         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "++++++++++ close()");
       
   302         if (iClosed)
       
   303         {
       
   304             return;
       
   305         }
       
   306         iClosed = true;
       
   307         if ((iInputStream == null) && (iOutputStream == null)
       
   308                 && (iState != SETUP))
       
   309         {
       
   310             if (iNativeHttpInputStream != null)
       
   311             {
       
   312                 iNativeHttpInputStream.close();
       
   313                 iNativeHttpInputStream = null;
       
   314             }
       
   315             closeConnection();
       
   316         }
       
   317         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "------- close()");
       
   318         return;
       
   319     }
       
   320 
       
   321     /**
       
   322      * Please refer to Jsr 118
       
   323      */
       
   324     public synchronized DataInputStream openDataInputStream()
       
   325     throws IOException
       
   326     {
       
   327         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ openDataInputStream()");
       
   328         // prevents multiple read
       
   329         synchronized (iNativeDataReadyForRead.getLock())
       
   330         {
       
   331             ensureOpen("openDataInputStream");
       
   332             if (iInputStreamOpened)
       
   333             {
       
   334                 throwIOException("Input stream is already opened");
       
   335             }
       
   336             ensureResponse();
       
   337             iInputStream = makeDataInputStream();
       
   338             iInputStreamOpened = true;
       
   339             // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "-
       
   340             // openDataInputStream()" );
       
   341             return iInputStream;
       
   342         }
       
   343     }
       
   344 
       
   345     /**
       
   346      * Please refer to Jsr 118
       
   347      */
       
   348     public synchronized InputStream openInputStream() throws IOException
       
   349     {
       
   350         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ openInputStream()" );
       
   351         final InputStream result = openDataInputStream();
       
   352         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- openInputStream()" );
       
   353         return result;
       
   354     }
       
   355 
       
   356 
       
   357     /**
       
   358      * Please refer to Jsr 118
       
   359      */
       
   360 
       
   361     public synchronized DataOutputStream openDataOutputStream()
       
   362     throws IOException
       
   363     {
       
   364         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ openDataOutputStream()"
       
   365         // );
       
   366         ensureOpen("openDataOutputStream");
       
   367         if (iOutputStreamOpened)
       
   368         {
       
   369             throwIOException("Output stream is already opened");
       
   370         }
       
   371         makeDataOutputStream();
       
   372         iOutputStreamOpened = true;
       
   373         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- openDataOutputStream()"
       
   374         // );
       
   375         return iOutputStream;
       
   376     }
       
   377 
       
   378     /**
       
   379      * Please refer to Jsr 118
       
   380      */
       
   381     public synchronized OutputStream openOutputStream() throws IOException
       
   382     {
       
   383         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ openOutputStream()" );
       
   384         final OutputStream result = openDataOutputStream();
       
   385         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- openOutputStream()" );
       
   386         return result;
       
   387     }
       
   388 
       
   389     /**
       
   390      * Please refer to Jsr 118
       
   391      */
       
   392     public synchronized String getEncoding()
       
   393     {
       
   394         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getEncoding()" );
       
   395         String result = null;
       
   396         try
       
   397         {
       
   398             result = getHeaderField(CONTENT_ENCODING);
       
   399         }
       
   400         catch (IOException ex)
       
   401         {
       
   402             // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getEncoding() returns
       
   403             // null" );
       
   404             return null;
       
   405         }
       
   406         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getEncoding()" );
       
   407         return result;
       
   408     }
       
   409 
       
   410     /**
       
   411      * Please refer to Jsr 118
       
   412      */
       
   413     public synchronized long getLength()
       
   414     {
       
   415         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getLength()");
       
   416         try
       
   417         {
       
   418             ensureOpen("getLength");
       
   419             ensureResponse();
       
   420             // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getLength() : " +
       
   421             // iLength);
       
   422             return iLength;
       
   423         }
       
   424         catch (IOException ex)
       
   425         {
       
   426             // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getLength() set -1
       
   427             // IOException: "+ ex.toString() );
       
   428             return -1;
       
   429         }
       
   430     }
       
   431 
       
   432     /**
       
   433      * Please refer to Jsr 118
       
   434      */
       
   435     public synchronized String getType()
       
   436     {
       
   437         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getType()" );
       
   438         String result = null;
       
   439         try
       
   440         {
       
   441             result = getHeaderField(CONTENT_TYPE);
       
   442         }
       
   443         catch (IOException ex)
       
   444         {
       
   445             // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getType() returns
       
   446             // null" );
       
   447             // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getType() NULL");
       
   448             return null;
       
   449         }
       
   450         //Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getType()" + result);
       
   451         return result;
       
   452     }
       
   453 
       
   454     // HttpConnection interface implementation
       
   455 
       
   456     public synchronized long getDate() throws IOException
       
   457     {
       
   458         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getDate()" );
       
   459         final long result = getHeaderFieldDate(DATE, 0);
       
   460         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getDate()" );
       
   461         return result;
       
   462     }
       
   463 
       
   464     public synchronized long getExpiration() throws IOException
       
   465     {
       
   466         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getExpiration()" );
       
   467         final long result = getHeaderFieldDate(EXPIRES, 0);
       
   468         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getExpiration()" );
       
   469         return result;
       
   470     }
       
   471 
       
   472     public String getFile()
       
   473     {
       
   474         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getFile()" );
       
   475         String result = iUri.getPath();
       
   476         if (result.length() == 0)
       
   477             result = null;
       
   478         else
       
   479             result = "/" + result;
       
   480         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getFile: " + result );
       
   481         return result;
       
   482     }
       
   483 
       
   484     public synchronized String getHeaderField(int aIndex) throws IOException
       
   485     {
       
   486         ensureOpen("getHeaderField");
       
   487         ensureResponse();
       
   488         if (aIndex >= iReplyHeaderKeys.size() || aIndex < 0)
       
   489         {
       
   490             // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getHeaderField(int)
       
   491             // returns null" );
       
   492             return null;
       
   493         }
       
   494         final String result = (String) iReplyHeaders.get(iReplyHeaderKeys
       
   495                               .elementAt(aIndex));
       
   496         if (result != null)
       
   497         {
       
   498             int length = result.length();
       
   499             String keys = (String) iReplyHeaderKeys.elementAt(aIndex);
       
   500             if (keys.equalsIgnoreCase("Set-Cookie") == true)
       
   501             {
       
   502                 // first cookie is discarded
       
   503                 if ((result.charAt(0)) == ',')
       
   504                 {
       
   505                     throw new IOException(
       
   506                         "cookie size too large - hence discarded");
       
   507                 }
       
   508 
       
   509                 // last cookie is discarded
       
   510                 if ((result.charAt(length - 2)) == ',')
       
   511                 {
       
   512                     throw new IOException(
       
   513                         "cookie size too large - hence discarded");
       
   514                 }
       
   515 
       
   516                 int index = result.indexOf(", ,", 0);
       
   517                 if (index != -1)
       
   518                 {
       
   519                     throw new IOException(
       
   520                         "cookie size too large - hence discarded");
       
   521                 }
       
   522             }
       
   523         }
       
   524         //Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getHeaderField(int)" );
       
   525         //Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getHeaderField(int): "  + result);
       
   526         return result;
       
   527     }
       
   528 
       
   529     public synchronized String getHeaderField(String aName) throws IOException
       
   530     {
       
   531         ensureOpen("getHeaderField");
       
   532         ensureResponse();
       
   533         if (aName == null)
       
   534         {
       
   535             // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "--
       
   536             // getHeaderField(String) returns null" );
       
   537             return null;
       
   538         }
       
   539         final String result = (String) iReplyHeaders.get(aName.toLowerCase());
       
   540 
       
   541         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getHeaderField(String): "
       
   542                    + result);
       
   543         if (result != null)
       
   544         {
       
   545             int length = result.length();
       
   546             if (aName.equalsIgnoreCase("Set-Cookie") == true)
       
   547             {
       
   548                 // first cookie is discarded
       
   549                 if ((result.charAt(0)) == ',')
       
   550                 {
       
   551                     throw new IOException(
       
   552                         "cookie size too large - hence discarded");
       
   553                 }
       
   554 
       
   555                 // last cookie is discarded
       
   556                 if ((result.charAt(length - 2)) == ',')
       
   557                 {
       
   558                     throw new IOException(
       
   559                         "cookie size too large - hence discarded");
       
   560                 }
       
   561 
       
   562                 int index = result.indexOf(", ,", 0);
       
   563                 if (index != -1)
       
   564                 {
       
   565                     throw new IOException(
       
   566                         "cookie size too large - hence discarded");
       
   567                 }
       
   568             }
       
   569         }
       
   570         return result;
       
   571     }
       
   572 
       
   573     public synchronized long getHeaderFieldDate(String aName, long aDfault)
       
   574     throws IOException
       
   575     {
       
   576         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
   577                    "+ getHeaderFieldDate(String, long)");
       
   578         String value;
       
   579 
       
   580         value = getHeaderField(aName);
       
   581         if (value != null)
       
   582         {
       
   583             final long result = parseDate(value);
       
   584             Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
   585                        "- getHeaderFieldDate(String, long)");
       
   586             return result;
       
   587         }
       
   588         else
       
   589         {
       
   590             Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
   591                        "- getHeaderFieldDate(String, long) return aDfault");
       
   592             return aDfault;
       
   593         }
       
   594     }
       
   595 
       
   596     public synchronized int getHeaderFieldInt(String aName, int aDfault)
       
   597     throws IOException
       
   598     {
       
   599         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
   600                    "+ getHeaderFieldInt(String, int) , name = " + aName
       
   601                    + "default = " + aDfault);
       
   602         String value;
       
   603 
       
   604         value = getHeaderField(aName);
       
   605         if (value == null)
       
   606         {
       
   607             Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
   608                        "- getHeaderFieldInt(String, int) returns aDfault");
       
   609             return aDfault;
       
   610         }
       
   611         else
       
   612         {
       
   613             try
       
   614             {
       
   615                 final int result = Integer.parseInt(value);
       
   616                 // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "-
       
   617                 // getHeaderFieldInt(String, int)" );
       
   618                 return result;
       
   619             }
       
   620             catch (NumberFormatException nfe)
       
   621             {
       
   622                 //Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getHeaderFieldInt (String, int): " + aDfault);
       
   623                 return aDfault;
       
   624             }
       
   625         }
       
   626     }
       
   627 
       
   628     public synchronized String getHeaderFieldKey(int aIndex) throws IOException
       
   629     {
       
   630         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getHeaderFieldKey(int)"
       
   631         // );
       
   632         ensureOpen("getHeaderFieldKey");
       
   633         ensureResponse();
       
   634         if (aIndex >= iReplyHeaderKeys.size() || aIndex < 0)
       
   635         {
       
   636             // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "-
       
   637             // getHeaderFieldKey(int) returns null" );
       
   638             return null;
       
   639         }
       
   640         final String result = (String) iReplyHeaderKeys.elementAt(aIndex);
       
   641         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getHeaderFieldKey(int)"
       
   642         // );
       
   643         return result;
       
   644     }
       
   645 
       
   646     public String getHost()
       
   647     {
       
   648         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getHost()" );
       
   649         final String result = iUri.getHost();
       
   650         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getHost()" );
       
   651         return result;
       
   652     }
       
   653 
       
   654     public synchronized long getLastModified() throws IOException
       
   655     {
       
   656         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getLastModified()" );
       
   657         final long result = getHeaderFieldDate(LAST_MODIFIED, 0);
       
   658         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getLastModified()" );
       
   659         return result;
       
   660     }
       
   661 
       
   662     public int getPort()
       
   663     {
       
   664         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getPort()" );
       
   665         final String temp = iUri.getPort();
       
   666         if (temp.length() != 0)
       
   667         {
       
   668             try
       
   669             {
       
   670                 final int result = Integer.parseInt(temp);
       
   671                 // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getPort()" );
       
   672                 return result;
       
   673             }
       
   674             catch (NumberFormatException ex)
       
   675             {
       
   676                 // do nothing, return default port
       
   677             }
       
   678         }
       
   679         //Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getPort() returns default port" );
       
   680         return DEFAULT_PORT;
       
   681     }
       
   682 
       
   683     public String getProtocol()
       
   684     {
       
   685         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getProtocol()" );
       
   686         final String result = iUri.getProtocol();
       
   687         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getProtocol()" );
       
   688         return result;
       
   689     }
       
   690 
       
   691     public String getQuery()
       
   692     {
       
   693         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getQuery()" );
       
   694         String result = iUri.getQuery();
       
   695         if (result.length() == 0)
       
   696             result = null;
       
   697         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getQuery()" );
       
   698         return result;
       
   699     }
       
   700 
       
   701     public String getRef()
       
   702     {
       
   703         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "* getRef()" );
       
   704         return iRef;
       
   705     }
       
   706 
       
   707     public final String getRequestMethod()
       
   708     {
       
   709         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "* getRequestMethod()" );
       
   710         return iRequestMethod;
       
   711     }
       
   712 
       
   713     public final String getRequestProperty(String aKey)
       
   714     {
       
   715         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+
       
   716         // getRequestProperty(String)" );
       
   717         final String result = (String) iRequestProperties.get(aKey);
       
   718 
       
   719         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "-
       
   720         // getRequestProperty(String)" );
       
   721         return result;
       
   722     }
       
   723 
       
   724     public synchronized final int getResponseCode() throws IOException
       
   725     {
       
   726         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getResponseCode()");
       
   727         ensureOpen("getResponseCode");
       
   728         ensureResponse();
       
   729         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getResponseCode() : "
       
   730                    + iResponseCode);
       
   731         return iResponseCode;
       
   732     }
       
   733 
       
   734     public synchronized String getResponseMessage() throws IOException
       
   735     {
       
   736         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getResponseMessage()" );
       
   737         ensureOpen("getResponseMessage");
       
   738         ensureResponse();
       
   739         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getResponseMessage() : "
       
   740         // + iResponseMessage);
       
   741         return iResponseMessage;
       
   742     }
       
   743 
       
   744     public String getURL()
       
   745     {
       
   746         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getURL()" );
       
   747         final String result = iUri.toString();
       
   748         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getURL()" );
       
   749         return result;
       
   750     }
       
   751 
       
   752     /**
       
   753          * Please refer to Jsr 118
       
   754          */
       
   755     public synchronized void setRequestMethod(String aMethod)
       
   756     throws IOException
       
   757     {
       
   758         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ setRequestMethod(String)"
       
   759         // );
       
   760         try
       
   761         {
       
   762             if (aMethod == null)
       
   763             {
       
   764                 throw new NullPointerException("Request method is null");
       
   765             }
       
   766             ensureOpen("setRequestMethod");
       
   767             if (iState != SETUP)
       
   768             {
       
   769                 throwIOException("setRequestMethod method failed.Connection state is already connected");
       
   770             }
       
   771             if ((GET.equals(aMethod) == false)
       
   772                     && (HEAD.equals(aMethod) == false)
       
   773                     && (POST.equals(aMethod) == false))
       
   774             {
       
   775                 throwIOException("Invalid or Unsupported request method: "
       
   776                                  + aMethod);
       
   777             }
       
   778             // ignore if an output stream has already been open
       
   779             if (iPostedDataStream == null)
       
   780                 iRequestMethod = aMethod;
       
   781         }
       
   782         catch (IOException ex)
       
   783         {
       
   784             Logger.WLOG(Logger.ESOCKET, "setRequestMethod failed", ex);
       
   785             throw ex;
       
   786         }
       
   787         //Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- setRequestMethod(String)" );
       
   788         return;
       
   789     }
       
   790 
       
   791     /**
       
   792          * Please refer to Jsr 118
       
   793          */
       
   794     public synchronized void setRequestProperty(String aKey, String aValue)
       
   795     throws IOException
       
   796     {
       
   797         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ setRequestProperty( " +
       
   798         // aKey + " , " + aValue );
       
   799         ensureOpen("setRequestProperty");
       
   800         if (iState != SETUP)
       
   801         {
       
   802             throwIOException("setRequestProperty method failed.Connection state is already connected");
       
   803         }
       
   804 
       
   805         // ignore if an outputstream has been open
       
   806         if (iPostedDataStream == null)
       
   807         {
       
   808             if (aKey.equals(USER_AGENT) && !iTrustedSuite)
       
   809             {
       
   810                 String val = aValue + ' ' + UNTRUSTED_1_0;
       
   811                 iRequestProperties.put(aKey, val);
       
   812             }
       
   813             else
       
   814             {
       
   815                 iRequestProperties.put(aKey, aValue);
       
   816             }
       
   817         }
       
   818         //Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- setRequestProperty(String, String)" );
       
   819         return;
       
   820     }
       
   821 
       
   822     protected void closeConnection() throws IOException
       
   823     {
       
   824         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
   825                    "++++++++++++++ Java closeConnection()");
       
   826         if ((iNativeTransactionHande != 0) &&(iNativeHttpSessionHandle!=0))
       
   827         {
       
   828             Logger.LOG(Logger.ESOCKET, Logger.EInfo, "########## Valid handle");
       
   829             _closeTransaction(iNativeTransactionHande);
       
   830             iNativeTransactionHande = 0;
       
   831 
       
   832         }
       
   833         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
   834                    "-------------- Java closeConnection()");
       
   835     }
       
   836 
       
   837     protected void addHeader(String aKey, String aValue)
       
   838     {
       
   839         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ addHeader to reply enum(
       
   840         // " + aKey + " , " + aValue );
       
   841         // Should check for duplicate keys
       
   842         aKey = aKey.toLowerCase();
       
   843         iReplyHeaders.put(aKey, aValue);
       
   844         iReplyHeaderKeys.addElement(aKey);
       
   845         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- addHeader(String,
       
   846         // String)" );
       
   847         return;
       
   848     }
       
   849 
       
   850     protected synchronized void inputStreamClosed() throws IOException
       
   851     {
       
   852         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "++++++ inputStreamClosed()");
       
   853         synchronized (iNativeDataReadyForRead.getLock())
       
   854         {
       
   855             iInputStream = null;
       
   856             iNativeHttpInputStream = null;
       
   857             if (iClosed && (iOutputStream == null))
       
   858             {
       
   859                 closeConnection();
       
   860             }
       
   861         }
       
   862         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
   863                    "-------- inputStreamClosed()");
       
   864     }
       
   865 
       
   866 
       
   867     protected synchronized void outputStreamFlushed() throws IOException
       
   868     {
       
   869         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ outputStreamFlushed()" );
       
   870         switch (iState)
       
   871         {
       
   872         case SETUP:
       
   873         case CONNECTED:
       
   874         case REQUEST_HEADERS_SENT:
       
   875             ensureResponse();
       
   876 
       
   877         default:
       
   878             // No-op
       
   879             ;
       
   880         }
       
   881         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- outputStreamFlushed()" );
       
   882     }
       
   883 
       
   884     protected synchronized void outputStreamClosed() throws IOException
       
   885     {
       
   886         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
   887                    "++++++++ outputStreamClosed()");
       
   888         iOutputStream = null;
       
   889         iPostedDataStream = null;
       
   890         if (iClosed && iInputStream == null)
       
   891         {
       
   892             closeConnection();
       
   893         }
       
   894         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
   895                    "-------- outputStreamClosed()");
       
   896     }
       
   897 
       
   898     private synchronized void connect() throws IOException
       
   899     {
       
   900         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+++++++ Java connect()");
       
   901         if (iNativeTransactionHande <= 0)
       
   902         {
       
   903             final int handle = _createNativeTransaction(
       
   904                                    iNativeHttpSessionHandle, iUri.toString(), iRequestMethod);
       
   905             iNativeTransactionHande = NativeError.check(handle);
       
   906         }
       
   907         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "-------- connect()");
       
   908     }
       
   909 
       
   910     protected void ensureConnected() throws IOException
       
   911     {
       
   912         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ ensureConnected()" );
       
   913         switch (iState)
       
   914         {
       
   915         case SETUP:
       
   916 
       
   917             connect();
       
   918             iState = CONNECTED;
       
   919             break;
       
   920 
       
   921         default:
       
   922             ;
       
   923         }
       
   924         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- ensureConnected()" );
       
   925         return;
       
   926     }
       
   927 
       
   928     protected void ensureOpen(String aMethodName) throws IOException
       
   929     {
       
   930         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ ensureOpen()" );
       
   931         if (iClosed)
       
   932         {
       
   933             throwIOException(aMethodName
       
   934                              + " method failed.Connection state is already closed");
       
   935         }
       
   936         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- ensureOpen()" );
       
   937         return;
       
   938     }
       
   939 
       
   940     protected void ensureResponse() throws IOException
       
   941     {
       
   942         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ ensureResponse()" );
       
   943         ensureConnected();
       
   944         switch (iState)
       
   945         {
       
   946         case CONNECTED:
       
   947 
       
   948             sendRequest();
       
   949             // Fall Through
       
   950         case REQUEST_HEADERS_SENT:
       
   951         case REQUEST_SENT:
       
   952             getResponse();
       
   953             iState = REPLY_RECEIVED;
       
   954             break;
       
   955 
       
   956         default:
       
   957             // No-op
       
   958             ;
       
   959         }
       
   960         //Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- ensureResponse()" );
       
   961         return;
       
   962     }
       
   963 
       
   964     protected synchronized void getResponse() throws IOException
       
   965     {
       
   966         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ getResponse()");
       
   967 
       
   968         boolean flag = true;
       
   969         String[] rawHeaders = _getResponse(iNativeTransactionHande);
       
   970         if (rawHeaders == null || rawHeaders.length == 0)
       
   971             throwIOException("Invalid http response");
       
   972 
       
   973         // First element is the Status Line
       
   974         readStatusLine(rawHeaders[0]);
       
   975         readHeaders(rawHeaders);
       
   976         processReplyHeaders();
       
   977         rawHeaders = null;
       
   978         //Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- getResponse()" );
       
   979         return;
       
   980     }
       
   981 
       
   982     protected void readStatusLine(String aStatusLine) throws IOException
       
   983     {
       
   984         // Status-Line = HTTP-Version ;; Status-Code ;; Reason-Phrase
       
   985         Logger.PLOG(Logger.ESOCKET, "HTTP response, status line: "
       
   986                     + aStatusLine);
       
   987         // HTTP-Version
       
   988         final int fisrtSepIndex = aStatusLine.indexOf(NATIVESEPERATOR);
       
   989         if (fisrtSepIndex <= 0)
       
   990         {
       
   991             throwIOException("Invalid http response");
       
   992         }
       
   993         String parse = aStatusLine.substring(0, fisrtSepIndex);
       
   994 
       
   995         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, " Server Vesion : " + parse
       
   996         // );
       
   997 
       
   998         // Check the server we are connecting to is a http v1.0 or v1.1
       
   999         if (parse.compareTo(VERSION_1_1) != 0
       
  1000                 && parse.compareTo(VERSION_1_0) != 0)
       
  1001         {
       
  1002             throwIOException("Invalid http response.Http-version mismatch");
       
  1003         }
       
  1004 
       
  1005         // Status Code
       
  1006         int nextSepIndex = 0;
       
  1007         nextSepIndex = aStatusLine.indexOf(NATIVESEPERATOR, fisrtSepIndex + 2);
       
  1008         if (nextSepIndex <= 0)
       
  1009         {
       
  1010             throwIOException("Invalid http response");
       
  1011         }
       
  1012         parse = null;
       
  1013         parse = aStatusLine.substring(fisrtSepIndex + 2, nextSepIndex);
       
  1014         iResponseCode = Integer.parseInt(parse);
       
  1015 
       
  1016         // Reason-Phrase
       
  1017 
       
  1018         iResponseMessage = aStatusLine.substring(nextSepIndex + 2, aStatusLine
       
  1019                            .length());
       
  1020         if (iResponseMessage.length() <= 0)
       
  1021         {
       
  1022             throwIOException("Invalid http response");
       
  1023         }
       
  1024         //Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- readStatusLine(InputStream)" );
       
  1025     }
       
  1026 
       
  1027     protected long parseDate(String aDateString)
       
  1028     {
       
  1029         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ parseDate(String)" );
       
  1030         final long result = DateUtil.epocDifference(aDateString);
       
  1031         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- parseDate(String)" );
       
  1032         return result;
       
  1033     }
       
  1034 
       
  1035     protected void processReplyHeaders()
       
  1036     {
       
  1037         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ processReplyHeaders()" );
       
  1038         String value;
       
  1039         value = (String) iReplyHeaders.get(CONTENT_LENGTH.toLowerCase());
       
  1040         if (value != null)
       
  1041         {
       
  1042             iLength = Long.parseLong(value);
       
  1043         }
       
  1044         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- processReplyHeaders()" );
       
  1045     }
       
  1046 
       
  1047     protected void readHeaders(String[] aHeaders) throws IOException
       
  1048     {
       
  1049         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ readHeaders()" );
       
  1050         // Headers are of the form
       
  1051         // valueKey + NATIVESEPERATOR + property
       
  1052         String key;
       
  1053         String value;
       
  1054         String rawHeader = null;
       
  1055         final int headersCount = aHeaders.length;
       
  1056 
       
  1057         // First element is status line which we ignore (parsed in
       
  1058         // readStatusLine)
       
  1059         int sepIndex = -1;
       
  1060         for (int ii = 1; ii < headersCount; ++ii)
       
  1061         {
       
  1062             rawHeader = aHeaders[ii];
       
  1063             sepIndex = rawHeader.indexOf(NATIVESEPERATOR);
       
  1064             key = rawHeader.substring(0, sepIndex);
       
  1065             value = rawHeader.substring(sepIndex + 2, rawHeader.length());
       
  1066             addHeader(key, value);
       
  1067             rawHeader = null;
       
  1068             key = null;
       
  1069             value = null;
       
  1070             sepIndex = -1;
       
  1071         }
       
  1072         //Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- readHeaders(InputStream)" );
       
  1073     }
       
  1074 
       
  1075     protected synchronized void sendRequest() throws IOException
       
  1076     {
       
  1077         ensureConnected();
       
  1078         final int count = iRequestProperties.size();
       
  1079         int headerCount = count;
       
  1080 
       
  1081         final Enumeration keyEnum = iRequestProperties.keys();
       
  1082         String[] headers = null;
       
  1083         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- headerCount: " +
       
  1084         // headerCount );
       
  1085         if (headerCount > 0)
       
  1086             headers = new String[headerCount];
       
  1087 
       
  1088         String valueKey = null;
       
  1089         String property = null;
       
  1090         String concat = null;
       
  1091         boolean untrustedAdded = false;
       
  1092         for (int ii = 0; ii < count; ++ii)
       
  1093         {
       
  1094             valueKey = (String) keyEnum.nextElement();
       
  1095             property = getRequestProperty(valueKey);
       
  1096             concat = valueKey + NATIVESEPERATOR + property;
       
  1097             headers[ii] = concat;
       
  1098             // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "submit : " + ii + " : "
       
  1099             // + concat + "concat length:" + concat.length() );
       
  1100         }
       
  1101 
       
  1102         byte[] postData = null;
       
  1103         int postDataLength = 0;
       
  1104         // Data to be sent native
       
  1105         if (iPostedDataStream != null)
       
  1106         {
       
  1107             postData = iPostedDataStream.toByteArray();
       
  1108             postDataLength = postData.length;
       
  1109         }
       
  1110 
       
  1111         synchronized (iTransactionBlock.getLock())
       
  1112         {
       
  1113             // Submit the headers and the data at the same time
       
  1114             // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ _submitTransaction
       
  1115             // headers count : " + (headers!=null ?headers.length:-1 ) );
       
  1116             synchronized (iTransactionBlock)
       
  1117             {
       
  1118                 Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
  1119                            "before _submitTransaction ");
       
  1120                 final int err = _submitTransaction(iNativeTransactionHande,
       
  1121                                                    headers, postData, postDataLength,iRespTimeOut);
       
  1122 
       
  1123                 Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
  1124                            "-_submitTransaction +err " + err);
       
  1125 
       
  1126                 // Clear tempory byte array and headers array
       
  1127                 postData = null;
       
  1128                 headers = null;
       
  1129                 if (err != 0)
       
  1130                     throwIOException("Unable to connect to server.Symbian os error code: "
       
  1131                                      + err);
       
  1132                 iState = REQUEST_SENT;
       
  1133                 waitForTransaction();
       
  1134                 Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
  1135                            "- sendRequest _submitTransaction");
       
  1136             }
       
  1137         }
       
  1138         if ((iTransactionBlock.getResult() == -18) &&(iRetries < 2))
       
  1139         {
       
  1140             iRetries++;
       
  1141             Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
  1142                        "- sendRequest KErrNotReady erroi, calling recursive sendRequest()");
       
  1143             sendRequest();
       
  1144             Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
  1145                        "- sendRequest KErrNotReady erroi, calling recursive sendRequest() returned");
       
  1146         }
       
  1147     }
       
  1148 
       
  1149     protected void throwIOException(String aMessage) throws IOException
       
  1150     {
       
  1151         throw new IOException(aMessage);
       
  1152     }
       
  1153 
       
  1154     protected void waitForTransaction() throws IOException
       
  1155     {
       
  1156         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+waitForTransaction");
       
  1157 
       
  1158         iTransactionBlock.waitForCompletion();
       
  1159         final int result = iTransactionBlock.getResult();
       
  1160         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "waitForTransaction result :"
       
  1161                    + result);
       
  1162         if ((result < 0))
       
  1163         {
       
  1164             final Integer error = new Integer(result);
       
  1165             if ((result == -18))
       
  1166             {
       
  1167                 if (iRetries >=2)
       
  1168                 {
       
  1169                     throwIOException(error.toString());
       
  1170                 }
       
  1171             }
       
  1172             else
       
  1173             {
       
  1174                 throwIOException(error.toString());
       
  1175             }
       
  1176 
       
  1177         }
       
  1178 
       
  1179         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "-waitForTransaction");
       
  1180     }
       
  1181 
       
  1182     protected DataInputStream makeDataInputStream() throws IOException
       
  1183     {
       
  1184         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
  1185                    ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> makeDataInputStream()<<<<<<<<<<<<<<<<<<<<<<<");
       
  1186         DataInputStream result = null;
       
  1187         final String transferEncoding;
       
  1188 
       
  1189         final int bytesTotal = (int) getLength();
       
  1190         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
  1191                    "++++++ makeDataInputStream()  getLength():" + bytesTotal);
       
  1192 
       
  1193         if (iNativeHttpInputStream == null)
       
  1194             iNativeHttpInputStream = new NativeHttpInputStream(this);
       
  1195         result = new PlainDataInputStream(iNativeHttpInputStream);
       
  1196         Logger.LOG(Logger.ESOCKET, Logger.EInfo, " makeDataInputStream()");
       
  1197         return result;
       
  1198     }
       
  1199 
       
  1200     protected void makeDataOutputStream() throws IOException
       
  1201     {
       
  1202         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ makeDataOutputStream()"
       
  1203         // );
       
  1204         iPostedDataStream = new ByteArrayOutputStream();
       
  1205         iOutputStream = new PlainDataOutputStream(iPostedDataStream);
       
  1206         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- makeDataOutputStream()"
       
  1207         // );
       
  1208     }
       
  1209 
       
  1210     /**
       
  1211      * From NativeHttpByteSoure
       
  1212      */
       
  1213     public void closeByteSource()
       
  1214     {
       
  1215     }
       
  1216 
       
  1217     /*
       
  1218      * Returns the total number of bytes read into the buffer, or -1 if there is
       
  1219      * no more data because the end of the stream has been reached.
       
  1220      */
       
  1221     public synchronized int getBytes(byte[] aBytes, int aLength)
       
  1222     throws IOException
       
  1223     {
       
  1224         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+getBytes()");
       
  1225         int result = -1;
       
  1226 
       
  1227         // Prevents multiple read
       
  1228         synchronized (iNativeDataReadyForRead.getLock())
       
  1229         {
       
  1230             synchronized (iNativeDataReadyForRead)
       
  1231             {
       
  1232                 if (iNativeDataReadyForRead.getResult() == BlockingOperation.BLOCKED)
       
  1233                 {
       
  1234                     Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
  1235                                "+ getBytes()- ReadOperation.waitForCompletion()");
       
  1236                     iNativeDataReadyForRead.waitForCompletion();
       
  1237                     Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
  1238                                "- getBytes()- ReadOperation.waitForCompletion()");
       
  1239                 }
       
  1240             }
       
  1241 
       
  1242             final int callBackResult = iNativeDataReadyForRead.getResult();
       
  1243             if (callBackResult == EOF)
       
  1244                 return 0; // All data has been read
       
  1245             if (callBackResult < 0)
       
  1246                 throwIOException("Unable to read http response.Symbian os error code: "
       
  1247                                  + result);
       
  1248             // Block until data has been read from native
       
  1249             iNativeDataReadyForRead.setResult(BlockingOperation.BLOCKED);
       
  1250             if (iNativeHttpSessionHandle!=0)
       
  1251             {
       
  1252                 result = _getBytes(iNativeTransactionHande, aBytes, aLength);
       
  1253                 Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ 2 getBytes()- result "
       
  1254                            + result);
       
  1255             }
       
  1256         }
       
  1257         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "-getBytes() + result "
       
  1258                    + result);
       
  1259         return result;
       
  1260     }
       
  1261 
       
  1262     public int available() throws IOException
       
  1263     {
       
  1264         if ((iClosed == true) && (iInputStream == null)
       
  1265                 && (iOutputStream == null))
       
  1266         {
       
  1267             throw new IOException(
       
  1268                 "Available method failed.Connection is already closed");
       
  1269         }
       
  1270         return _available(iNativeTransactionHande);
       
  1271     }
       
  1272 
       
  1273     /*
       
  1274      * Native call back methods
       
  1275      */
       
  1276     protected void transactionSubmitCallback(int aStatus)
       
  1277     {
       
  1278         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
  1279                    "+ transactionSubmitCallback Callback");
       
  1280         iTransactionBlock.notifyCompleted(aStatus);
       
  1281         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
  1282                    "- transactionSubmitCallback Callback");
       
  1283     }
       
  1284 
       
  1285     protected void dataReadyForReadCallBack(int aStatus)
       
  1286     {
       
  1287         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ dataReadyForReadCallBack  "
       
  1288                    + aStatus);
       
  1289         iNativeDataReadyForRead.notifyCompleted(aStatus);
       
  1290         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- dataReadyForReadCallBack");
       
  1291     }
       
  1292 
       
  1293     /*
       
  1294      * Native Calls
       
  1295      */
       
  1296     private native int _createHttpSession(int a, int aType, int aApn,
       
  1297                                           int[] retval);
       
  1298     private native int _createNativeTransaction(int aNativeHttpSessionHandle,
       
  1299             String aUri, String aRequestMethod);
       
  1300     private native int _submitTransaction(int aNativeTransactionHande,
       
  1301                                           String[] aHeaders, byte[] aPostData, int aPostLength,
       
  1302                                           int aRespTimeOut);
       
  1303     private native String[] _getResponse(int aNativeTransactionHande);
       
  1304     private native int _getBytes(int aNativeTransactionHande, byte[] aBuffer,
       
  1305                                  int aLength);
       
  1306     private native void _closeTransaction(int aNativeTransactionHande);
       
  1307     private native int _available(int aNativeTransactionHande);
       
  1308     private native String _getUserAgentHeaderValue(boolean aMidpRuntime);
       
  1309 
       
  1310     /*
       
  1311      *
       
  1312      * class PlainDataInputStream
       
  1313      *
       
  1314      */
       
  1315     protected class PlainDataInputStream extends DataInputStream
       
  1316     {
       
  1317         public void close() throws IOException
       
  1318         {
       
  1319             super.close();
       
  1320             inputStreamClosed();
       
  1321         }
       
  1322 
       
  1323         PlainDataInputStream(InputStream aIs)
       
  1324         {
       
  1325             super(aIs);
       
  1326         }
       
  1327     }
       
  1328 
       
  1329     /*
       
  1330      *
       
  1331      * class PlainDataOutputStream
       
  1332      *
       
  1333      */
       
  1334     protected class PlainDataOutputStream extends DataOutputStream
       
  1335     {
       
  1336         private boolean iFlushed = false;
       
  1337 
       
  1338         public void close() throws IOException
       
  1339         {
       
  1340             if (!iFlushed)
       
  1341                 flush();
       
  1342             super.close();
       
  1343             outputStreamClosed();
       
  1344         }
       
  1345 
       
  1346         public void flush() throws IOException
       
  1347         {
       
  1348             super.flush();
       
  1349             outputStreamFlushed();
       
  1350             iFlushed = true;
       
  1351         }
       
  1352 
       
  1353         PlainDataOutputStream(OutputStream aOs)
       
  1354         {
       
  1355             super(aOs);
       
  1356         }
       
  1357     }
       
  1358 
       
  1359     class NativeHttpInputStream extends InputStream
       
  1360     {
       
  1361         private NativeHttpByteSource iByteSource;
       
  1362         private byte[] iBuffer;
       
  1363         private int iOffset;
       
  1364         private int iLength;
       
  1365         // 6K buffer to read from native http
       
  1366         private final static int BUFFER_SIZE = 6144;
       
  1367         private boolean iIsClosed;
       
  1368 
       
  1369         NativeHttpInputStream(NativeHttpByteSource aByteSource)
       
  1370         {
       
  1371             // Bytesource length may be -1 indicating CHUNKED (size unknown)
       
  1372             iByteSource = aByteSource;
       
  1373             iBuffer = new byte[BUFFER_SIZE];
       
  1374             iIsClosed = false;
       
  1375         }
       
  1376 
       
  1377         public synchronized void close() throws IOException
       
  1378         {
       
  1379             iIsClosed = true;
       
  1380             iByteSource.closeByteSource();
       
  1381         }
       
  1382 
       
  1383         public synchronized int read() throws IOException
       
  1384         {
       
  1385             final int BYTEPADDER = 0xFF;
       
  1386             // Logger.LOG(Logger.ESOCKET, Logger.EInfo,"NativeInputStream.read()
       
  1387             // iOffset, "+ iOffset + "iLength " + iLength);
       
  1388             throwIfClosed();
       
  1389 
       
  1390             if (iOffset == iLength)
       
  1391             {
       
  1392                 // Logger.LOG(Logger.ESOCKET,
       
  1393                 // Logger.EInfo,"NativeInputStream.read() iOffset == iLength
       
  1394                 // getBytes: iLength " + iLength );
       
  1395                 getBytes();
       
  1396             }
       
  1397 
       
  1398             // Logger.LOG(Logger.ESOCKET, Logger.EInfo,"NativeInputStream.read()
       
  1399             // 2 iOffset, "+ iOffset + " iLength " + iLength);
       
  1400             if (iLength > 0)
       
  1401             {
       
  1402                 return iBuffer[iOffset++] & BYTEPADDER;
       
  1403             }
       
  1404             else
       
  1405             {
       
  1406                 Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
  1407                            "NativeInputStream.read(): return -1 ");
       
  1408                 return EOF;
       
  1409             }
       
  1410         }
       
  1411 
       
  1412         public synchronized int read(byte[] aBytes, int aOffset, int aLength)
       
  1413         throws IOException
       
  1414         {
       
  1415             // Logger.LOG(Logger.ESOCKET,
       
  1416             // Logger.EInfo,"+NativeInputStream.read(,,,) aOffset, "+ aOffset +
       
  1417             // "aLength" + aLength);
       
  1418 
       
  1419             throwIfClosed();
       
  1420 
       
  1421             int nBytes = 0;
       
  1422             while (nBytes < aLength)
       
  1423             {
       
  1424                 // Logger.LOG(Logger.ESOCKET,
       
  1425                 // Logger.EInfo,"NativeInputStream.read(,,,) nBytes, "+ nBytes);
       
  1426                 int count = readInner(aBytes, aOffset + nBytes, aLength
       
  1427                                       - nBytes);
       
  1428                 // Logger.LOG(Logger.ESOCKET,
       
  1429                 // Logger.EInfo,"NativeInputStream.read(,,,) count = readInner,
       
  1430                 // "+ count);
       
  1431                 if (count < 0)
       
  1432                 {
       
  1433                     nBytes = (nBytes == 0) ? -1 : nBytes;
       
  1434                     break;
       
  1435                 }
       
  1436                 nBytes += count;
       
  1437             }
       
  1438             Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
  1439                        "- NativeInputStream.read(,,,) return nBytes, " + nBytes);
       
  1440             return nBytes;
       
  1441         }
       
  1442 
       
  1443         private int readInner(byte[] aBytes, int aOffset, int aLength)
       
  1444         throws IOException
       
  1445         {
       
  1446             // Logger.LOG(Logger.ESOCKET,
       
  1447             // Logger.EInfo,"NativeInputStream.readInner() iOffset: "+ iOffset +
       
  1448             // "iLength: " + iLength);
       
  1449             if (iOffset == iLength)
       
  1450             {
       
  1451                 getBytes();
       
  1452             }
       
  1453             if (iLength == 0)
       
  1454             {
       
  1455                 return EOF;
       
  1456             }
       
  1457 
       
  1458             int nBytesLeft = iLength - iOffset;
       
  1459             // Logger.LOG(Logger.ESOCKET,
       
  1460             // Logger.EInfo,"NativeInputStream.readInner() : nBytesLeft "+
       
  1461             // nBytesLeft);
       
  1462             int nBytesToCopy = aLength > nBytesLeft ? nBytesLeft : aLength;
       
  1463             System.arraycopy(iBuffer, iOffset, aBytes, aOffset, nBytesToCopy);
       
  1464             iOffset += nBytesToCopy;
       
  1465             return nBytesToCopy;
       
  1466         }
       
  1467 
       
  1468         private void getBytes() throws IOException
       
  1469         {
       
  1470             int nBytes = iByteSource.getBytes(iBuffer, iBuffer.length);
       
  1471 
       
  1472             if (nBytes == -1)
       
  1473             {
       
  1474                 throw new IOException();
       
  1475             }
       
  1476             iLength = nBytes;
       
  1477             iOffset = 0;
       
  1478         }
       
  1479 
       
  1480 
       
  1481         /**
       
  1482          * Returns the number of bytes that can be read (or skipped over) from
       
  1483          * this input stream without blocking by the next caller of a method for
       
  1484          * this input stream. The next caller might be the same thread or
       
  1485          * another thread.
       
  1486          *
       
  1487          * @return the number of bytes that can be read from this input stream
       
  1488          *         without blocking.
       
  1489          * @exception IOException
       
  1490          *                if an I/O error occurs.
       
  1491          */
       
  1492         public int available() throws IOException
       
  1493         {
       
  1494             throwIfClosed();
       
  1495             return iByteSource.available();
       
  1496         }
       
  1497 
       
  1498         private void throwIfClosed() throws IOException
       
  1499         {
       
  1500             if (iIsClosed)
       
  1501             {
       
  1502                 throw new IOException("Connection is already closed");
       
  1503             }
       
  1504         }
       
  1505     }
       
  1506 }