diff options
Diffstat (limited to 'filter/source/config/tools/merge')
-rw-r--r-- | filter/source/config/tools/merge/FCFGMerge.cfg | 112 | ||||
-rwxr-xr-x | filter/source/config/tools/merge/pyAltFCFGMerge | 590 |
2 files changed, 702 insertions, 0 deletions
diff --git a/filter/source/config/tools/merge/FCFGMerge.cfg b/filter/source/config/tools/merge/FCFGMerge.cfg new file mode 100644 index 000000000..8a0b4b78f --- /dev/null +++ b/filter/source/config/tools/merge/FCFGMerge.cfg @@ -0,0 +1,112 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright +# ownership. The ASF licenses this file to you under the Apache +# License, Version 2.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 . +# + +#************************************************ +# Specify the verbose mode of this tool. +# 1 = show errors only +# 2 = show errors/warnings (default) +# 3 = show errors/warnings and some generic infos +# 4 = show anything (including detailed infos) +# +# [OPTIONAL] +#************************************************ + +loglevel = 2 + +#************************************************ +# This extension is used for all XML files. It doesn't +# matter if it's used for reading fragments or writing +# XML packages. +# Must be given without any additional signes like "." +# or "*."! +# +# [REQUIRED] +#************************************************ + +extension_xcu=xcu + +#************************************************ +# This extension is used for all Package files. It doesn't +# matter if it's used for reading such files or writing +# it. +# Must be given without any additional signes like "." +# or "*."! +# +# [REQUIRED] +#************************************************ + +extension_pkg=pkg + +#************************************************ +# These values are used to generate a correct XML +# header. +# Note: The property "xmlpackage" must be specified +# via command line. There exists more than one +# possible value. +# +# [REQUIRED] +#************************************************ + +xmlversion = 1.0 +xmlencoding = UTF-8 +xmlpath = org.openoffice.TypeDetection +#xmlpackage = + +#************************************************ +# These values are used to name the configuration +# sets inside the generated XCM file for different +# item groups like e.g. types, filters etcpp. +# +# [REQUIRED] +#************************************************ + +setname_types = Types +setname_filters = Filters +setname_frameloaders = FrameLoaders +setname_contenthandlers = ContentHandlers + +subdir_types = types +subdir_filters = filters +subdir_frameloaders = frameloaders +subdir_contenthandlers = contenthandlers + +#************************************************ +# This delimiter is used to split every +# item list of the package configuration files +# (which are temp. created by the make process) +# into its tokens. +# +# [REQUIRED] +#************************************************ +delimiter=, + +#************************************************ +# Enable/disable removing of leading/trailing whitespaces +# during splitting stringlists. +# +# [REQUIRED] +#************************************************ +trim=true + +#************************************************ +# Enable/disable removing of leading/trailing "-signs +# during splitting stringlists. +# +# [REQUIRED] +#************************************************ +decode=false diff --git a/filter/source/config/tools/merge/pyAltFCFGMerge b/filter/source/config/tools/merge/pyAltFCFGMerge new file mode 100755 index 000000000..7040108e8 --- /dev/null +++ b/filter/source/config/tools/merge/pyAltFCFGMerge @@ -0,0 +1,590 @@ +#!/usr/bin/env python +#_____________________________________________ +# Caolan McNamara caolanm@redhat.com +# converted from original java written by Andreas Schluens so we can continue +# to build 680 OpenOffice.org series without java +# this is not really a replacement for the existing java tool, just the +# minimum required to make it work for now, the existing tool is still +# the canonical base, changes to it will have to be mirrored here until +# there is a java which is available for use by all +#_____________________________________________ + +import sys, string, os.path, codecs + +CFGFILE = os.environ["SRCDIR"] + "/filter/source/config/tools/merge/FCFGMerge.cfg" + +PROP_XMLVERSION = "xmlversion" # // <= global cfg file +PROP_XMLENCODING = "xmlencoding" # // <= global cfg file +PROP_XMLPATH = "xmlpath" # // <= global cfg file +PROP_XMLPACKAGE = "xmlpackage" # // <= global cfg file +PROP_SETNAME_TYPES = "setname_types" # // <= global cfg file +PROP_SETNAME_FILTERS = "setname_filters" # // <= global cfg file +PROP_SETNAME_LOADERS = "setname_frameloaders" # // <= global cfg file +PROP_SETNAME_HANDLERS = "setname_contenthandlers" # // <= global cfg file +PROP_SUBDIR_TYPES = "subdir_types" # // <= global cfg file +PROP_SUBDIR_FILTERS = "subdir_filters" # // <= global cfg file +PROP_SUBDIR_LOADERS = "subdir_frameloaders" # // <= global cfg file +PROP_SUBDIR_HANDLERS = "subdir_contenthandlers" # // <= global cfg file +PROP_EXTENSION_XCU = "extension_xcu" # // <= global cfg file +PROP_EXTENSION_PKG = "extension_pkg" # // <= global cfg file +PROP_DELIMITER = "delimiter" # // <= global cfg file +PROP_TRIM = "trim" # // <= global cfg file +PROP_DECODE = "decode" # // <= global cfg file +PROP_FRAGMENTSDIR = "fragmentsdir" # // <= cmdline +PROP_TEMPDIR = "tempdir" # // <= cmdline +PROP_OUTDIR = "outdir" # // <= cmdline +PROP_PKG = "pkg" # // <= cmdline +PROP_TCFG = "tcfg" # // <= cmdline +PROP_FCFG = "fcfg" # // <= cmdline +PROP_LCFG = "lcfg" # // <= cmdline +PROP_CCFG = "ccfg" # // <= cmdline +PROP_LANGUAGEPACK = "languagepack" # // <= cmdline +PROP_VERBOSE = "verbose" # // <= cmdline +PROP_SHARE_SUBDIR_NAME = "share_subdir_name" # // <= cmdline +PROP_ITEMS = "items" # // <= pkg cfg files! + +#---begin java.util.Properties copy---# +r""" + +An incomplete clean room implementation of +java.util.Properties written in Python. + +Copyright (C) 2002,2004 - Ollie Rutherfurd <oliver@rutherfurd.net> + +Based on: + + http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html + +Missing: + + - Currently, u\XXXX sequences are escaped when saving, but not unescaped + when read... + +License: Python License + +Example Usage: + +>>> from properties import Properties +>>> props = Properties() +>>> props['one'] = '1' +>>> props['your name'] = "I don't know" +>>> print('\n'.join(list(props.keys()))) +your name +one +>>> from StringIO import StringIO +>>> buff = StringIO() +>>> props.store(buff, "a little example...") +>>> buff.seek(0) +>>> print(buff.read()) +# a little example... +your\ name=I\ don\'t\ know +one=1 +>>> print(props['your name']) +I don't know + +$Id: pyAltFCFGMerge,v 1.3 2007-12-07 10:57:44 vg Exp $ + +""" + +__all__ = ['Properties'] + + +def dec2hex(n): + h = hex(n)[2:].upper() + return '\\u' + '0' * (4 - len(h)) + h + + +def escapestr(s): + buff = [] + # QUESTION: escape leading or trailing spaces? + for c in s: + if c == '\\': + buff.append('\\\\') + elif c == '\t': + buff.append('\\t') + elif c == '\n': + buff.append('\\n') + elif c == '\r': + buff.append('\\r') + elif c == ' ': + buff.append('\\ ') + elif c == "'": + buff.append("\\'") + elif c == '"': + buff.append('\\"') + elif c == '#': + buff.append('\\#') + elif c == '!': + buff.append('\\!') + elif c == '=': + buff.append('\\=') + elif 32 <= ord(c) <= 126: + buff.append(c) + else: + buff.append(dec2hex(c)) + + return ''.join(buff) + + +# TODO: add support for \uXXXX? +def unescapestr(line): + buff = [] + escape = 0 + for i in range(len(line)): + c = line[i] + if c == '\\': + if escape: + escape = 0 + buff.append('\\') + continue + else: + # this is to deal with '\' + # acting as a line continuation + # character + if i == len(line) - 1: + buff.append('\\') + break + else: + escape = 1 + continue + elif c == 'n': + if escape: + escape = 0 + buff.append('\n') + continue + elif c == 'r': + if escape: + escape = 0 + buff.append('\r') + continue + elif c == 't': + if escape: + escape = 0 + buff.append('\t') + continue + + buff.append(c) + + # make sure escape doesn't stay one + # all expected escape sequences either break + # or continue, so this should be safe + if escape: + escape = 0 + + return ''.join(buff) + + +class Properties(dict): + def __init__(self, defaults={}): + dict.__init__(self) + for n,v in list(defaults.items()): + self[n] = v + + def __getittem__(self,key): + try: + return dict.__getittem__(self,key) + except KeyError: + return None + + def read(self,filename): + """ + Reads properties from a file (java Property class + reads from an input stream -- see load()). + """ + f = None + try: + f = open(filename) + self.load(f) + finally: + if f: + f.close() + + def load(self, buff): + """ + Reads properties from a stream (StringIO, file, etc...) + """ + props = readprops(buff) + for n,v in list(props.items()): + self[n] = v + +def readprops(buff): + name,value = None,'' + props = {} + continued = 0 + + while 1: + line = buff.readline() + if not line: + break + line = line.strip() + + # empty line + if not line: + continue + + # comment + if line[0] in ('#','!'): + continue + + # find name + i,escaped = 0,0 + while i < len(line): + c = line[i] + + if c == '\\': + if escaped: + escaped = 0 + else: + escaped = 1 + i += 1 + continue + + elif c in (' ', '\t', ':', '=') and not escaped: + name = unescapestr(line[:i]) + break + + # make sure escaped doesn't stay on + if escaped: + escaped = 0 + + i += 1 + + # no delimiter was found, name is entire line, there is no value + if name is None: + name = unescapestr(line.lstrip()) + + # skip delimiter + while line[i:i + 1] in ('\t', ' ', ':', '='): + i += 1 + + value = unescapestr(line[i:].strip()) + while value[-1:] == '\\': + value = value[:-1] # remove \ + line = buff.readline() + if not line: + break + value += unescapestr(line.strip()) + + props[name] = value + + return props +#---end java.util.Properties copy---# + +# It's a simple command line tool, which can merge different XML fragments +# together. Such fragments must exist as files on disk, will be moved into +# one file together on disk. + +def run(sCmdLine): + aCfg = ConfigHelper(CFGFILE, sCmdLine) + if aCfg.getValueWithDefault(PROP_VERBOSE,None) == None: + sys.stdout=None + + printCopyright() + + # help requested? + if aCfg.isHelp(): + printHelp() + sys.exit(-1) + + #create new merge object and start operation + aMerger = Merger(aCfg) + aMerger.merge() + + sys.exit(0) + +def printOut(s): + if sys.stdout is None: + return + print(s) + +#prints out a copyright message on stdout. +def printCopyright(): + printOut("FCFGMerge") + printOut("Copyright: 2003 by Red Hat, Inc., based on FCFGMerge.java` by Sun") + printOut("All Rights Reserved.") + +# Prints out a help message on stdout. +def printHelp(): + printOut("____________________________________________________________") + printOut("usage: FCFGMerge cfg=<file name>" ) + printOut("parameters:" ) + printOut("\tcfg=<file name>" ) + printOut("\t\tmust point to a system file, which contains" ) + printOut("\t\tall necessary configuration data for the merge process.") + printOut("\tFurther cou can specify every parameter allowed in the" ) + printOut("\tconfig file as command line parameter too, to overwrite" ) + printOut("\tthe value from the file." ) + +# Return a list of tokens given a base string and a string of +# separators, optionally including the separators if asked for""" +def StringTokenizer(mstring, separators, isSepIncluded = 0): + token = '' + tokenList = [] + for c in mstring: + if c in separators: + if token != '': + tokenList.append(token) + token = '' + if isSepIncluded: + tokenList.append(c) + else: + token += c + if token: + tokenList.append(token) + return tokenList + +# Can be used to analyze command line parameters +# and merge it together with might existing config +# files. That provides the possibility to overwrite +# config values via command line parameter. + +class ConfigHelper: + def __init__(self, sPropFile, lCommandLineArgs): + self.m_bEmpty = 1 + # first load prop file, so its values can be overwritten + # by command line args later + # Do it only, if a valid file name was given. + # But in case this file name is wrong, throw an exception. + # So the outside code can react! + if sPropFile is not None and len(sPropFile) > 0: + self.props = Properties() + self.props.read(sPropFile) + + count = 0 + if lCommandLineArgs is not None: + count = len(lCommandLineArgs) + self.m_bEmpty = (count < 1) + + # printOut(lCommandLineArgs, "and len is", count) + for arg in range(count): + # is it a named-value argument? + # Note: we ignore double "=" signs! => search from left to right + pos = lCommandLineArgs[arg].find('=') + if pos != -1: + sArg = lCommandLineArgs[arg][0:pos] + sValue = lCommandLineArgs[arg][pos + 1:] + self.props[sArg] = sValue + continue + + # is it a boolean argument? + # Note: Because "--" and "-" will be interpreted as the same + # we search from right to left! + pos = lCommandLineArgs[arg].rfind('-') + if pos == -1: + pos = lCommandLineArgs[arg].rfind('/') + if pos != -1: + sArg = lCommandLineArgs[arg][pos + 1:] + self.props[sArg] = 1 + continue + + raise Exception("Invalid command line detected. The argument \"" + \ + lCommandLineArgs[arg] + "\" use an unsupported format.") + + def isHelp(self): + return ("help" in self.props) or ("?" in self.props) or ("?" in self.props) + + def getValue(self, sProp): + if sProp not in self.props: + raise Exception("The requested config value \"" + sProp + "\" "\ + "does not exists!"); + return self.props[sProp]; + + def getValueWithDefault(self, sProp, default): + if sProp not in self.props: + return default; + return self.props[sProp]; + + def getStringList(self, sProp, sDelimiter, bTrim, bDecode): + if sProp not in self.props: + raise Exception("The requested config value \"" + sProp + "\" does "\ + "not exists!"); + sValue = self.props[sProp] + + lValue = [] + lTokens = StringTokenizer(sValue, sDelimiter) + for sToken in lTokens: + if bTrim: + sToken = sToken.strip() + # remove "" + if ((bDecode) and (sToken.find("\"") == 0) and \ + (sToken.rfind("\"") == len(sToken) - 1)): + sToken = sToken[1, len(sToken) - 1] + lValue.append(sToken) + + return lValue + +def generateHeader(sVersion, sEncoding, sPath, sPackage, bLanguagePack): + sHeader = "<?xml version=\"" + sHeader += sVersion + sHeader += "\" encoding=\"" + sHeader += sEncoding + sHeader += "\"?>\n" + + if bLanguagePack: + sHeader += "<oor:component-data oor:package=\"" + sHeader += sPath + sHeader += "\" oor:name=\"" + sHeader += sPackage + sHeader += "\" xmlns:install=\"http://openoffice.org/2004/installation\"" + sHeader += " xmlns:oor=\"http://openoffice.org/2001/registry\"" + sHeader += " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" + sHeader += " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" + else: + sHeader += "<oor:component-data xmlns:oor=\"http://openoffice.org/2001/registry\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" oor:package=\"" + sHeader += sPath + sHeader += "\" oor:name=\"" + sHeader += sPackage + sHeader += "\">\n" + return sHeader + +def generateFooter(): + return "</oor:component-data>\n" + +# Can merge different xml fragments together. + +class Merger: + def __init__(self, aCfg): + self.m_aCfg = aCfg + + self.m_aFragmentsDir = self.m_aCfg.getValue(PROP_FRAGMENTSDIR) + + sDelimiter = self.m_aCfg.getValue(PROP_DELIMITER) + bTrim = self.m_aCfg.getValue(PROP_TRIM) + bDecode = self.m_aCfg.getValue(PROP_DECODE) + + try: + aFcfg = ConfigHelper(self.m_aCfg.getValue(PROP_TCFG), None) + self.m_lTypes = aFcfg.getStringList(PROP_ITEMS, sDelimiter, bTrim, bDecode) + except: + self.m_lTypes = [] + + try: + aFcfg = ConfigHelper(self.m_aCfg.getValue(PROP_FCFG), None) + self.m_lFilters = aFcfg.getStringList(PROP_ITEMS, sDelimiter, bTrim, bDecode) + except: + self.m_lFilters = [] + + try: + aFcfg = ConfigHelper(self.m_aCfg.getValue(PROP_LCFG), None) + self.m_lLoaders = aFcfg.getStringList(PROP_ITEMS, sDelimiter, bTrim, bDecode) + except: + self.m_lLoaders = [] + + try: + aFcfg = ConfigHelper(self.m_aCfg.getValue(PROP_CCFG), None) + self.m_lHandlers = aFcfg.getStringList(PROP_ITEMS, sDelimiter, bTrim, bDecode) + except: + self.m_lHandlers = [] + + # Merges the xml sets returned by getFragments(...), adds an xml header + # and footer and writes the result to a file. + def merge(self): + sPackage = self.m_aCfg.getValue(PROP_PKG) + + printOut("create package \"" + sPackage + "\" ...") + printOut("generate package header ... ") + + sBuffer = generateHeader(\ + self.m_aCfg.getValue(PROP_XMLVERSION ),\ + self.m_aCfg.getValue(PROP_XMLENCODING),\ + self.m_aCfg.getValue(PROP_XMLPATH ),\ + self.m_aCfg.getValue(PROP_XMLPACKAGE ),\ + self.m_aCfg.getValueWithDefault(PROP_LANGUAGEPACK, False)) + + # counts all transferred fragments + # Can be used later to decide, if a generated package file + # contains "nothing"! + nItemCount = 0 + + for i in range(4): + sSetName = None + sSubDir = None + lFragments = None + + try: + if i == 0: # types + printOut("generate set for types ... ") + sSetName = self.m_aCfg.getValue(PROP_SETNAME_TYPES) + sSubDir = self.m_aCfg.getValue(PROP_SUBDIR_TYPES) + lFragments = self.m_lTypes + elif i == 1: # filters + printOut("generate set for filter ... ") + sSetName = self.m_aCfg.getValue(PROP_SETNAME_FILTERS) + sSubDir = self.m_aCfg.getValue(PROP_SUBDIR_FILTERS) + lFragments = self.m_lFilters + elif i == 2: # loaders + printOut("generate set for frame loader ... ") + sSetName = self.m_aCfg.getValue(PROP_SETNAME_LOADERS) + sSubDir = self.m_aCfg.getValue(PROP_SUBDIR_LOADERS) + lFragments = self.m_lLoaders + elif i == 3: # handlers + printOut("generate set for content handler ... ") + sSetName = self.m_aCfg.getValue(PROP_SETNAME_HANDLERS) + sSubDir = self.m_aCfg.getValue(PROP_SUBDIR_HANDLERS) + lFragments = self.m_lHandlers + except: + continue + + nItemCount = nItemCount + len(lFragments) + + sBuffer = sBuffer + self.getFragments(\ + os.path.join(self.m_aFragmentsDir, sSubDir), \ + sSetName, lFragments, 1) + + printOut("generate package footer ... ") + sBuffer = sBuffer + generateFooter() + + # Attention! + # If the package seem to be empty, it makes no sense to generate a + # corresponding xml file. We should suppress writing of this file on + # disk completely ... + if nItemCount < 1: + printOut("Package is empty and will not result into a xml file on "\ + "disk!? Please check configuration file.") + return + printOut("package contains " + str(nItemCount) + " items") + + aPackage = codecs.open(sPackage, 'w', "utf-8") + printOut("write temp package \"" + sPackage) + aPackage.write(sBuffer) + aPackage.close() + + # Reads the fragment files with the file names lFragments in directory aDir, + # formats them and returns a string that contains the merged fragments. + def getFragments(self, aDir, sSetName, lFragments, nPrettyTabs): + sBuffer = '' + sExtXcu = self.m_aCfg.getValue(PROP_EXTENSION_XCU); + sShareSubdirName = self.m_aCfg.getValue(PROP_SHARE_SUBDIR_NAME) + if len(sShareSubdirName) < 1: + raise Exception("no share subdir set") + + if len(lFragments) < 1: + return sBuffer + + for tabs in range(nPrettyTabs): + sBuffer = sBuffer + "\t" + sBuffer = sBuffer + "<node oor:name=\"" + sSetName + "\">\n" + nPrettyTabs = nPrettyTabs + 1 + + for sFragment in lFragments: + sFragPath = os.path.join(aDir, sFragment + "." + sExtXcu) + try: + aFragmentFile = codecs.open(sFragPath, "r", "utf-8") + except: + # handle simple files only and check for existence! + raise Exception("fragment \"" + sFragPath + "\" does not exists.") + printOut("merge fragment \"" + sFragPath + "\" ...") + data = aFragmentFile.read() + aFragmentFile.close() + data = data.replace("$(share_subdir_name)", sShareSubdirName) + sBuffer = sBuffer + data + sBuffer = sBuffer + "\n" + + nPrettyTabs = nPrettyTabs - 1 + for tabs in range(nPrettyTabs): + sBuffer = sBuffer + "\t" + sBuffer = sBuffer + "</node>\n" + return sBuffer + +run(sys.argv) + |