QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsconfigcache.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsconfigcache.cpp
3  ------------------
4  begin : July 24th, 2010
5  copyright : (C) 2010 by Marco Hugentobler
6  email : marco dot hugentobler at sourcepole dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgsconfigcache.h"
19 #include "qgsmessagelog.h"
20 #include "qgsserverexception.h"
21 #include "qgsstorebadlayerinfo.h"
22 #include "qgsserverprojectutils.h"
23 
24 #include <QFile>
25 
27 {
28  static QgsConfigCache *sInstance = nullptr;
29 
30  if ( !sInstance )
31  sInstance = new QgsConfigCache();
32 
33  return sInstance;
34 }
35 
36 QgsConfigCache::QgsConfigCache()
37 {
38  QObject::connect( &mFileSystemWatcher, &QFileSystemWatcher::fileChanged, this, &QgsConfigCache::removeChangedEntry );
39 }
40 
41 
42 const QgsProject *QgsConfigCache::project( const QString &path, QgsServerSettings *settings )
43 {
44  if ( ! mProjectCache[ path ] )
45  {
46  std::unique_ptr<QgsProject> prj( new QgsProject() );
47 
48  QgsStoreBadLayerInfo *badLayerHandler = new QgsStoreBadLayerInfo();
49  prj->setBadLayerHandler( badLayerHandler );
50 
51  QgsProject::ReadFlags readFlags = QgsProject::ReadFlag();
52  if ( settings )
53  {
54  // Activate trust layer metadata flag
55  if ( settings->trustLayerMetadata() )
56  {
58  }
59  // Activate don't load layouts flag
60  if ( settings->getPrintDisabled() )
61  {
63  }
64  }
65 
66  if ( prj->read( path, readFlags ) )
67  {
68  if ( !badLayerHandler->badLayers().isEmpty() )
69  {
70  // if bad layers are not restricted layers so service failed
71  QStringList unrestrictedBadLayers;
72  // test bad layers through restrictedlayers
73  const QStringList badLayerIds = badLayerHandler->badLayers();
74  const QMap<QString, QString> badLayerNames = badLayerHandler->badLayerNames();
75  const QStringList resctrictedLayers = QgsServerProjectUtils::wmsRestrictedLayers( *prj );
76  for ( const QString &badLayerId : badLayerIds )
77  {
78  // if this bad layer is in restricted layers
79  // it doesn't need to be added to unrestricted bad layers
80  if ( badLayerNames.contains( badLayerId ) &&
81  resctrictedLayers.contains( badLayerNames.value( badLayerId ) ) )
82  {
83  continue;
84  }
85  unrestrictedBadLayers.append( badLayerId );
86  }
87  if ( !unrestrictedBadLayers.isEmpty() )
88  {
89  // This is a critical error unless QGIS_SERVER_IGNORE_BAD_LAYERS is set to TRUE
90  if ( ! settings || ! settings->ignoreBadLayers() )
91  {
93  QStringLiteral( "Error, Layer(s) %1 not valid in project %2" ).arg( unrestrictedBadLayers.join( QLatin1String( ", " ) ), path ),
94  QStringLiteral( "Server" ), Qgis::Critical );
95  throw QgsServerException( QStringLiteral( "Layer(s) not valid" ) );
96  }
97  else
98  {
100  QStringLiteral( "Warning, Layer(s) %1 not valid in project %2" ).arg( unrestrictedBadLayers.join( QLatin1String( ", " ) ), path ),
101  QStringLiteral( "Server" ), Qgis::Warning );
102  }
103  }
104  }
105  mProjectCache.insert( path, prj.release() );
106  mFileSystemWatcher.addPath( path );
107  }
108  else
109  {
111  QStringLiteral( "Error when loading project file '%1': %2 " ).arg( path, prj->error() ),
112  QStringLiteral( "Server" ), Qgis::Critical );
113  }
114  }
115  return mProjectCache[ path ];
116 
117 }
118 
119 QDomDocument *QgsConfigCache::xmlDocument( const QString &filePath )
120 {
121  //first open file
122  QFile configFile( filePath );
123  if ( !configFile.exists() )
124  {
125  QgsMessageLog::logMessage( "Error, configuration file '" + filePath + "' does not exist", QStringLiteral( "Server" ), Qgis::Critical );
126  return nullptr;
127  }
128 
129  if ( !configFile.open( QIODevice::ReadOnly ) )
130  {
131  QgsMessageLog::logMessage( "Error, cannot open configuration file '" + filePath + "'", QStringLiteral( "Server" ), Qgis::Critical );
132  return nullptr;
133  }
134 
135  // first get cache
136  QDomDocument *xmlDoc = mXmlDocumentCache.object( filePath );
137  if ( !xmlDoc )
138  {
139  //then create xml document
140  xmlDoc = new QDomDocument();
141  QString errorMsg;
142  int line, column;
143  if ( !xmlDoc->setContent( &configFile, true, &errorMsg, &line, &column ) )
144  {
145  QgsMessageLog::logMessage( "Error parsing file '" + filePath +
146  QStringLiteral( "': parse error %1 at row %2, column %3" ).arg( errorMsg ).arg( line ).arg( column ), QStringLiteral( "Server" ), Qgis::Critical );
147  delete xmlDoc;
148  return nullptr;
149  }
150  mXmlDocumentCache.insert( filePath, xmlDoc );
151  mFileSystemWatcher.addPath( filePath );
152  xmlDoc = mXmlDocumentCache.object( filePath );
153  Q_ASSERT( xmlDoc );
154  }
155  return xmlDoc;
156 }
157 
158 void QgsConfigCache::removeChangedEntry( const QString &path )
159 {
160  mProjectCache.remove( path );
161 
162  //xml document must be removed last, as other config cache destructors may require it
163  mXmlDocumentCache.remove( path );
164 
165  mFileSystemWatcher.removePath( path );
166 }
167 
168 
169 void QgsConfigCache::removeEntry( const QString &path )
170 {
171  removeChangedEntry( path );
172 }
QgsStoreBadLayerInfo::badLayerNames
QMap< QString, QString > badLayerNames() const
Returns names of bad layers with ids.
Definition: qgsstorebadlayerinfo.h:56
QgsServerSettings::getPrintDisabled
bool getPrintDisabled() const
Returns true if WMS GetPrint request is disabled and the project's reading flag QgsProject::ReadFlag:...
Definition: qgsserversettings.cpp:512
QgsConfigCache::removeEntry
void removeEntry(const QString &path)
Removes an entry from cache.
Definition: qgsconfigcache.cpp:169
QgsConfigCache
Cache for server configuration.
Definition: qgsconfigcache.h:39
QgsProject::ReadFlag::FlagDontLoadLayouts
@ FlagDontLoadLayouts
Don't load print layouts. Improves project read time if layouts are not required, and allows projects...
qgsconfigcache.h
Qgis::Warning
@ Warning
Definition: qgis.h:91
QgsConfigCache::instance
static QgsConfigCache * instance()
Returns the current instance.
Definition: qgsconfigcache.cpp:26
qgsserverprojectutils.h
QgsProject::ReadFlag
ReadFlag
Flags which control project read behavior.
Definition: qgsproject.h:120
qgsstorebadlayerinfo.h
QgsStoreBadLayerInfo::badLayers
QStringList badLayers() const
badLayers
Definition: qgsstorebadlayerinfo.h:50
QgsProject
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:95
QgsServerSettings::trustLayerMetadata
bool trustLayerMetadata() const
Returns true if the reading flag trust layer metadata is activated.
Definition: qgsserversettings.cpp:507
QgsServerSettings
Provides a way to retrieve settings by prioritizing according to environment variables,...
Definition: qgsserversettings.h:85
QgsServerProjectUtils::wmsRestrictedLayers
SERVER_EXPORT QStringList wmsRestrictedLayers(const QgsProject &project)
Returns the restricted layer name list.
Definition: qgsserverprojectutils.cpp:311
QgsServerSettings::ignoreBadLayers
bool ignoreBadLayers() const
Returns true if the bad layers are ignored and false when the presence of a bad layers invalidates th...
Definition: qgsserversettings.cpp:502
QgsServerException
Exception base class for server exceptions.
Definition: qgsserverexception.h:43
QgsMessageLog::logMessage
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Definition: qgsmessagelog.cpp:27
Qgis::Critical
@ Critical
Definition: qgis.h:92
QgsConfigCache::project
const QgsProject * project(const QString &path, QgsServerSettings *settings=nullptr)
If the project is not cached yet, then the project is read from the path.
Definition: qgsconfigcache.cpp:42
QgsStoreBadLayerInfo
Stores layer ids of bad layers.
Definition: qgsstorebadlayerinfo.h:32
qgsserverexception.h
QgsProject::ReadFlag::FlagTrustLayerMetadata
@ FlagTrustLayerMetadata
Trust layer metadata. Improves project read time. Do not use it if layers' extent is not fixed during...
qgsmessagelog.h