LCOV - app.info - rdf/base/src/nsRDFXMLDataSource.cpp

LCOV - code coverage report
| Current view: | directory - rdf/base/src - nsRDFXMLDataSource.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 398 | 305 | 76.6 %
| Date: | 2012-04-21 | Functions: | 65 | 50 | 76.9 %

           1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is mozilla.org code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Netscape Communications Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
          24                 :  *
          25                 :  * Alternatively, the contents of this file may be used under the terms of
          26                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          27                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          29                 :  * of those above. If you wish to allow use of your version of this file only
          30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          31                 :  * use your version of this file under the terms of the MPL, indicate your
          32                 :  * decision by deleting the provisions above and replace them with the notice
          33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          34                 :  * the provisions above, a recipient may use your version of this file under
          35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          36                 :  *
          37                 :  * ***** END LICENSE BLOCK ***** */
          38                 :
          39                 : /*
          40                 :
          41                 :   A data source that can read itself from and write itself to an
          42                 :   RDF/XML stream.
          43                 :
          44                 :   For more information on the RDF/XML syntax,
          45                 :   see http://www.w3.org/TR/REC-rdf-syntax/.
          46                 :
          47                 :   This code is based on the final W3C Recommendation,
          48                 :   http://www.w3.org/TR/1999/REC-rdf-syntax-19990222.
          49                 :
          50                 :
          51                 :   TO DO
          52                 :   -----
          53                 :
          54                 :   1) Right now, the only kind of stream data sources that are _really_
          55                 :      writable are "file:" URIs. (In fact, _all_ "file:" URIs are
          56                 :      writable, modulo file system permissions; this may lead to some
          57                 :      surprising behavior.) Eventually, it'd be great if we could open
          58                 :      an arbitrary nsIOutputStream on *any* URL, and Netlib could just
          59                 :      do the magic.
          60                 :
          61                 :   2) Implement a more terse output for "typed" nodes; that is, instead
          62                 :      of "RDF:Description type='ns:foo'", just output "ns:foo".
          63                 :
          64                 :   3) When re-serializing, we "cheat" for Descriptions that talk about
          65                 :      inline resources (i.e.., using the `ID' attribute specified in
          66                 :      [6.21]). Instead of writing an `ID="foo"' for the first instance,
          67                 :      and then `about="#foo"' for each subsequent instance, we just
          68                 :      _always_ write `about="#foo"'.
          69                 :
          70                 :      We do this so that we can handle the case where an RDF container
          71                 :      has been assigned arbitrary properties: the spec says we can't
          72                 :      dangle the attributes directly off the container, so we need to
          73                 :      refer to it. Of course, with a little cleverness, we could fix
          74                 :      this. But who cares?
          75                 :
          76                 :   4) When re-serializing containers. We have to cheat on some
          77                 :      containers, and use an illegal "about=" construct. We do this to
          78                 :      handle containers that have been assigned URIs outside of the
          79                 :      local document.
          80                 :
          81                 :
          82                 :   Logging
          83                 :   -------
          84                 :
          85                 :   To turn on logging for this module, set
          86                 :
          87                 :     NSPR_LOG_MODULES=nsRDFXMLDataSource:5
          88                 :
          89                 :  */
          90                 :
          91                 : #include "nsIFileStreams.h"
          92                 : #include "nsIOutputStream.h"
          93                 : #include "nsIFile.h"
          94                 : #include "nsIFileChannel.h"
          95                 : #include "nsIDTD.h"
          96                 : #include "nsIRDFPurgeableDataSource.h"
          97                 : #include "nsIInputStream.h"
          98                 : #include "nsIOutputStream.h"
          99                 : #include "nsIRDFContainerUtils.h"
         100                 : #include "nsIRDFNode.h"
         101                 : #include "nsIRDFRemoteDataSource.h"
         102                 : #include "nsIRDFService.h"
         103                 : #include "nsIRDFXMLParser.h"
         104                 : #include "nsIRDFXMLSerializer.h"
         105                 : #include "nsIRDFXMLSink.h"
         106                 : #include "nsIRDFXMLSource.h"
         107                 : #include "nsIServiceManager.h"
         108                 : #include "nsIStreamListener.h"
         109                 : #include "nsIURL.h"
         110                 : #include "nsIFileURL.h"
         111                 : #include "nsNetUtil.h"
         112                 : #include "nsIChannel.h"
         113                 : #include "nsRDFCID.h"
         114                 : #include "nsRDFBaseDataSources.h"
         115                 : #include "nsCOMArray.h"
         116                 : #include "nsXPIDLString.h"
         117                 : #include "plstr.h"
         118                 : #include "prio.h"
         119                 : #include "prthread.h"
         120                 : #include "rdf.h"
         121                 : #include "rdfutil.h"
         122                 : #include "prlog.h"
         123                 : #include "nsNameSpaceMap.h"
         124                 : #include "nsCRT.h"
         125                 : #include "nsCycleCollectionParticipant.h"
         126                 : #include "nsIScriptSecurityManager.h"
         127                 : #include "nsIChannelEventSink.h"
         128                 : #include "nsIAsyncVerifyRedirectCallback.h"
         129                 : #include "nsNetUtil.h"
         130                 :
         131                 : #include "rdfIDataSource.h"
         132                 :
         133                 : //----------------------------------------------------------------------
         134                 :
         135                 : static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
         136                 : static NS_DEFINE_CID(kRDFServiceCID,            NS_RDFSERVICE_CID);
         137                 :
         138                 : #ifdef PR_LOGGING
         139                 : static PRLogModuleInfo* gLog;
         140                 : #endif
         141                 :
         142                 : //----------------------------------------------------------------------
         143                 : //
         144                 : // RDFXMLDataSourceImpl
         145                 : //
         146                 :
         147                 : class RDFXMLDataSourceImpl : public nsIRDFDataSource,
         148                 :                              public nsIRDFRemoteDataSource,
         149                 :                              public nsIRDFXMLSink,
         150                 :                              public nsIRDFXMLSource,
         151                 :                              public nsIStreamListener,
         152                 :                              public rdfIDataSource,
         153                 :                              public nsIInterfaceRequestor,
         154                 :                              public nsIChannelEventSink
         155                 : {
         156                 : protected:
         157                 :     enum LoadState {
         158                 :         eLoadState_Unloaded,
         159                 :         eLoadState_Pending,
         160                 :         eLoadState_Loading,
         161                 :         eLoadState_Loaded
         162                 :     };
         163                 :
         164                 :     nsCOMPtr<nsIRDFDataSource> mInner;
         165                 :     bool                mIsWritable;    // true if the document can be written back
         166                 :     bool                mIsDirty;       // true if the document should be written back
         167                 :     LoadState           mLoadState;     // what we're doing now
         168                 :     nsCOMArray<nsIRDFXMLSinkObserver> mObservers;
         169                 :     nsCOMPtr<nsIURI>    mURL;
         170                 :     nsCOMPtr<nsIStreamListener> mListener;
         171                 :     nsNameSpaceMap      mNameSpaces;
         172                 :
         173                 :     // pseudo-constants
         174                 :     static PRInt32 gRefCnt;
         175                 :     static nsIRDFService* gRDFService;
         176                 :
         177                 :     nsresult Init();
         178                 :     RDFXMLDataSourceImpl(void);
         179                 :     virtual ~RDFXMLDataSourceImpl(void);
         180                 :     nsresult rdfXMLFlush(nsIURI *aURI);
         181                 :
         182                 :     friend nsresult
         183                 :     NS_NewRDFXMLDataSource(nsIRDFDataSource** aResult);
         184                 :
         185             758 :     inline bool IsLoading() {
         186                 :         return (mLoadState == eLoadState_Pending) ||
         187             758 :                (mLoadState == eLoadState_Loading);
         188                 :     }
         189                 :
         190                 : public:
         191                 :     // nsISupports
         192               2 :     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
         193            2700 :     NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(RDFXMLDataSourceImpl,
         194                 :                                              nsIRDFDataSource)
         195                 :
         196                 :     // nsIRDFDataSource
         197                 :     NS_IMETHOD GetURI(char* *uri);
         198                 :
         199               1 :     NS_IMETHOD GetSource(nsIRDFResource* property,
         200                 :                          nsIRDFNode* target,
         201                 :                          bool tv,
         202                 :                          nsIRDFResource** source) {
         203               1 :         return mInner->GetSource(property, target, tv, source);
         204                 :     }
         205                 :
         206               5 :     NS_IMETHOD GetSources(nsIRDFResource* property,
         207                 :                           nsIRDFNode* target,
         208                 :                           bool tv,
         209                 :                           nsISimpleEnumerator** sources) {
         210               5 :         return mInner->GetSources(property, target, tv, sources);
         211                 :     }
         212                 :
         213             767 :     NS_IMETHOD GetTarget(nsIRDFResource* source,
         214                 :                          nsIRDFResource* property,
         215                 :                          bool tv,
         216                 :                          nsIRDFNode** target) {
         217             767 :         return mInner->GetTarget(source, property, tv, target);
         218                 :     }
         219                 :
         220            1431 :     NS_IMETHOD GetTargets(nsIRDFResource* source,
         221                 :                           nsIRDFResource* property,
         222                 :                           bool tv,
         223                 :                           nsISimpleEnumerator** targets) {
         224            1431 :         return mInner->GetTargets(source, property, tv, targets);
         225                 :     }
         226                 :
         227                 :     NS_IMETHOD Assert(nsIRDFResource* aSource,
         228                 :                       nsIRDFResource* aProperty,
         229                 :                       nsIRDFNode* aTarget,
         230                 :                       bool tv);
         231                 :
         232                 :     NS_IMETHOD Unassert(nsIRDFResource* source,
         233                 :                         nsIRDFResource* property,
         234                 :                         nsIRDFNode* target);
         235                 :
         236                 :     NS_IMETHOD Change(nsIRDFResource* aSource,
         237                 :                       nsIRDFResource* aProperty,
         238                 :                       nsIRDFNode* aOldTarget,
         239                 :                       nsIRDFNode* aNewTarget);
         240                 :
         241                 :     NS_IMETHOD Move(nsIRDFResource* aOldSource,
         242                 :                     nsIRDFResource* aNewSource,
         243                 :                     nsIRDFResource* aProperty,
         244                 :                     nsIRDFNode* aTarget);
         245                 :
         246            1271 :     NS_IMETHOD HasAssertion(nsIRDFResource* source,
         247                 :                             nsIRDFResource* property,
         248                 :                             nsIRDFNode* target,
         249                 :                             bool tv,
         250                 :                             bool* hasAssertion) {
         251            1271 :         return mInner->HasAssertion(source, property, target, tv, hasAssertion);
         252                 :     }
         253                 :
         254               0 :     NS_IMETHOD AddObserver(nsIRDFObserver* aObserver) {
         255               0 :         return mInner->AddObserver(aObserver);
         256                 :     }
         257                 :
         258               0 :     NS_IMETHOD RemoveObserver(nsIRDFObserver* aObserver) {
         259               0 :         return mInner->RemoveObserver(aObserver);
         260                 :     }
         261                 :
         262               6 :     NS_IMETHOD HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *_retval) {
         263               6 :         return mInner->HasArcIn(aNode, aArc, _retval);
         264                 :     }
         265                 :
         266             431 :     NS_IMETHOD HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, bool *_retval) {
         267             431 :         return mInner->HasArcOut(aSource, aArc, _retval);
         268                 :     }
         269                 :
         270              19 :     NS_IMETHOD ArcLabelsIn(nsIRDFNode* node,
         271                 :                            nsISimpleEnumerator** labels) {
         272              19 :         return mInner->ArcLabelsIn(node, labels);
         273                 :     }
         274                 :
         275             573 :     NS_IMETHOD ArcLabelsOut(nsIRDFResource* source,
         276                 :                             nsISimpleEnumerator** labels) {
         277             573 :         return mInner->ArcLabelsOut(source, labels);
         278                 :     }
         279                 :
         280              19 :     NS_IMETHOD GetAllResources(nsISimpleEnumerator** aResult) {
         281              19 :         return mInner->GetAllResources(aResult);
         282                 :     }
         283                 :
         284               0 :     NS_IMETHOD GetAllCmds(nsIRDFResource* source,
         285                 :                               nsISimpleEnumerator/*<nsIRDFResource>*/** commands) {
         286               0 :         return mInner->GetAllCmds(source, commands);
         287                 :     }
         288                 :
         289               0 :     NS_IMETHOD IsCommandEnabled(nsISupportsArray/*<nsIRDFResource>*/* aSources,
         290                 :                                 nsIRDFResource*   aCommand,
         291                 :                                 nsISupportsArray/*<nsIRDFResource>*/* aArguments,
         292                 :                                 bool* aResult) {
         293               0 :         return mInner->IsCommandEnabled(aSources, aCommand, aArguments, aResult);
         294                 :     }
         295                 :
         296               0 :     NS_IMETHOD DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
         297                 :                          nsIRDFResource*   aCommand,
         298                 :                          nsISupportsArray/*<nsIRDFResource>*/* aArguments) {
         299                 :         // XXX Uh oh, this could cause problems wrt. the "dirty" flag
         300                 :         // if it changes the in-memory store's internal state.
         301               0 :         return mInner->DoCommand(aSources, aCommand, aArguments);
         302                 :     }
         303                 :
         304               0 :     NS_IMETHOD BeginUpdateBatch() {
         305               0 :         return mInner->BeginUpdateBatch();
         306                 :     }
         307                 :
         308               0 :     NS_IMETHOD EndUpdateBatch() {
         309               0 :         return mInner->EndUpdateBatch();
         310                 :     }
         311                 :
         312                 :     // nsIRDFRemoteDataSource interface
         313                 :     NS_DECL_NSIRDFREMOTEDATASOURCE
         314                 :
         315                 :     // nsIRDFXMLSink interface
         316                 :     NS_DECL_NSIRDFXMLSINK
         317                 :
         318                 :     // nsIRDFXMLSource interface
         319                 :     NS_DECL_NSIRDFXMLSOURCE
         320                 :
         321                 :     // nsIRequestObserver
         322                 :     NS_DECL_NSIREQUESTOBSERVER
         323                 :
         324                 :     // nsIStreamListener
         325                 :     NS_DECL_NSISTREAMLISTENER
         326                 :
         327                 :     // nsIInterfaceRequestor
         328                 :     NS_DECL_NSIINTERFACEREQUESTOR
         329                 :
         330                 :     // nsIChannelEventSink
         331                 :     NS_DECL_NSICHANNELEVENTSINK
         332                 :
         333                 :     // rdfIDataSource
         334               0 :     NS_IMETHOD VisitAllSubjects(rdfITripleVisitor *aVisitor) {
         335                 :         nsresult rv;
         336               0 :         nsCOMPtr<rdfIDataSource> rdfds = do_QueryInterface(mInner, &rv);
         337               0 :         if (NS_FAILED(rv)) return rv;
         338               0 :         return rdfds->VisitAllSubjects(aVisitor);
         339                 :     }
         340                 :
         341              19 :     NS_IMETHOD VisitAllTriples(rdfITripleVisitor *aVisitor) {
         342                 :         nsresult rv;
         343              38 :         nsCOMPtr<rdfIDataSource> rdfds = do_QueryInterface(mInner, &rv);
         344              19 :         if (NS_FAILED(rv)) return rv;
         345              19 :         return rdfds->VisitAllTriples(aVisitor);
         346                 :     }
         347                 :
         348                 :     // Implementation methods
         349                 :     bool
         350                 :     MakeQName(nsIRDFResource* aResource,
         351                 :               nsString& property,
         352                 :               nsString& nameSpacePrefix,
         353                 :               nsString& nameSpaceURI);
         354                 :
         355                 :     nsresult
         356                 :     SerializeAssertion(nsIOutputStream* aStream,
         357                 :                        nsIRDFResource* aResource,
         358                 :                        nsIRDFResource* aProperty,
         359                 :                        nsIRDFNode* aValue);
         360                 :
         361                 :     nsresult
         362                 :     SerializeProperty(nsIOutputStream* aStream,
         363                 :                       nsIRDFResource* aResource,
         364                 :                       nsIRDFResource* aProperty);
         365                 :
         366                 :     bool
         367                 :     IsContainerProperty(nsIRDFResource* aProperty);
         368                 :
         369                 :     nsresult
         370                 :     SerializeDescription(nsIOutputStream* aStream,
         371                 :                          nsIRDFResource* aResource);
         372                 :
         373                 :     nsresult
         374                 :     SerializeMember(nsIOutputStream* aStream,
         375                 :                     nsIRDFResource* aContainer,
         376                 :                     nsIRDFNode* aMember);
         377                 :
         378                 :     nsresult
         379                 :     SerializeContainer(nsIOutputStream* aStream,
         380                 :                        nsIRDFResource* aContainer);
         381                 :
         382                 :     nsresult
         383                 :     SerializePrologue(nsIOutputStream* aStream);
         384                 :
         385                 :     nsresult
         386                 :     SerializeEpilogue(nsIOutputStream* aStream);
         387                 :
         388                 :     bool
         389                 :     IsA(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType);
         390                 :
         391                 : protected:
         392                 :     nsresult
         393                 :     BlockingParse(nsIURI* aURL, nsIStreamListener* aConsumer);
         394                 : };
         395                 :
         396                 : PRInt32         RDFXMLDataSourceImpl::gRefCnt = 0;
         397                 : nsIRDFService*  RDFXMLDataSourceImpl::gRDFService;
         398                 :
         399                 : static const char kFileURIPrefix[] = "file:";
         400                 : static const char kResourceURIPrefix[] = "resource:";
         401                 :
         402                 :
         403                 : //----------------------------------------------------------------------
         404                 :
         405                 : nsresult
         406              10 : NS_NewRDFXMLDataSource(nsIRDFDataSource** aResult)
         407                 : {
         408              10 :     NS_PRECONDITION(aResult != nsnull, "null ptr");
         409              10 :     if (! aResult)
         410               0 :         return NS_ERROR_NULL_POINTER;
         411                 :
         412              10 :     RDFXMLDataSourceImpl* datasource = new RDFXMLDataSourceImpl();
         413              10 :     if (! datasource)
         414               0 :         return NS_ERROR_OUT_OF_MEMORY;
         415                 :
         416                 :     nsresult rv;
         417              10 :     rv = datasource->Init();
         418                 :
         419              10 :     if (NS_FAILED(rv)) {
         420               0 :         delete datasource;
         421               0 :         return rv;
         422                 :     }
         423                 :
         424              10 :     NS_ADDREF(datasource);
         425              10 :     *aResult = datasource;
         426              10 :     return NS_OK;
         427                 : }
         428                 :
         429                 :
         430              10 : RDFXMLDataSourceImpl::RDFXMLDataSourceImpl(void)
         431                 :     : mIsWritable(true),
         432                 :       mIsDirty(false),
         433              10 :       mLoadState(eLoadState_Unloaded)
         434                 : {
         435                 : #ifdef PR_LOGGING
         436              10 :     if (! gLog)
         437               7 :         gLog = PR_NewLogModule("nsRDFXMLDataSource");
         438                 : #endif
         439              10 : }
         440                 :
         441                 :
         442                 : nsresult
         443              10 : RDFXMLDataSourceImpl::Init()
         444                 : {
         445                 :     nsresult rv;
         446              10 :     mInner = do_CreateInstance(kRDFInMemoryDataSourceCID, &rv);
         447              10 :     if (NS_FAILED(rv)) return rv;
         448                 :
         449              10 :     if (gRefCnt++ == 0) {
         450               7 :         rv = CallGetService(kRDFServiceCID, &gRDFService);
         451                 :
         452               7 :         NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF service");
         453               7 :         if (NS_FAILED(rv)) return rv;
         454                 :     }
         455                 :
         456              10 :     return NS_OK;
         457                 : }
         458                 :
         459                 :
         460              30 : RDFXMLDataSourceImpl::~RDFXMLDataSourceImpl(void)
         461                 : {
         462                 :     nsresult rv;
         463                 :
         464                 :     // Unregister first so that nobody else tries to get us.
         465              10 :     rv = gRDFService->UnregisterDataSource(this);
         466                 :
         467                 :     // Now flush contents
         468              10 :     rv = Flush();
         469                 :
         470                 :     // Release RDF/XML sink observers
         471              10 :     mObservers.Clear();
         472                 :
         473              10 :     if (--gRefCnt == 0)
         474               7 :         NS_IF_RELEASE(gRDFService);
         475              40 : }
         476                 :
         477            1396 : NS_IMPL_CYCLE_COLLECTION_CLASS(RDFXMLDataSourceImpl)
         478               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_0(RDFXMLDataSourceImpl)
         479               2 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(RDFXMLDataSourceImpl)
         480               2 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInner)
         481               2 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
         482                 :
         483             647 : NS_IMPL_CYCLE_COLLECTING_ADDREF(RDFXMLDataSourceImpl)
         484             647 : NS_IMPL_CYCLE_COLLECTING_RELEASE(RDFXMLDataSourceImpl)
         485                 :
         486            1069 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RDFXMLDataSourceImpl)
         487             602 :     NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
         488             448 :     NS_INTERFACE_MAP_ENTRY(nsIRDFRemoteDataSource)
         489             436 :     NS_INTERFACE_MAP_ENTRY(nsIRDFXMLSink)
         490             208 :     NS_INTERFACE_MAP_ENTRY(nsIRDFXMLSource)
         491             208 :     NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
         492             208 :     NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
         493             200 :     NS_INTERFACE_MAP_ENTRY(rdfIDataSource)
         494             181 :     NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
         495             167 :     NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink)
         496             163 :     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRDFDataSource)
         497             126 : NS_INTERFACE_MAP_END
         498                 :
         499                 : // nsIInterfaceRequestor
         500                 : NS_IMETHODIMP
         501              17 : RDFXMLDataSourceImpl::GetInterface(const nsIID& aIID, void** aSink)
         502                 : {
         503              17 :   return QueryInterface(aIID, aSink);
         504                 : }
         505                 :
         506                 : nsresult
         507               6 : RDFXMLDataSourceImpl::BlockingParse(nsIURI* aURL, nsIStreamListener* aConsumer)
         508                 : {
         509                 :     nsresult rv;
         510                 :
         511                 :     // XXX I really hate the way that we're spoon-feeding this stuff
         512                 :     // to the parser: it seems like this is something that netlib
         513                 :     // should be able to do by itself.
         514                 :
         515              12 :     nsCOMPtr<nsIChannel> channel;
         516              12 :     nsCOMPtr<nsIRequest> request;
         517                 :
         518                 :     // Null LoadGroup ?
         519               6 :     rv = NS_NewChannel(getter_AddRefs(channel), aURL, nsnull);
         520               6 :     if (NS_FAILED(rv)) return rv;
         521              12 :     nsCOMPtr<nsIInputStream> in;
         522               6 :     rv = channel->Open(getter_AddRefs(in));
         523                 :
         524                 :     // Report success if the file doesn't exist, but propagate other errors.
         525               6 :     if (rv == NS_ERROR_FILE_NOT_FOUND) return NS_OK;
         526               4 :     if (NS_FAILED(rv)) return rv;
         527                 :
         528               4 :     if (! in) {
         529               0 :         NS_ERROR("no input stream");
         530               0 :         return NS_ERROR_FAILURE;
         531                 :     }
         532                 :
         533                 :     // Wrap the channel's input stream in a buffered stream to ensure that
         534                 :     // ReadSegments is implemented (which OnDataAvailable expects).
         535               8 :     nsCOMPtr<nsIInputStream> bufStream;
         536               4 :     rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), in,
         537               4 :                                    4096 /* buffer size */);
         538               4 :     if (NS_FAILED(rv)) return rv;
         539                 :
         540                 :     // Notify load observers
         541                 :     PRInt32 i;
         542               4 :     for (i = mObservers.Count() - 1; i >= 0; --i) {
         543                 :         // Make sure to hold a strong reference to the observer so
         544                 :         // that it doesn't go away in this call if it removes itself
         545                 :         // as an observer
         546               0 :         nsCOMPtr<nsIRDFXMLSinkObserver> obs = mObservers[i];
         547                 :
         548               0 :         if (obs) {
         549               0 :             obs->OnBeginLoad(this);
         550                 :         }
         551                 :     }
         552                 :
         553               4 :     rv = aConsumer->OnStartRequest(channel, nsnull);
         554                 :
         555               4 :     PRUint32 offset = 0;
         556              12 :     while (NS_SUCCEEDED(rv)) {
         557                 :         // Skip ODA if the channel is canceled
         558               8 :         channel->GetStatus(&rv);
         559               8 :         if (NS_FAILED(rv))
         560               0 :             break;
         561                 :
         562                 :         PRUint32 avail;
         563               8 :         if (NS_FAILED(rv = bufStream->Available(&avail)))
         564               0 :             break; // error
         565                 :
         566               8 :         if (avail == 0)
         567               4 :             break; // eof
         568                 :
         569               4 :         rv = aConsumer->OnDataAvailable(channel, nsnull, bufStream, offset, avail);
         570               4 :         if (NS_SUCCEEDED(rv))
         571               4 :             offset += avail;
         572                 :     }
         573                 :
         574               4 :     if (NS_FAILED(rv))
         575               0 :         channel->Cancel(rv);
         576                 :
         577               4 :     channel->GetStatus(&rv);
         578               4 :     aConsumer->OnStopRequest(channel, nsnull, rv);
         579                 :
         580                 :     // Notify load observers
         581               4 :     for (i = mObservers.Count() - 1; i >= 0; --i) {
         582                 :         // Make sure to hold a strong reference to the observer so
         583                 :         // that it doesn't go away in this call if it removes itself
         584                 :         // as an observer
         585               0 :         nsCOMPtr<nsIRDFXMLSinkObserver> obs = mObservers[i];
         586                 :
         587               0 :         if (obs) {
         588               0 :             if (NS_FAILED(rv))
         589               0 :                 obs->OnError(this, rv, nsnull);
         590                 :
         591               0 :             obs->OnEndLoad(this);
         592                 :         }
         593                 :     }
         594                 :
         595               4 :     return rv;
         596                 : }
         597                 :
         598                 : NS_IMETHODIMP
         599               0 : RDFXMLDataSourceImpl::GetLoaded(bool* _result)
         600                 : {
         601               0 :     *_result = (mLoadState == eLoadState_Loaded);
         602               0 :     return NS_OK;
         603                 : }
         604                 :
         605                 : NS_IMETHODIMP
         606              10 : RDFXMLDataSourceImpl::Init(const char* uri)
         607                 : {
         608              10 :     NS_PRECONDITION(mInner != nsnull, "not initialized");
         609              10 :     if (! mInner)
         610               0 :         return NS_ERROR_OUT_OF_MEMORY;
         611                 :
         612                 :     nsresult rv;
         613                 :
         614              10 :     rv = NS_NewURI(getter_AddRefs(mURL), nsDependentCString(uri));
         615              10 :     if (NS_FAILED(rv)) return rv;
         616                 :
         617                 :     // XXX this is a hack: any "file:" URI is considered writable. All
         618                 :     // others are considered read-only.
         619              14 :     if ((PL_strncmp(uri, kFileURIPrefix, sizeof(kFileURIPrefix) - 1) != 0) &&
         620               4 :         (PL_strncmp(uri, kResourceURIPrefix, sizeof(kResourceURIPrefix) - 1) != 0)) {
         621               4 :         mIsWritable = false;
         622                 :     }
         623                 :
         624              10 :     rv = gRDFService->RegisterDataSource(this, false);
         625              10 :     if (NS_FAILED(rv)) return rv;
         626                 :
         627              10 :     return NS_OK;
         628                 : }
         629                 :
         630                 :
         631                 : NS_IMETHODIMP
         632              39 : RDFXMLDataSourceImpl::GetURI(char* *aURI)
         633                 : {
         634              39 :     *aURI = nsnull;
         635              39 :     if (!mURL) {
         636               0 :         return NS_OK;
         637                 :     }
         638                 :
         639              78 :     nsCAutoString spec;
         640              39 :     mURL->GetSpec(spec);
         641              39 :     *aURI = ToNewCString(spec);
         642              39 :     if (!*aURI) {
         643               0 :         return NS_ERROR_OUT_OF_MEMORY;
         644                 :     }
         645                 :
         646              39 :     return NS_OK;
         647                 : }
         648                 :
         649                 : NS_IMETHODIMP
         650             524 : RDFXMLDataSourceImpl::Assert(nsIRDFResource* aSource,
         651                 :                              nsIRDFResource* aProperty,
         652                 :                              nsIRDFNode* aTarget,
         653                 :                              bool aTruthValue)
         654                 : {
         655                 :     // We don't accept assertions unless we're writable (except in the
         656                 :     // case that we're actually _reading_ the datasource in).
         657                 :     nsresult rv;
         658                 :
         659             524 :     if (IsLoading()) {
         660             371 :         bool hasAssertion = false;
         661                 :
         662             742 :         nsCOMPtr<nsIRDFPurgeableDataSource> gcable = do_QueryInterface(mInner);
         663             371 :         if (gcable) {
         664             371 :             rv = gcable->Mark(aSource, aProperty, aTarget, aTruthValue, &hasAssertion);
         665             371 :             if (NS_FAILED(rv)) return rv;
         666                 :         }
         667                 :
         668             371 :         rv = NS_RDF_ASSERTION_ACCEPTED;
         669                 :
         670             371 :         if (! hasAssertion) {
         671             371 :             rv = mInner->Assert(aSource, aProperty, aTarget, aTruthValue);
         672                 :
         673             371 :             if (NS_SUCCEEDED(rv) && gcable) {
         674                 :                 // Now mark the new assertion, so it doesn't get
         675                 :                 // removed when we sweep. Ignore rv, because we want
         676                 :                 // to return what mInner->Assert() gave us.
         677                 :                 bool didMark;
         678             371 :                 (void) gcable->Mark(aSource, aProperty, aTarget, aTruthValue, &didMark);
         679                 :             }
         680                 :
         681             371 :             if (NS_FAILED(rv)) return rv;
         682                 :         }
         683                 :
         684             371 :         return rv;
         685                 :     }
         686             153 :     else if (mIsWritable) {
         687             153 :         rv = mInner->Assert(aSource, aProperty, aTarget, aTruthValue);
         688                 :
         689             153 :         if (rv == NS_RDF_ASSERTION_ACCEPTED)
         690             153 :             mIsDirty = true;
         691                 :
         692             153 :         return rv;
         693                 :     }
         694                 :     else {
         695               0 :         return NS_RDF_ASSERTION_REJECTED;
         696                 :     }
         697                 : }
         698                 :
         699                 :
         700                 : NS_IMETHODIMP
         701              78 : RDFXMLDataSourceImpl::Unassert(nsIRDFResource* source,
         702                 :                                nsIRDFResource* property,
         703                 :                                nsIRDFNode* target)
         704                 : {
         705                 :     // We don't accept assertions unless we're writable (except in the
         706                 :     // case that we're actually _reading_ the datasource in).
         707                 :     nsresult rv;
         708                 :
         709              78 :     if (IsLoading() || mIsWritable) {
         710              78 :         rv = mInner->Unassert(source, property, target);
         711              78 :         if (!IsLoading() && rv == NS_RDF_ASSERTION_ACCEPTED)
         712              46 :             mIsDirty = true;
         713                 :     }
         714                 :     else {
         715               0 :         rv = NS_RDF_ASSERTION_REJECTED;
         716                 :     }
         717                 :
         718              78 :     return rv;
         719                 : }
         720                 :
         721                 : NS_IMETHODIMP
         722              34 : RDFXMLDataSourceImpl::Change(nsIRDFResource* aSource,
         723                 :                              nsIRDFResource* aProperty,
         724                 :                              nsIRDFNode* aOldTarget,
         725                 :                              nsIRDFNode* aNewTarget)
         726                 : {
         727                 :     nsresult rv;
         728                 :
         729              34 :     if (IsLoading() || mIsWritable) {
         730              34 :         rv = mInner->Change(aSource, aProperty, aOldTarget, aNewTarget);
         731                 :
         732              34 :         if (!IsLoading() && rv == NS_RDF_ASSERTION_ACCEPTED)
         733              34 :             mIsDirty = true;
         734                 :     }
         735                 :     else {
         736               0 :         rv = NS_RDF_ASSERTION_REJECTED;
         737                 :     }
         738                 :
         739              34 :     return rv;
         740                 : }
         741                 :
         742                 : NS_IMETHODIMP
         743               0 : RDFXMLDataSourceImpl::Move(nsIRDFResource* aOldSource,
         744                 :                            nsIRDFResource* aNewSource,
         745                 :                            nsIRDFResource* aProperty,
         746                 :                            nsIRDFNode* aTarget)
         747                 : {
         748                 :     nsresult rv;
         749                 :
         750               0 :     if (IsLoading() || mIsWritable) {
         751               0 :         rv = mInner->Move(aOldSource, aNewSource, aProperty, aTarget);
         752               0 :         if (!IsLoading() && rv == NS_RDF_ASSERTION_ACCEPTED)
         753               0 :             mIsDirty = true;
         754                 :     }
         755                 :     else {
         756               0 :         rv = NS_RDF_ASSERTION_REJECTED;
         757                 :     }
         758                 :
         759               0 :     return rv;
         760                 : }
         761                 :
         762                 :
         763                 : nsresult
         764              20 : RDFXMLDataSourceImpl::rdfXMLFlush(nsIURI *aURI)
         765                 : {
         766                 :
         767                 :     nsresult rv;
         768                 :
         769                 :     {
         770                 :         // Quick and dirty check to see if we're in XPCOM shutdown. If
         771                 :         // we are, we're screwed: it's too late to serialize because
         772                 :         // many of the services that we'll need to acquire to properly
         773                 :         // write the file will be unaquirable.
         774              40 :         nsCOMPtr<nsIRDFService> dummy = do_GetService(kRDFServiceCID, &rv);
         775              20 :         if (NS_FAILED(rv)) {
         776               1 :             NS_WARNING("unable to Flush() diry datasource during XPCOM shutdown");
         777               1 :             return rv;
         778                 :         }
         779                 :     }
         780                 :
         781                 :     // Is it a file? If so, we can write to it. Some day, it'd be nice
         782                 :     // if we didn't care what kind of stream this was...
         783              38 :     nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aURI);
         784                 :
         785              19 :     if (fileURL) {
         786              38 :         nsCOMPtr<nsIFile> file;
         787              19 :         fileURL->GetFile(getter_AddRefs(file));
         788              19 :         if (file) {
         789                 :             // get a safe output stream, so we don't clobber the datasource file unless
         790                 :             // all the writes succeeded.
         791              38 :             nsCOMPtr<nsIOutputStream> out;
         792              19 :             rv = NS_NewSafeLocalFileOutputStream(getter_AddRefs(out),
         793                 :                                                  file,
         794                 :                                                  PR_WRONLY | PR_CREATE_FILE,
         795                 :                                                  /*octal*/ 0666,
         796              19 :                                                  0);
         797              19 :             if (NS_FAILED(rv)) return rv;
         798                 :
         799              38 :             nsCOMPtr<nsIOutputStream> bufferedOut;
         800              19 :             rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOut), out, 4096);
         801              19 :             if (NS_FAILED(rv)) return rv;
         802                 :
         803              19 :             rv = Serialize(bufferedOut);
         804              19 :             if (NS_FAILED(rv)) return rv;
         805                 :
         806                 :             // All went ok. Maybe except for problems in Write(), but the stream detects
         807                 :             // that for us
         808              38 :             nsCOMPtr<nsISafeOutputStream> safeStream = do_QueryInterface(bufferedOut, &rv);
         809              19 :             if (NS_FAILED(rv)) return rv;
         810                 :
         811              19 :             rv = safeStream->Finish();
         812              19 :             if (NS_FAILED(rv)) {
         813               0 :                 NS_WARNING("failed to save datasource file! possible dataloss");
         814               0 :                 return rv;
         815                 :             }
         816                 :         }
         817                 :     }
         818                 :
         819              19 :     return NS_OK;
         820                 : }
         821                 :
         822                 :
         823                 : NS_IMETHODIMP
         824               0 : RDFXMLDataSourceImpl::FlushTo(const char *aURI)
         825                 : {
         826               0 :     NS_PRECONDITION(aURI != nsnull, "not initialized");
         827               0 :     if (!aURI)
         828               0 :         return NS_ERROR_NULL_POINTER;
         829                 :
         830                 :     // XXX this is a hack: any "file:" URI is considered writable. All
         831                 :     // others are considered read-only.
         832               0 :     if ((PL_strncmp(aURI, kFileURIPrefix, sizeof(kFileURIPrefix) - 1) != 0) &&
         833               0 :         (PL_strncmp(aURI, kResourceURIPrefix, sizeof(kResourceURIPrefix) - 1) != 0))
         834                 :     {
         835               0 :         return NS_ERROR_ILLEGAL_VALUE;
         836                 :     }
         837                 :
         838               0 :     nsCOMPtr<nsIURI>  url;
         839               0 :     nsresult rv = NS_NewURI(getter_AddRefs(url), aURI);
         840               0 :     if (NS_FAILED(rv))
         841               0 :       return rv;
         842               0 :     rv = rdfXMLFlush(url);
         843               0 :     return rv;
         844                 : }
         845                 :
         846                 :
         847                 : NS_IMETHODIMP
         848              29 : RDFXMLDataSourceImpl::Flush(void)
         849                 : {
         850              29 :     if (!mIsWritable || !mIsDirty)
         851               9 :         return NS_OK;
         852                 :
         853                 :     // while it is not fatal if mURL is not set,
         854                 :     // indicate failure since we can't flush back to an unknown origin
         855              20 :     if (! mURL)
         856               0 :         return NS_ERROR_NOT_INITIALIZED;
         857                 :
         858                 : #ifdef PR_LOGGING
         859              40 :     nsCAutoString spec;
         860              20 :     mURL->GetSpec(spec);
         861              20 :     PR_LOG(gLog, PR_LOG_NOTICE,
         862                 :            ("rdfxml[%p] flush(%s)", this, spec.get()));
         863                 : #endif
         864                 :
         865                 :     nsresult rv;
         866              20 :     if (NS_SUCCEEDED(rv = rdfXMLFlush(mURL)))
         867                 :     {
         868              19 :       mIsDirty = false;
         869                 :     }
         870              20 :     return rv;
         871                 : }
         872                 :
         873                 :
         874                 : //----------------------------------------------------------------------
         875                 : //
         876                 : // nsIRDFXMLDataSource methods
         877                 : //
         878                 :
         879                 : NS_IMETHODIMP
         880               0 : RDFXMLDataSourceImpl::GetReadOnly(bool* aIsReadOnly)
         881                 : {
         882               0 :     *aIsReadOnly = !mIsWritable;
         883               0 :     return NS_OK;
         884                 : }
         885                 :
         886                 :
         887                 : NS_IMETHODIMP
         888               0 : RDFXMLDataSourceImpl::SetReadOnly(bool aIsReadOnly)
         889                 : {
         890               0 :     if (mIsWritable && aIsReadOnly)
         891               0 :         mIsWritable = false;
         892                 :
         893               0 :     return NS_OK;
         894                 : }
         895                 :
         896                 : // nsIChannelEventSink
         897                 :
         898                 : // This code is copied from nsSameOriginChecker::OnChannelRedirect. See
         899                 : // bug 475940 on providing this code in a shared location.
         900                 : NS_IMETHODIMP
         901               2 : RDFXMLDataSourceImpl::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
         902                 :                                              nsIChannel *aNewChannel,
         903                 :                                              PRUint32 aFlags,
         904                 :                                              nsIAsyncVerifyRedirectCallback *cb)
         905                 : {
         906               2 :     NS_PRECONDITION(aNewChannel, "Redirecting to null channel?");
         907                 :
         908                 :     nsresult rv;
         909                 :     nsCOMPtr<nsIScriptSecurityManager> secMan =
         910               4 :         do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
         911               2 :     NS_ENSURE_SUCCESS(rv, rv);
         912                 :
         913               4 :     nsCOMPtr<nsIPrincipal> oldPrincipal;
         914               2 :     secMan->GetChannelPrincipal(aOldChannel, getter_AddRefs(oldPrincipal));
         915                 :
         916               4 :     nsCOMPtr<nsIURI> newURI;
         917               2 :     aNewChannel->GetURI(getter_AddRefs(newURI));
         918               4 :     nsCOMPtr<nsIURI> newOriginalURI;
         919               2 :     aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
         920                 :
         921               2 :     NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI);
         922                 :
         923               2 :     rv = oldPrincipal->CheckMayLoad(newURI, false);
         924               2 :     if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
         925               0 :         rv = oldPrincipal->CheckMayLoad(newOriginalURI, false);
         926                 :     }
         927                 :
         928               2 :     if (NS_FAILED(rv))
         929               1 :         return rv;
         930                 :
         931               1 :     cb->OnRedirectVerifyCallback(NS_OK);
         932               1 :     return NS_OK;
         933                 : }
         934                 :
         935                 : NS_IMETHODIMP
         936              10 : RDFXMLDataSourceImpl::Refresh(bool aBlocking)
         937                 : {
         938                 : #ifdef PR_LOGGING
         939              20 :     nsCAutoString spec;
         940              10 :     if (mURL) {
         941              10 :         mURL->GetSpec(spec);
         942                 :     }
         943              10 :     PR_LOG(gLog, PR_LOG_NOTICE,
         944                 :            ("rdfxml[%p] refresh(%s) %sblocking", this, spec.get(), (aBlocking ? "" : "non")));
         945                 : #endif
         946                 :
         947                 :     // If an asynchronous load is already pending, then just let it do
         948                 :     // the honors.
         949              10 :     if (IsLoading()) {
         950               0 :         PR_LOG(gLog, PR_LOG_NOTICE,
         951                 :                ("rdfxml[%p] refresh(%s) a load was pending", this, spec.get()));
         952                 :
         953               0 :         if (aBlocking) {
         954               0 :             NS_WARNING("blocking load requested when async load pending");
         955               0 :             return NS_ERROR_FAILURE;
         956                 :         }
         957                 :         else {
         958               0 :             return NS_OK;
         959                 :         }
         960                 :     }
         961                 :
         962              10 :     if (! mURL)
         963               0 :         return NS_ERROR_FAILURE;
         964              20 :     nsCOMPtr<nsIRDFXMLParser> parser = do_CreateInstance("@mozilla.org/rdf/xml-parser;1");
         965              10 :     if (! parser)
         966               0 :         return NS_ERROR_FAILURE;
         967                 :
         968              10 :     nsresult rv = parser->ParseAsync(this, mURL, getter_AddRefs(mListener));
         969              10 :     if (NS_FAILED(rv)) return rv;
         970                 :
         971              10 :     if (aBlocking) {
         972               6 :         rv = BlockingParse(mURL, this);
         973                 :
         974               6 :         mListener = nsnull; // release the parser
         975                 :
         976               6 :         if (NS_FAILED(rv)) return rv;
         977                 :     }
         978                 :     else {
         979                 :         // Null LoadGroup ?
         980               4 :         rv = NS_OpenURI(this, nsnull, mURL, nsnull, nsnull, this);
         981               4 :         if (NS_FAILED(rv)) return rv;
         982                 :
         983                 :         // So we don't try to issue two asynchronous loads at once.
         984               4 :         mLoadState = eLoadState_Pending;
         985                 :     }
         986                 :
         987              10 :     return NS_OK;
         988                 : }
         989                 :
         990                 : NS_IMETHODIMP
         991               8 : RDFXMLDataSourceImpl::BeginLoad(void)
         992                 : {
         993                 : #ifdef PR_LOGGING
         994              16 :     nsCAutoString spec;
         995               8 :     if (mURL) {
         996               8 :         mURL->GetSpec(spec);
         997                 :     }
         998               8 :     PR_LOG(gLog, PR_LOG_NOTICE,
         999                 :            ("rdfxml[%p] begin-load(%s)", this, spec.get()));
        1000                 : #endif
        1001                 :
        1002               8 :     mLoadState = eLoadState_Loading;
        1003              12 :     for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
        1004                 :         // Make sure to hold a strong reference to the observer so
        1005                 :         // that it doesn't go away in this call if it removes itself
        1006                 :         // as an observer
        1007               8 :         nsCOMPtr<nsIRDFXMLSinkObserver> obs = mObservers[i];
        1008                 :
        1009               4 :         if (obs) {
        1010               4 :             obs->OnBeginLoad(this);
        1011                 :         }
        1012                 :     }
        1013               8 :     return NS_OK;
        1014                 : }
        1015                 :
        1016                 : NS_IMETHODIMP
        1017               7 : RDFXMLDataSourceImpl::Interrupt(void)
        1018                 : {
        1019                 : #ifdef PR_LOGGING
        1020              14 :     nsCAutoString spec;
        1021               7 :     if (mURL) {
        1022               7 :         mURL->GetSpec(spec);
        1023                 :     }
        1024               7 :     PR_LOG(gLog, PR_LOG_NOTICE,
        1025                 :            ("rdfxml[%p] interrupt(%s)", this, spec.get()));
        1026                 : #endif
        1027                 :
        1028              10 :     for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
        1029                 :         // Make sure to hold a strong reference to the observer so
        1030                 :         // that it doesn't go away in this call if it removes itself
        1031                 :         // as an observer
        1032               6 :         nsCOMPtr<nsIRDFXMLSinkObserver> obs = mObservers[i];
        1033                 :
        1034               3 :         if (obs) {
        1035               3 :             obs->OnInterrupt(this);
        1036                 :         }
        1037                 :     }
        1038               7 :     return NS_OK;
        1039                 : }
        1040                 :
        1041                 : NS_IMETHODIMP
        1042              15 : RDFXMLDataSourceImpl::Resume(void)
        1043                 : {
        1044                 : #ifdef PR_LOGGING
        1045              30 :     nsCAutoString spec;
        1046              15 :     if (mURL) {
        1047              15 :         mURL->GetSpec(spec);
        1048                 :     }
        1049              15 :     PR_LOG(gLog, PR_LOG_NOTICE,
        1050                 :            ("rdfxml[%p] resume(%s)", this, spec.get()));
        1051                 : #endif
        1052                 :
        1053              22 :     for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
        1054                 :         // Make sure to hold a strong reference to the observer so
        1055                 :         // that it doesn't go away in this call if it removes itself
        1056                 :         // as an observer
        1057              14 :         nsCOMPtr<nsIRDFXMLSinkObserver> obs = mObservers[i];
        1058                 :
        1059               7 :         if (obs) {
        1060               7 :             obs->OnResume(this);
        1061                 :         }
        1062                 :     }
        1063              15 :     return NS_OK;
        1064                 : }
        1065                 :
        1066                 : NS_IMETHODIMP
        1067               8 : RDFXMLDataSourceImpl::EndLoad(void)
        1068                 : {
        1069                 : #ifdef PR_LOGGING
        1070              16 :     nsCAutoString spec;
        1071               8 :     if (mURL) {
        1072               8 :         mURL->GetSpec(spec);
        1073                 :     }
        1074               8 :     PR_LOG(gLog, PR_LOG_NOTICE,
        1075                 :            ("rdfxml[%p] end-load(%s)", this, spec.get()));
        1076                 : #endif
        1077                 :
        1078               8 :     mLoadState = eLoadState_Loaded;
        1079                 :
        1080                 :     // Clear out any unmarked assertions from the datasource.
        1081              16 :     nsCOMPtr<nsIRDFPurgeableDataSource> gcable = do_QueryInterface(mInner);
        1082               8 :     if (gcable) {
        1083               8 :         gcable->Sweep();
        1084                 :     }
        1085                 :
        1086                 :     // Notify load observers
        1087              12 :     for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
        1088                 :         // Make sure to hold a strong reference to the observer so
        1089                 :         // that it doesn't go away in this call if it removes itself
        1090                 :         // as an observer
        1091               8 :         nsCOMPtr<nsIRDFXMLSinkObserver> obs = mObservers[i];
        1092                 :
        1093               4 :         if (obs) {
        1094               4 :             obs->OnEndLoad(this);
        1095                 :         }
        1096                 :     }
        1097               8 :     return NS_OK;
        1098                 : }
        1099                 :
        1100                 : NS_IMETHODIMP
        1101              18 : RDFXMLDataSourceImpl::AddNameSpace(nsIAtom* aPrefix, const nsString& aURI)
        1102                 : {
        1103              18 :     mNameSpaces.Put(aURI, aPrefix);
        1104              18 :     return NS_OK;
        1105                 : }
        1106                 :
        1107                 :
        1108                 : NS_IMETHODIMP
        1109               4 : RDFXMLDataSourceImpl::AddXMLSinkObserver(nsIRDFXMLSinkObserver* aObserver)
        1110                 : {
        1111               4 :     if (! aObserver)
        1112               0 :         return NS_ERROR_NULL_POINTER;
        1113                 :
        1114               4 :     mObservers.AppendObject(aObserver);
        1115               4 :     return NS_OK;
        1116                 : }
        1117                 :
        1118                 : NS_IMETHODIMP
        1119               4 : RDFXMLDataSourceImpl::RemoveXMLSinkObserver(nsIRDFXMLSinkObserver* aObserver)
        1120                 : {
        1121               4 :     if (! aObserver)
        1122               0 :         return NS_ERROR_NULL_POINTER;
        1123                 :
        1124               4 :     mObservers.RemoveObject(aObserver);
        1125                 :
        1126               4 :     return NS_OK;
        1127                 : }
        1128                 :
        1129                 :
        1130                 : //----------------------------------------------------------------------
        1131                 : //
        1132                 : // nsIRequestObserver
        1133                 : //
        1134                 :
        1135                 : NS_IMETHODIMP
        1136               8 : RDFXMLDataSourceImpl::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
        1137                 : {
        1138               8 :     return mListener->OnStartRequest(request, ctxt);
        1139                 : }
        1140                 :
        1141                 : NS_IMETHODIMP
        1142               8 : RDFXMLDataSourceImpl::OnStopRequest(nsIRequest *request,
        1143                 :                                     nsISupports *ctxt,
        1144                 :                                     nsresult status)
        1145                 : {
        1146               8 :     if (NS_FAILED(status)) {
        1147               0 :         for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
        1148                 :             // Make sure to hold a strong reference to the observer so
        1149                 :             // that it doesn't go away in this call if it removes
        1150                 :             // itself as an observer
        1151               0 :             nsCOMPtr<nsIRDFXMLSinkObserver> obs = mObservers[i];
        1152                 :
        1153               0 :             if (obs) {
        1154               0 :                 obs->OnError(this, status, nsnull);
        1155                 :             }
        1156                 :         }
        1157                 :     }
        1158                 :
        1159                 :     nsresult rv;
        1160               8 :     rv = mListener->OnStopRequest(request, ctxt, status);
        1161                 :
        1162               8 :     mListener = nsnull; // release the parser
        1163                 :
        1164               8 :     return rv;
        1165                 : }
        1166                 :
        1167                 : //----------------------------------------------------------------------
        1168                 : //
        1169                 : // nsIStreamListener
        1170                 : //
        1171                 :
        1172                 : NS_IMETHODIMP
        1173               7 : RDFXMLDataSourceImpl::OnDataAvailable(nsIRequest *request,
        1174                 :                                       nsISupports *ctxt,
        1175                 :                                       nsIInputStream *inStr,
        1176                 :                                       PRUint32 sourceOffset,
        1177                 :                                       PRUint32 count)
        1178                 : {
        1179               7 :     return mListener->OnDataAvailable(request, ctxt, inStr, sourceOffset, count);
        1180                 : }
        1181                 :
        1182                 : //----------------------------------------------------------------------
        1183                 : //
        1184                 : // nsIRDFXMLSource
        1185                 : //
        1186                 :
        1187                 : NS_IMETHODIMP
        1188              19 : RDFXMLDataSourceImpl::Serialize(nsIOutputStream* aStream)
        1189                 : {
        1190                 :     nsresult rv;
        1191                 :     nsCOMPtr<nsIRDFXMLSerializer> serializer
        1192              38 :         = do_CreateInstance("@mozilla.org/rdf/xml-serializer;1", &rv);
        1193                 :
        1194              19 :     if (! serializer)
        1195               0 :         return rv;
        1196                 :
        1197              19 :     rv = serializer->Init(this);
        1198              19 :     if (NS_FAILED(rv)) return rv;
        1199                 :
        1200                 :     // Add any namespace information that we picked up when reading
        1201                 :     // the RDF/XML
        1202              19 :     nsNameSpaceMap::const_iterator last = mNameSpaces.last();
        1203              19 :     for (nsNameSpaceMap::const_iterator iter = mNameSpaces.first();
        1204                 :          iter != last; ++iter) {
        1205                 :         // We might wanna change nsIRDFXMLSerializer to nsACString and
        1206                 :         // use a heap allocated buffer here in the future.
        1207               0 :         NS_ConvertUTF8toUTF16 uri(iter->mURI);
        1208               0 :         serializer->AddNameSpace(iter->mPrefix, uri);
        1209                 :     }
        1210                 :
        1211                 :     // Serialize!
        1212              38 :     nsCOMPtr<nsIRDFXMLSource> source = do_QueryInterface(serializer);
        1213              19 :     if (! source)
        1214               0 :         return NS_ERROR_FAILURE;
        1215                 :
        1216              19 :     return source->Serialize(aStream);
        1217            4188 : }

Generated by: LCOV version 1.7