ConfigObject parse()

in src/main/groovy/groovy/util/ConfigSlurper.groovy [186:296]


    ConfigObject parse(Script script, URL location) {
        Stack<String> currentConditionalBlock = new Stack<String>()
        def config = location ? new ConfigObject(location) : new ConfigObject()
        GroovySystem.metaClassRegistry.removeMetaClass(script.class)
        def mc = script.class.metaClass
        def prefix = ''
        LinkedList stack = new LinkedList()
        stack << [config: config, scope: [:]]
        def pushStack = { co ->
            stack << [config: co, scope: stack.last.scope.clone()]
        }
        def assignName = { name, co ->
            def current = stack.last
            current.config[name] = co
            current.scope[name] = co
        }
        mc.getProperty = { String name ->
            def current = stack.last
            def result
            if (current.config.get(name)) {
                result = current.config.get(name)
            } else if (current.scope[name]) {
                result = current.scope[name]
            } else {
                try {
                    result = InvokerHelper.getProperty(this, name)
                } catch (GroovyRuntimeException e) {
                    result = new ConfigObject()
                    assignName.call(name, result)
                }
            }
            result
        }

        ConfigObject overrides = new ConfigObject()
        mc.invokeMethod = { String name, args ->
            def result
            if (args.length == 1 && args[0] instanceof Closure) {
                if (name in conditionValues.keySet()) {
                    try {
                        currentConditionalBlock.push(name)
                        conditionalBlocks.push([:])
                        args[0].call()
                    } finally {
                        currentConditionalBlock.pop()
                        for (entry in conditionalBlocks.pop().entrySet()) {
                            def c = stack.last.config
                            (c != config? c : overrides).merge(entry.value)
                        }
                    }
                } else if (currentConditionalBlock.size() > 0) {
                    String conditionalBlockKey = currentConditionalBlock.peek()
                    if (name == conditionValues[conditionalBlockKey]) {
                        def co = new ConfigObject()
                        conditionalBlocks.peek()[conditionalBlockKey] = co

                        pushStack.call(co)
                        try {
                            currentConditionalBlock.pop()
                            args[0].call()
                        } finally {
                            currentConditionalBlock.push(conditionalBlockKey)
                        }
                        stack.removeLast()
                    }
                } else {
                    def co
                    if (stack.last.config.get(name) instanceof ConfigObject) {
                        co = stack.last.config.get(name)
                    } else {
                        co = new ConfigObject()
                    }

                    assignName.call(name, co)
                    pushStack.call(co)
                    args[0].call()
                    stack.removeLast()
                }
            } else if (args.length == 2 && args[1] instanceof Closure) {
                try {
                    prefix = name + '.'
                    assignName.call(name, args[0])
                    args[1].call()
                } finally { prefix = '' }
            } else {
                MetaMethod mm = mc.getMetaMethod(name, args)
                if (mm) {
                    result = mm.invoke(delegate, args)
                } else {
                    throw new MissingMethodException(name, getClass(), args)
                }
            }
            result
        }
        script.metaClass = mc

        def setProperty = { String name, value ->
            assignName.call(prefix + name, value)
        }
        def binding = new ConfigBinding(setProperty)
        if (this.bindingVars) {
            binding.variables.putAll(this.bindingVars)
        }
        script.binding = binding

        script.run()

        config.merge(overrides)

        config
    }