GME  13
URLAccessCFBinInputStream.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  *
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: URLAccessCFBinInputStream.cpp 936316 2010-04-21 14:19:58Z borisk $
00020  */
00021 
00022 #include <cstdlib>
00023 #include <cstring>
00024 
00025 #include <xercesc/util/XMLNetAccessor.hpp>
00026 #include <xercesc/util/NetAccessors/MacOSURLAccessCF/URLAccessCFBinInputStream.hpp>
00027 #include <xercesc/util/XMLString.hpp>
00028 #include <xercesc/util/XMLExceptMsgs.hpp>
00029 #include <xercesc/util/Janitor.hpp>
00030 
00031 XERCES_CPP_NAMESPACE_BEGIN
00032 
00033 URLAccessCFBinInputStream::URLAccessCFBinInputStream(const XMLURL& urlSource)
00034       : mBytesProcessed(0),
00035         mDataRef(NULL)
00036 {
00037     //  Figure out what we're dealing with
00038     const XMLCh* urlText = urlSource.getURLText();
00039     unsigned int urlLength = XMLString::stringLen(urlText);
00040 
00041     //  Create a CFString from the path
00042     CFStringRef stringRef = NULL;
00043     if (urlText)
00044     {
00045         stringRef = CFStringCreateWithCharacters(
00046             kCFAllocatorDefault,
00047             urlText,
00048             urlLength
00049             );
00050     }
00051 
00052     //  Create a URLRef from the CFString
00053     CFURLRef urlRef = NULL;
00054     if (stringRef)
00055     {
00056         urlRef = CFURLCreateWithString(
00057             kCFAllocatorDefault,
00058             stringRef,
00059             NULL                                // CFURLRef baseURL
00060             );
00061     }
00062 
00063         //      Fetch the data
00064     mDataRef = NULL;
00065     SInt32 errorCode = 0;
00066     Boolean success = false;
00067     if (stringRef)
00068     {
00069         success = CFURLCreateDataAndPropertiesFromResource(
00070             kCFAllocatorDefault,
00071             urlRef,
00072             &mDataRef,
00073             NULL,                               // CFDictionaryRef *properties,
00074             NULL,                               // CFArrayRef desiredProperties,
00075             &errorCode
00076             );
00077     }
00078 
00079     //  Cleanup temporary stuff
00080     if (stringRef)
00081         CFRelease(stringRef);
00082     if (urlRef)
00083         CFRelease(urlRef);
00084 
00085     //  Check for an error in fetching the data
00086     if (!success || errorCode)
00087     {
00088         //      Dispose any potential dataRef
00089         if (mDataRef)
00090         {
00091             CFRelease(mDataRef);
00092             mDataRef = NULL;
00093         }
00094 
00095         //      Do a best attempt at mapping some errors
00096         switch (errorCode)
00097         {
00098             case kCFURLUnknownSchemeError:
00099                 ThrowXML(MalformedURLException, XMLExcepts::URL_UnsupportedProto);
00100                 break;
00101 
00102             case kCFURLRemoteHostUnavailableError:
00103               {
00104                 if (urlSource.getHost())
00105                   ThrowXML1(NetAccessorException, XMLExcepts::NetAcc_TargetResolution, urlSource.getHost());
00106                 else
00107                   ThrowXML1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, urlText);
00108                 break;
00109               }
00110 
00111             case kCFURLUnknownError:
00112                 ThrowXML1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, urlText);
00113                 break;
00114 
00115             case kCFURLResourceNotFoundError:
00116             case kCFURLResourceAccessViolationError:
00117             case kCFURLTimeoutError:
00118                 ThrowXML1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, urlText);
00119                 break;
00120 
00121             case kCFURLImproperArgumentsError:
00122             case kCFURLUnknownPropertyKeyError:
00123             case kCFURLPropertyKeyUnavailableError:
00124             default:
00125                 ThrowXML1(NetAccessorException, XMLExcepts::NetAcc_InternalError, urlText);
00126                 break;
00127         }
00128     }
00129 }
00130 
00131 
00132 URLAccessCFBinInputStream::~URLAccessCFBinInputStream()
00133 {
00134     //  Release any dataRef
00135     if (mDataRef)
00136         CFRelease(mDataRef);
00137 }
00138 
00139 
00140 //
00141 //      We've already read the data into a dataRef.
00142 //      Just spoon it out to the caller as they ask for it.
00143 //
00144 XMLSize_t
00145 URLAccessCFBinInputStream::readBytes(XMLByte* const    toFill
00146                                     , const XMLSize_t  maxToRead)
00147 {
00148     //  If we don't have a dataRef, we can't return any data
00149     if (!mDataRef)
00150         return 0;
00151 
00152     //  Get the length of the data we've fetched
00153     CFIndex dataLength = CFDataGetLength(mDataRef);
00154 
00155     //  Calculate how much to return based on how much
00156     //  we've already returned, and how much the user wants
00157     CFIndex n = dataLength - mBytesProcessed;                   // Amount remaining
00158     CFIndex desired = maxToRead & 0x7fffffff;                   // CFIndex is signed
00159     if (n > desired)                                                                    // Amount desired
00160         n = desired;
00161 
00162     //  Read the appropriate bytes into the user buffer
00163     CFRange range = CFRangeMake(mBytesProcessed, n);
00164     CFDataGetBytes(mDataRef, range, reinterpret_cast<UInt8*>(toFill));
00165 
00166     //  Update bytes processed
00167     mBytesProcessed += n;
00168 
00169     //  Return the number of bytes delivered
00170     return n;
00171 }
00172 
00173 const XMLCh* URLAccessCFBinInputStream::getContentType() const
00174 {
00175     // TODO
00176     //
00177     return 0;
00178 }
00179 
00180 XERCES_CPP_NAMESPACE_END