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-06-02 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            2768 :     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            1464 : 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            4392 : }

Generated by: LCOV version 1.7