Back to index

lightning-sunbird  0.9+nobinonly
TestStreamConv.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsIServiceManager.h"
00039 #include "nsIComponentManager.h"
00040 #include "nsIComponentRegistrar.h"
00041 #include "nsIStreamConverterService.h"
00042 #include "nsIStreamConverter.h"
00043 #include "nsICategoryManager.h"
00044 #include "nsIFactory.h"
00045 #include "nsIStringStream.h"
00046 #include "nsCOMPtr.h"
00047 #include "nsNetUtil.h"
00048 
00049 #include "nspr.h"
00050 
00051 #define ASYNC_TEST // undefine this if you want to test sycnronous conversion.
00052 
00054 // Event pump setup
00056 #include "nsIEventQueueService.h"
00057 #ifdef XP_WIN
00058 #include <windows.h>
00059 #endif
00060 #ifdef XP_OS2
00061 #include <os2.h>
00062 #endif
00063 
00064 static int gKeepRunning = 0;
00065 static nsIEventQueue* gEventQ = nsnull;
00067 // Event pump END
00069 
00070 
00072 // Test converters include
00074 #include "Converters.h"
00075 
00076 // CID setup
00077 static NS_DEFINE_CID(kEventQueueServiceCID,      NS_EVENTQUEUESERVICE_CID);
00078 static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
00079 
00081 // EndListener - This listener is the final one in the chain. It
00082 //   receives the fully converted data, although it doesn't do anything with
00083 //   the data.
00085 class EndListener : public nsIStreamListener {
00086 public:
00087     // nsISupports declaration
00088     NS_DECL_ISUPPORTS
00089 
00090     EndListener() {};
00091 
00092     // nsIStreamListener method
00093     NS_IMETHOD OnDataAvailable(nsIRequest* request, nsISupports *ctxt, nsIInputStream *inStr, 
00094                                PRUint32 sourceOffset, PRUint32 count)
00095     {
00096         nsresult rv;
00097         PRUint32 read, len;
00098         rv = inStr->Available(&len);
00099         if (NS_FAILED(rv)) return rv;
00100 
00101         char *buffer = (char*)nsMemory::Alloc(len + 1);
00102         if (!buffer) return NS_ERROR_OUT_OF_MEMORY;
00103 
00104         rv = inStr->Read(buffer, len, &read);
00105         buffer[len] = '\0';
00106         if (NS_SUCCEEDED(rv)) {
00107             printf("CONTEXT %p: Received %u bytes and the following data: \n %s\n\n", ctxt, read, buffer);
00108         }
00109         nsMemory::Free(buffer);
00110 
00111         return NS_OK;
00112     }
00113 
00114     // nsIRequestObserver methods
00115     NS_IMETHOD OnStartRequest(nsIRequest* request, nsISupports *ctxt) { return NS_OK; }
00116 
00117     NS_IMETHOD OnStopRequest(nsIRequest* request, nsISupports *ctxt, 
00118                              nsresult aStatus) { return NS_OK; }
00119 };
00120 
00121 NS_IMPL_ISUPPORTS1(EndListener, nsIStreamListener)
00123 // EndListener END
00125 
00126 
00127 nsresult SendData(const char * aData, nsIStreamListener* aListener, nsIRequest* request) {
00128     nsCOMPtr<nsIInputStream> dataStream;
00129     nsresult rv = NS_NewCharInputStream(getter_AddRefs(dataStream), aData);
00130     if (NS_FAILED(rv)) return rv;
00131 
00132     PRUint32 avail;
00133     dataStream->Available(&avail);
00134 
00135     return aListener->OnDataAvailable(request, nsnull, dataStream, 0, avail);
00136 }
00137 #define SEND_DATA(x) SendData(x, converterListener, request)
00138 
00139 int
00140 main(int argc, char* argv[])
00141 {
00142     nsresult rv;
00143     {
00144         nsCOMPtr<nsIServiceManager> servMan;
00145         NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
00146         nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
00147         NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
00148         if (registrar)
00149             registrar->AutoRegister(nsnull);
00150     
00151         // Create the Event Queue for this thread...
00152         nsCOMPtr<nsIEventQueueService> eventQService =
00153                  do_GetService(kEventQueueServiceCID, &rv);
00154         if (NS_FAILED(rv)) return rv;
00155 
00156         eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ);
00157 
00158         nsCOMPtr<nsICategoryManager> catman =
00159             do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
00160         if (NS_FAILED(rv)) return rv;
00161         nsXPIDLCString previous;
00162 
00164         // BEGIN - Stream converter registration
00165         //   All stream converters must register with the ComponentManager
00167 
00168         // these stream converters are just for testing. running this harness
00169         // from the dist/bin dir will also pickup converters registered
00170         // in other modules (necko converters for example).
00171 
00172         PRUint32 converterListSize = 7;
00173         const char *const converterList[] = {
00174             "?from=a/foo&to=b/foo",
00175             "?from=b/foo&to=c/foo",
00176             "?from=b/foo&to=d/foo",
00177             "?from=c/foo&to=d/foo",
00178             "?from=d/foo&to=e/foo",
00179             "?from=d/foo&to=f/foo",
00180             "?from=t/foo&to=k/foo",
00181         };
00182 
00183         TestConverterFactory *convFactory = new TestConverterFactory(kTestConverterCID, "TestConverter", NS_ISTREAMCONVERTER_KEY);
00184         nsCOMPtr<nsIFactory> convFactSup(do_QueryInterface(convFactory, &rv));
00185         if (NS_FAILED(rv)) return rv;
00186 
00187         for (PRUint32 count = 0; count < converterListSize; ++count) {
00188             // register the TestConverter with the component manager. One contractid registration
00189             // per conversion pair (from - to pair).
00190             nsCString contractID(NS_ISTREAMCONVERTER_KEY);
00191             contractID.Append(converterList[count]);
00192             rv = registrar->RegisterFactory(kTestConverterCID,
00193                                             "TestConverter",
00194                                             contractID.get(),
00195                                             convFactSup);
00196             if (NS_FAILED(rv)) return rv;
00197             rv = catman->AddCategoryEntry(NS_ISTREAMCONVERTER_KEY, converterList[count], "x",
00198                                             PR_TRUE, PR_TRUE, getter_Copies(previous));
00199             if (NS_FAILED(rv)) return rv;
00200         }
00201 
00202         nsCOMPtr<nsIStreamConverterService> StreamConvService =
00203                  do_GetService(kStreamConverterServiceCID, &rv);
00204         if (NS_FAILED(rv)) return rv;
00205 
00206         // Define the *from* content type and *to* content-type for conversion.
00207         static const char fromStr[] = "a/foo";
00208         static const char toStr[] = "c/foo";
00209     
00210 #ifdef ASYNC_TEST
00211         // ASYNCHRONOUS conversion
00212 
00213         // Build up a channel that represents the content we're
00214         // starting the transaction with.
00215         //
00216         // sample multipart mixed content-type string:
00217         // "multipart/x-mixed-replacE;boundary=thisrandomstring"
00218 #if 0
00219         nsCOMPtr<nsIChannel> channel;
00220         nsCOMPtr<nsIURI> dummyURI;
00221         rv = NS_NewURI(getter_AddRefs(dummyURI), "http://meaningless");
00222         if (NS_FAILED(rv)) return rv;
00223 
00224         rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
00225                                       dummyURI,
00226                                       nsnull,   // inStr
00227                                       "text/plain", // content-type
00228                                       -1);      // XXX fix contentLength
00229         if (NS_FAILED(rv)) return rv;
00230 
00231         nsCOMPtr<nsIRequest> request(do_QueryInterface(channel));
00232 #endif
00233 
00234         nsCOMPtr<nsIRequest> request;
00235 
00236         // setup a listener to receive the converted data. This guy is the end
00237         // listener in the chain, he wants the fully converted (toType) data.
00238         // An example of this listener in mozilla would be the DocLoader.
00239         nsIStreamListener *dataReceiver = new EndListener();
00240         NS_ADDREF(dataReceiver);
00241 
00242         // setup a listener to push the data into. This listener sits inbetween the
00243         // unconverted data of fromType, and the final listener in the chain (in this case
00244         // the dataReceiver.
00245         nsIStreamListener *converterListener = nsnull;
00246         rv = StreamConvService->AsyncConvertData(fromStr, toStr,
00247                                                  dataReceiver, nsnull, &converterListener);
00248         if (NS_FAILED(rv)) return rv;
00249         NS_RELEASE(dataReceiver);
00250 
00251         // at this point we have a stream listener to push data to, and the one
00252         // that will receive the converted data. Let's mimic On*() calls and get the conversion
00253         // going. Typically these On*() calls would be made inside their respective wrappers On*()
00254         // methods.
00255         rv = converterListener->OnStartRequest(request, nsnull);
00256         if (NS_FAILED(rv)) return rv;
00257 
00258         rv = SEND_DATA("aaa");
00259         if (NS_FAILED(rv)) return rv;
00260 
00261         rv = SEND_DATA("aaa");
00262         if (NS_FAILED(rv)) return rv;
00263 
00264         // Finish the request.
00265         rv = converterListener->OnStopRequest(request, nsnull, rv);
00266         if (NS_FAILED(rv)) return rv;
00267 
00268         NS_RELEASE(converterListener);
00269 #else
00270         // SYNCHRONOUS conversion
00271         nsCOMPtr<nsIInputStream> convertedData;
00272         rv = StreamConvService->Convert(inputData, fromStr, toStr,
00273                                         nsnull, getter_AddRefs(convertedData));
00274         if (NS_FAILED(rv)) return rv;
00275 #endif
00276 
00277         // Enter the message pump to allow the URL load to proceed.
00278         while ( gKeepRunning ) {
00279             PLEvent *gEvent;
00280             gEventQ->WaitForEvent(&gEvent);
00281             gEventQ->HandleEvent(gEvent);
00282             /* gKeepRunning = PR_FALSE; */
00283         }
00284     } // this scopes the nsCOMPtrs
00285     // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
00286     NS_ShutdownXPCOM(nsnull);
00287     return rv;
00288 }