GME  13
LocalFileInputSource.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 // ---------------------------------------------------------------------------
00020 //  Includes
00021 // ---------------------------------------------------------------------------
00022 #include <xercesc/framework/LocalFileInputSource.hpp>
00023 #include <xercesc/util/BinFileInputStream.hpp>
00024 #include <xercesc/util/PlatformUtils.hpp>
00025 #include <xercesc/util/XMLString.hpp>
00026 #include <xercesc/util/XMLUniDefs.hpp>
00027 
00028 XERCES_CPP_NAMESPACE_BEGIN
00029 
00030 /***
00031  *
00032  * Originated by Chris larsson
00033  *
00034  * Issue:
00035  *
00036  * There is an inconsistency in URI resolution in the case where the file itself is a 
00037  * symbolic link to another path (or the path has path segment which is a symbolic
00038  * link to another path). So, is the base path the directory where the symbolic link resides 
00039  * or the directory where the real file resides? I'm sure one could argue either way, 
00040  * but I think that having the base path be the directory where the symbolic link resides 
00041  * is more intuitive. 
00042  *
00043  * Defining it this way would then make the behavior consistent with using an absolute 
00044  * path as well as with the java behavior. 
00045  *
00046  * Proposal:
00047  *
00048  * The URI is resolved within the parser code, and is somewhat independant of the OS. 
00049  * 
00050  * A relative path is resolved by querying the current directory and appending the 
00051  * relative part onto the returned current directory string to obtain the base URI. 
00052  * An absolute path is simply used as the base URI. 
00053  * Then remove all "./" and "../" path segments using an algorithm like weavepath to obtain 
00054  * the resolved base URI. 
00055  *
00056  * When you need to access another file such as a dtd, use the resolved base URI and add on
00057  * the relative URI of the dtd file. Then resolve it using the same weavepath algorithm. 
00058  *
00059  * Note:
00060  *
00061  *   Java parser behaves differently for a path containning symbolic path segment. When 
00062  *   it is given an absolute path, it can locate the primary instance document, while given 
00063  *   relative path, it might not.
00064  *
00065  *   It is because Java parser uses URI solution where "/segment/../" is required to be removed
00066  *   from the resultant path if a relative URI is merged to a baseURI. While this is NOT required
00067  *   for an absolute URI. 
00068  *   
00069  *   So if a path segment, which is symbolic link, happen to be followed by the '/../', it is 
00070  *   NOT removed from the path if it is given in absolute form, and the underlying file system 
00071  *   will locate the file, if in relative form, that symbolic link path segment together with 
00072  *   '../' is removed from the resultant path, and the file system may NOT be able to locate 
00073  *   the file, if there is a one, it is definitely not the one expected, in fact by accident.
00074  *
00075  *   Therefore, to keep consistent with Java parser, for now, we do not apply removeDotDotSlash()
00076  *   for absolute path.
00077  *  
00078  ***/
00079 
00080 // ---------------------------------------------------------------------------
00081 //  LocalFileInputSource: Constructors and Destructor
00082 // ---------------------------------------------------------------------------
00083 LocalFileInputSource::LocalFileInputSource( const XMLCh* const basePath
00084                                           , const XMLCh* const relativePath
00085                                           , MemoryManager* const manager)
00086     : InputSource(manager)
00087 {
00088     //
00089     //  If the relative part is really relative, then weave it together
00090     //  with the base path. If not, just take the relative path as the
00091     //  entire path.
00092     //
00093     if (XMLPlatformUtils::isRelative(relativePath, manager))
00094     {
00095         XMLCh* tmpBuf = XMLPlatformUtils::weavePaths(basePath, relativePath, manager);
00096         setSystemId(tmpBuf);
00097         manager->deallocate(tmpBuf); //delete [] tmpBuf;
00098     }
00099     else
00100     {
00101         XMLCh* tmpBuf = XMLString::replicate(relativePath, manager);
00102         XMLPlatformUtils::removeDotSlash(tmpBuf, manager);
00103         setSystemId(tmpBuf);
00104         manager->deallocate(tmpBuf);//delete [] tmpBuf;
00105     }
00106 
00107 }
00108 
00109 LocalFileInputSource::LocalFileInputSource(const XMLCh* const filePath,
00110                                            MemoryManager* const manager)
00111     : InputSource(manager)
00112 {
00113 
00114     //
00115     //  If the path is relative, then complete it acording to the current
00116     //  working directory rules of the current platform. Else, just take
00117     //  it as is.
00118     //
00119     if (XMLPlatformUtils::isRelative(filePath, manager))
00120     {
00121         XMLCh* curDir = XMLPlatformUtils::getCurrentDirectory(manager);
00122 
00123         XMLSize_t curDirLen = XMLString::stringLen(curDir);
00124         XMLSize_t filePathLen = XMLString::stringLen(filePath);
00125         XMLCh* fullDir = (XMLCh*) manager->allocate
00126         (
00127             (curDirLen + filePathLen + 2) * sizeof(XMLCh)
00128         );//new XMLCh [ curDirLen + filePathLen + 2];
00129 
00130         XMLString::copyString(fullDir, curDir);
00131         fullDir[curDirLen] = chForwardSlash;
00132         XMLString::copyString(&fullDir[curDirLen+1], filePath);
00133         
00134         XMLPlatformUtils::removeDotSlash(fullDir, manager);
00135         XMLPlatformUtils::removeDotDotSlash(fullDir, manager);
00136 
00137         setSystemId(fullDir);
00138 
00139         manager->deallocate(curDir);//delete [] curDir;
00140         manager->deallocate(fullDir);//delete [] fullDir;
00141     }
00142      else
00143     {
00144         XMLCh* tmpBuf = XMLString::replicate(filePath, manager);
00145         XMLPlatformUtils::removeDotSlash(tmpBuf, manager);
00146         setSystemId(tmpBuf);
00147         manager->deallocate(tmpBuf);//delete [] tmpBuf;
00148     }
00149 
00150 }
00151 
00152 LocalFileInputSource::~LocalFileInputSource()
00153 {
00154 }
00155 
00156 
00157 // ---------------------------------------------------------------------------
00158 //  LocalFileInputSource: InputSource interface implementation
00159 // ---------------------------------------------------------------------------
00160 BinInputStream* LocalFileInputSource::makeStream() const
00161 {
00162     BinFileInputStream* retStrm = new (getMemoryManager()) BinFileInputStream(getSystemId(), getMemoryManager());
00163     if (!retStrm->getIsOpen())
00164     {
00165         delete retStrm;
00166         return 0;
00167     }
00168     return retStrm;
00169 }
00170 
00171 XERCES_CPP_NAMESPACE_END
00172