QGIS API Documentation  3.12.1-BucureČ™ti (121cc00ff0)
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 const QgsProject *QgsConfigCache::project( const QString &path )
42 {
43  if ( ! mProjectCache[ path ] )
44  {
45  std::unique_ptr<QgsProject> prj( new QgsProject() );
46  QgsStoreBadLayerInfo *badLayerHandler = new QgsStoreBadLayerInfo();
47  prj->setBadLayerHandler( badLayerHandler );
48  if ( prj->read( path ) )
49  {
50  if ( !badLayerHandler->badLayers().isEmpty() )
51  {
52  // if bad layers are not restricted layers so service failed
53  QStringList unrestrictedBadLayers;
54  // test bad layers through restrictedlayers
55  const QStringList badLayerIds = badLayerHandler->badLayers();
56  const QMap<QString, QString> badLayerNames = badLayerHandler->badLayerNames();
57  const QStringList resctrictedLayers = QgsServerProjectUtils::wmsRestrictedLayers( *prj );
58  for ( const QString &badLayerId : badLayerIds )
59  {
60  // if this bad layer is in restricted layers
61  // it doesn't need to be added to unrestricted bad layers
62  if ( badLayerNames.contains( badLayerId ) &&
63  resctrictedLayers.contains( badLayerNames.value( badLayerId ) ) )
64  {
65  continue;
66  }
67  unrestrictedBadLayers.append( badLayerId );
68  }
69  if ( !unrestrictedBadLayers.isEmpty() )
70  {
72  QStringLiteral( "Error, Layer(s) %1 not valid in project %2" ).arg( unrestrictedBadLayers.join( QStringLiteral( ", " ) ), path ),
73  QStringLiteral( "Server" ), Qgis::Critical );
74  throw QgsServerException( QStringLiteral( "Layer(s) not valid" ) );
75  }
76  }
77  mProjectCache.insert( path, prj.release() );
78  mFileSystemWatcher.addPath( path );
79  }
80  else
81  {
83  QStringLiteral( "Error when loading project file '%1': %2 " ).arg( path, prj->error() ),
84  QStringLiteral( "Server" ), Qgis::Critical );
85  }
86  }
87  QgsProject::setInstance( mProjectCache[ path ] );
88  return mProjectCache[ path ];
89 }
90 
91 QDomDocument *QgsConfigCache::xmlDocument( const QString &filePath )
92 {
93  //first open file
94  QFile configFile( filePath );
95  if ( !configFile.exists() )
96  {
97  QgsMessageLog::logMessage( "Error, configuration file '" + filePath + "' does not exist", QStringLiteral( "Server" ), Qgis::Critical );
98  return nullptr;
99  }
100 
101  if ( !configFile.open( QIODevice::ReadOnly ) )
102  {
103  QgsMessageLog::logMessage( "Error, cannot open configuration file '" + filePath + "'", QStringLiteral( "Server" ), Qgis::Critical );
104  return nullptr;
105  }
106 
107  // first get cache
108  QDomDocument *xmlDoc = mXmlDocumentCache.object( filePath );
109  if ( !xmlDoc )
110  {
111  //then create xml document
112  xmlDoc = new QDomDocument();
113  QString errorMsg;
114  int line, column;
115  if ( !xmlDoc->setContent( &configFile, true, &errorMsg, &line, &column ) )
116  {
117  QgsMessageLog::logMessage( "Error parsing file '" + filePath +
118  QStringLiteral( "': parse error %1 at row %2, column %3" ).arg( errorMsg ).arg( line ).arg( column ), QStringLiteral( "Server" ), Qgis::Critical );
119  delete xmlDoc;
120  return nullptr;
121  }
122  mXmlDocumentCache.insert( filePath, xmlDoc );
123  mFileSystemWatcher.addPath( filePath );
124  xmlDoc = mXmlDocumentCache.object( filePath );
125  Q_ASSERT( xmlDoc );
126  }
127  return xmlDoc;
128 }
129 
130 void QgsConfigCache::removeChangedEntry( const QString &path )
131 {
132  mProjectCache.remove( path );
133 
134  //xml document must be removed last, as other config cache destructors may require it
135  mXmlDocumentCache.remove( path );
136 
137  mFileSystemWatcher.removePath( path );
138 }
139 
140 
141 void QgsConfigCache::removeEntry( const QString &path )
142 {
143  removeChangedEntry( path );
144 }
QMap< QString, QString > badLayerNames() const
Returns names of bad layers with ids.
QStringList badLayers() const
badLayers
void removeEntry(const QString &path)
Removes an entry from cache.
Stores layer ids of bad layers.
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).
Encapsulates a QGIS project, including sets of map layers and their styles, layouts, annotations, canvases, etc.
Definition: qgsproject.h:91
const QgsProject * project(const QString &path)
If the project is not cached yet, then the project is read thanks to the path.
Exception base class for server exceptions.
Cache for server configuration.
static QgsConfigCache * instance()
Returns the current instance.
SERVER_EXPORT QStringList wmsRestrictedLayers(const QgsProject &project)
Returns the restricted layer name list.