'Scan layers xml and see if there are external references.
Find references to data outside data dir and include them in
backup. Also, some references may point to specific url, which
may not be available later.'

def dump_geoserver_externals(self, config, settings, target_folder):

    external_folder = os.path.join(target_folder, helpers.EXTERNAL_ROOT)
    def copy_external_resource(abspath):
        external_path = os.path.join(external_folder, abspath[1:])
        external_dir = os.path.dirname(external_path)
        if (not os.path.isdir(external_dir)):
            os.makedirs(external_dir)
        shutil.copy(abspath, external_path)
    def match_filename(key, text, regexp=re.compile('^(.+)$')):
        if (key in ('filename',)):
            match = regexp.match(text)
            if match:
                relpath = match.group(1)
                abspath = (relpath if os.path.isabs(relpath) else os.path.abspath(os.path.join(os.path.dirname(path), relpath)))
                if os.path.exists(abspath):
                    return abspath
    def match_fileurl(key, text, regexp=re.compile('^file:(.+)$')):
        if (key in ('url',)):
            match = regexp.match(text)
            if match:
                relpath = match.group(1)
                abspath = (relpath if os.path.isabs(relpath) else os.path.abspath(os.path.join(config.gs_data_dir, relpath)))
                if os.path.exists(abspath):
                    return abspath
    def dump_external_resources_from_xml(path):
        def find_external(tree, key=None):
            if isinstance(tree, dict):
                for (key, value) in tree.iteritems():
                    for found in find_external(value, key=key):
                        (yield found)
            elif isinstance(tree, list):
                for item in tree:
                    for found in find_external(item, key=key):
                        (yield found)
            elif isinstance(tree, unicode):
                text = tree.encode('utf-8')
                for find in (match_fileurl, match_filename):
                    found = find(key, text)
                    if found:
                        (yield found)
        with open(path) as fd:
            content = fd.read()
            tree = parse_xml(content)
            for found in find_external(tree):
                if (found.find(config.gs_data_dir) != 0):
                    copy_external_resource(found)
    def is_xml_file(filename, regexp=re.compile('.*.xml$')):
        return (regexp.match(filename) is not None)
    for directory in ('workspaces', 'styles'):
        source = os.path.join(config.gs_data_dir, directory)
        for (root, dirs, files) in os.walk(source):
            for filename in filter(is_xml_file, files):
                path = os.path.join(root, filename)
                dump_external_resources_from_xml(path)
