| 179 | } |
| 180 | |
| 181 | bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& fullName, |
| 182 | const String& config, const Array::Ptr& errors, const Array::Ptr& diagnosticInformation, const Value& cookie) |
| 183 | { |
| 184 | CreateStorage(); |
| 185 | |
| 186 | { |
| 187 | auto configType (dynamic_cast<ConfigType*>(type.get())); |
| 188 | |
| 189 | if (configType && configType->GetObject(fullName)) { |
| 190 | errors->Add("Object '" + fullName + "' already exists."); |
| 191 | return false; |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | String path; |
| 196 | |
| 197 | try { |
| 198 | path = ComputeNewObjectConfigPath(type, fullName); |
| 199 | } catch (const std::exception& ex) { |
| 200 | errors->Add("Config package broken: " + DiagnosticInformation(ex, false)); |
| 201 | return false; |
| 202 | } |
| 203 | |
| 204 | // AtomicFile doesn't create not yet existing directories, so we have to do it by ourselves. |
| 205 | Utility::MkDirP(Utility::DirName(path), 0700); |
| 206 | |
| 207 | AtomicFile::Write(path, 0644, config); |
| 208 | |
| 209 | // Remove the just created config file in all the error cases and if the object creation |
| 210 | // succeeds the deferred callback will be cancelled. |
| 211 | Defer removeConfigPath([&path]{ |
| 212 | Utility::Remove(path); |
| 213 | }); |
| 214 | |
| 215 | std::unique_ptr<Expression> expr = ConfigCompiler::CompileFile(path, String(), "_api"); |
| 216 | |
| 217 | try { |
| 218 | ActivationScope ascope; |
| 219 | |
| 220 | ScriptFrame frame(true); |
| 221 | expr->Evaluate(frame); |
| 222 | expr.reset(); |
| 223 | |
| 224 | WorkQueue upq; |
| 225 | upq.SetName("ConfigObjectUtility::CreateObject"); |
| 226 | |
| 227 | std::vector<ConfigItem::Ptr> newItems; |
| 228 | |
| 229 | /* |
| 230 | * Disable logging for object creation, but do so ourselves later on. |
| 231 | * Duplicate the error handling for better logging and debugging here. |
| 232 | */ |
| 233 | if (!ConfigItem::CommitItems(ascope.GetContext(), upq, newItems, true)) { |
| 234 | if (errors) { |
| 235 | Log(LogNotice, "ConfigObjectUtility") |
| 236 | << "Failed to commit config item '" << fullName << "'. Aborting and removing config path '" << path << "'."; |
| 237 | |
| 238 | for (const boost::exception_ptr& ex : upq.GetExceptions()) { |
nothing calls this directly
no test coverage detected