generate_pom.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. import sys
  2. import xml.etree.ElementTree as et
  3. import argparse
  4. import os
  5. import json
  6. import base64
  7. import re
  8. DEFAULT_YANDEX_GROUP_ID = 'ru.yandex'
  9. DEFAULT_NAMESPACE = 'http://maven.apache.org/POM/4.0.0'
  10. XSI_NAMESPACE = 'http://www.w3.org/2001/XMLSchema-instance'
  11. SCHEMA_LOCATION = 'http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd'
  12. MODEL_VERSION = '4.0.0'
  13. MAVEN_PLUGIN_GROUP_ID = 'org.apache.maven.plugins'
  14. MAVEN_PLUGIN_ARTIFACT_ID = 'maven-compiler-plugin'
  15. MAVEN_PLUGIN_VERSION = '3.3'
  16. JAVA_LANGUAGE_LEVEL = '1.8'
  17. MAVEN_BUILD_HELPER_GROUP_ID = 'org.codehaus.mojo'
  18. MAVEN_BUILD_HELPER_ARTIFACT_ID = 'build-helper-maven-plugin'
  19. MAVEN_BUILD_HELPER_VERSION = '1.9.1'
  20. MAVEN_EXEC_GROUP_ID = 'org.codehaus.mojo'
  21. MAVEN_EXEC_ARTIFACT_ID = 'exec-maven-plugin'
  22. MAVEN_EXEC_VERSION = '1.5.0'
  23. MAVEN_SUREFIRE_GROUP_ID = 'org.apache.maven.plugins'
  24. MAVEN_SUREFIRE_ARTIFACT_ID = 'maven-surefire-plugin'
  25. MAVEN_SUREFIRE_VERSION = '2.12.2'
  26. def target_from_contrib(target_path):
  27. return target_path.startswith('contrib')
  28. def split_artifacts(s):
  29. m = re.match('^([^:]*:[^:]*:[^:]*:[^:]*)(.*)$', s)
  30. if not m or not m.groups():
  31. return []
  32. if not m.groups()[1].startswith('::'):
  33. return [m.groups()[0]]
  34. return [m.groups()[0]] + m.groups()[1].split('::')[1:]
  35. def build_pom_and_export_to_maven(**kwargs):
  36. target_path = kwargs.get('target_path')
  37. target = kwargs.get('target')
  38. pom_path = kwargs.get('pom_path')
  39. source_dirs = kwargs.get('source_dirs')
  40. output_dir = kwargs.get('output_dir')
  41. final_name = kwargs.get('final_name')
  42. packaging = kwargs.get('packaging')
  43. target_dependencies = kwargs.get('target_dependencies')
  44. test_target_dependencies = kwargs.get('test_target_dependencies')
  45. test_target_dependencies_exclude = kwargs.get('test_target_dependencies_exclude')
  46. modules_path = kwargs.get('modules_path')
  47. prop_vars = kwargs.get('properties')
  48. external_jars = kwargs.get('external_jars')
  49. resources = kwargs.get('resources')
  50. run_java_programs = [json.loads(base64.b64decode(i)) for i in kwargs.get('run_java_programs')]
  51. test_source_dirs = kwargs.get('test_source_dirs')
  52. test_resource_dirs = kwargs.get('test_resource_dirs')
  53. modules = []
  54. def _indent(elem, level=0):
  55. ind = "\n" + level * " "
  56. if len(elem):
  57. if not elem.text or not elem.text.strip():
  58. elem.text = ind + " "
  59. if not elem.tail or not elem.tail.strip():
  60. elem.tail = ind
  61. for elem in elem:
  62. _indent(elem, level + 1)
  63. if not elem.tail or not elem.tail.strip():
  64. elem.tail = ind
  65. else:
  66. if level and (not elem.tail or not elem.tail.strip()):
  67. elem.tail = ind
  68. project = et.Element(
  69. '{}{}{}project'.format('{', DEFAULT_NAMESPACE, '}'),
  70. attrib={'{}{}{}schemaLocation'.format('{', XSI_NAMESPACE, '}'): SCHEMA_LOCATION}
  71. )
  72. group_id, artifact_id, version = target.split(':')
  73. et.SubElement(project, 'modelVersion').text = MODEL_VERSION
  74. et.SubElement(project, 'groupId').text = group_id
  75. et.SubElement(project, 'artifactId').text = artifact_id
  76. et.SubElement(project, 'version').text = version
  77. et.SubElement(project, 'packaging').text = packaging
  78. properties = et.SubElement(project, 'properties')
  79. et.SubElement(properties, 'project.build.sourceEncoding').text = 'UTF-8'
  80. if prop_vars:
  81. for property, value in json.loads(base64.b64decode(prop_vars)).items():
  82. et.SubElement(properties, property).text = value
  83. if modules_path:
  84. with open(modules_path) as f:
  85. modules = [i.strip() for i in f if i.strip()]
  86. if modules:
  87. modules_el = et.SubElement(project, 'modules')
  88. for module in modules:
  89. et.SubElement(modules_el, 'module').text = module
  90. build = et.SubElement(project, 'build')
  91. if source_dirs:
  92. et.SubElement(build, 'sourceDirectory').text = source_dirs[0]
  93. source_dirs = source_dirs[1:]
  94. if test_source_dirs:
  95. et.SubElement(build, 'testSourceDirectory').text = test_source_dirs[0]
  96. test_source_dirs = test_source_dirs[1:]
  97. if output_dir:
  98. et.SubElement(build, 'outputDirectory').text = output_dir
  99. if final_name:
  100. et.SubElement(build, 'finalName').text = final_name
  101. if resources:
  102. resource_element = et.SubElement(et.SubElement(build, 'resources'), 'resource')
  103. et.SubElement(resource_element, 'directory').text = '${basedir}'
  104. includes = et.SubElement(resource_element, 'includes')
  105. for resource in resources:
  106. et.SubElement(includes, 'include').text = resource
  107. if test_resource_dirs:
  108. test_resource_element = et.SubElement(build, 'testResources')
  109. for test_resource_dir in test_resource_dirs:
  110. et.SubElement(et.SubElement(test_resource_element, 'testResource'), 'directory').text = '${basedir}' + (('/' + test_resource_dir) if test_resource_dir != '.' else '')
  111. plugins = et.SubElement(build, 'plugins')
  112. if packaging != 'pom':
  113. maven_plugin = et.SubElement(plugins, 'plugin')
  114. et.SubElement(maven_plugin, 'groupId').text = MAVEN_PLUGIN_GROUP_ID
  115. et.SubElement(maven_plugin, 'artifactId').text = MAVEN_PLUGIN_ARTIFACT_ID
  116. et.SubElement(maven_plugin, 'version').text = MAVEN_PLUGIN_VERSION
  117. configuration = et.SubElement(maven_plugin, 'configuration')
  118. et.SubElement(configuration, 'source').text = JAVA_LANGUAGE_LEVEL
  119. et.SubElement(configuration, 'target').text = JAVA_LANGUAGE_LEVEL
  120. if source_dirs or external_jars or test_source_dirs:
  121. build_helper_plugin = et.SubElement(plugins, 'plugin')
  122. et.SubElement(build_helper_plugin, 'groupId').text = MAVEN_BUILD_HELPER_GROUP_ID
  123. et.SubElement(build_helper_plugin, 'artifactId').text = MAVEN_BUILD_HELPER_ARTIFACT_ID
  124. et.SubElement(build_helper_plugin, 'version').text = MAVEN_BUILD_HELPER_VERSION
  125. executions = et.SubElement(build_helper_plugin, 'executions')
  126. if source_dirs:
  127. execution = et.SubElement(executions, 'execution')
  128. et.SubElement(execution, 'id').text = 'add-source'
  129. et.SubElement(execution, 'phase').text = 'generate-sources'
  130. et.SubElement(et.SubElement(execution, 'goals'), 'goal').text = 'add-source'
  131. sources = et.SubElement(et.SubElement(execution, 'configuration'), 'sources')
  132. for source_dir in source_dirs:
  133. et.SubElement(sources, 'source').text = source_dir
  134. if external_jars:
  135. execution = et.SubElement(executions, 'execution')
  136. et.SubElement(execution, 'id').text = 'attach-artifacts'
  137. et.SubElement(execution, 'phase').text = 'generate-sources'
  138. et.SubElement(et.SubElement(execution, 'goals'), 'goal').text = 'attach-artifact'
  139. artifacts = et.SubElement(et.SubElement(execution, 'configuration'), 'artifacts')
  140. for external_jar in external_jars:
  141. external_artifact = et.SubElement(artifacts, 'artifact')
  142. et.SubElement(external_artifact, 'file').text = '${basedir}/' + external_jar
  143. et.SubElement(external_artifact, 'type').text = 'jar'
  144. if test_source_dirs:
  145. execution = et.SubElement(executions, 'execution')
  146. et.SubElement(execution, 'id').text = 'add-test-source'
  147. et.SubElement(execution, 'phase').text = 'generate-test-sources'
  148. et.SubElement(et.SubElement(execution, 'goals'), 'goal').text = 'add-test-source'
  149. sources = et.SubElement(et.SubElement(execution, 'configuration'), 'sources')
  150. for source_dir in source_dirs:
  151. et.SubElement(sources, 'source').text = source_dir
  152. if run_java_programs:
  153. exec_plugin = et.SubElement(plugins, 'plugin')
  154. et.SubElement(exec_plugin, 'groupId').text = MAVEN_EXEC_GROUP_ID
  155. et.SubElement(exec_plugin, 'artifactId').text = MAVEN_EXEC_ARTIFACT_ID
  156. et.SubElement(exec_plugin, 'version').text = MAVEN_EXEC_VERSION
  157. jp_dependencies = et.SubElement(exec_plugin, 'dependencies')
  158. executions = et.SubElement(exec_plugin, 'executions')
  159. for java_program in run_java_programs:
  160. execution = et.SubElement(executions, 'execution')
  161. et.SubElement(execution, 'phase').text = 'generate-sources'
  162. et.SubElement(et.SubElement(execution, 'goals'), 'goal').text = 'java'
  163. jp_configuration = et.SubElement(execution, 'configuration')
  164. main_cls, args = None, []
  165. for word in java_program['cmd']:
  166. if not main_cls and not word.startswith('-'):
  167. main_cls = word
  168. else:
  169. args.append(word)
  170. et.SubElement(jp_configuration, 'mainClass').text = main_cls
  171. et.SubElement(jp_configuration, 'includePluginDependencies').text = 'true'
  172. et.SubElement(jp_configuration, 'includeProjectDependencies').text = 'false'
  173. if args:
  174. jp_arguments = et.SubElement(jp_configuration, 'arguments')
  175. for arg in args:
  176. et.SubElement(jp_arguments, 'argument').text = arg
  177. if java_program['deps']:
  178. for jp_dep in java_program['deps']:
  179. jp_dependency = et.SubElement(jp_dependencies, 'dependency')
  180. jp_g, jp_a, jp_v = jp_dep.split(':')
  181. et.SubElement(jp_dependency, 'groupId').text = jp_g
  182. et.SubElement(jp_dependency, 'artifactId').text = jp_a
  183. et.SubElement(jp_dependency, 'version').text = jp_v
  184. et.SubElement(jp_dependency, 'type').text = 'jar'
  185. if target_dependencies + test_target_dependencies:
  186. dependencies = et.SubElement(project, 'dependencies')
  187. for target_dependency in target_dependencies + test_target_dependencies:
  188. dependency = et.SubElement(dependencies, 'dependency')
  189. dependency_info = split_artifacts(target_dependency)
  190. group_id, artifact_id, version, classifier = dependency_info[0].split(':')
  191. et.SubElement(dependency, 'groupId').text = group_id
  192. et.SubElement(dependency, 'artifactId').text = artifact_id
  193. et.SubElement(dependency, 'version').text = version
  194. if classifier:
  195. et.SubElement(dependency, 'classifier').text = classifier
  196. if target_dependency in test_target_dependencies:
  197. et.SubElement(dependency, 'scope').text = 'test'
  198. if len(dependency_info) > 1:
  199. exclusions = et.SubElement(dependency, 'exclusions')
  200. for exclude in dependency_info[1:]:
  201. group_id, artifact_id = exclude.split(':')
  202. exclusion_el = et.SubElement(exclusions, 'exclusion')
  203. et.SubElement(exclusion_el, 'groupId').text = group_id
  204. et.SubElement(exclusion_el, 'artifactId').text = artifact_id
  205. if test_target_dependencies_exclude:
  206. surefire_plugin = et.SubElement(plugins, 'plugin')
  207. et.SubElement(surefire_plugin, 'groupId').text = MAVEN_SUREFIRE_GROUP_ID
  208. et.SubElement(surefire_plugin, 'artifactId').text = MAVEN_SUREFIRE_ARTIFACT_ID
  209. et.SubElement(surefire_plugin, 'version').text = MAVEN_SUREFIRE_VERSION
  210. classpath_excludes = et.SubElement(et.SubElement(surefire_plugin, 'configuration'), 'classpathDependencyExcludes')
  211. for classpath_exclude in test_target_dependencies_exclude:
  212. et.SubElement(classpath_excludes, 'classpathDependencyExclude').text = classpath_exclude
  213. et.register_namespace('', DEFAULT_NAMESPACE)
  214. et.register_namespace('xsi', XSI_NAMESPACE)
  215. _indent(project)
  216. et.ElementTree(project).write(pom_path)
  217. sys.stderr.write("[MAVEN EXPORT] Generated {} file for target {}\n".format(os.path.basename(pom_path), target_path))
  218. if __name__ == '__main__':
  219. parser = argparse.ArgumentParser()
  220. parser.add_argument('--target-path', action='store', default='')
  221. parser.add_argument('--target', action='store')
  222. parser.add_argument('--pom-path', action='store')
  223. parser.add_argument('--source-dirs', action='append', default=[])
  224. parser.add_argument('--external-jars', action='append', default=[])
  225. parser.add_argument('--resources', action='append', default=[])
  226. parser.add_argument('--run-java-programs', action='append', default=[])
  227. parser.add_argument('--output-dir')
  228. parser.add_argument('--final-name')
  229. parser.add_argument('--packaging', default='jar')
  230. parser.add_argument('--target-dependencies', action='append', default=[])
  231. parser.add_argument('--test-target-dependencies', action='append', default=[])
  232. parser.add_argument('--test-target-dependencies-exclude', action='append', default=[])
  233. parser.add_argument('--modules-path', action='store')
  234. parser.add_argument('--properties')
  235. parser.add_argument('--test-source-dirs', action='append', default=[])
  236. parser.add_argument('--test-resource-dirs', action='append', default=[])
  237. args = parser.parse_args()
  238. build_pom_and_export_to_maven(**vars(args))