blob: 30f6edf654d1204ac90f237c8aa9abfa40eaf5b7 [file] [log] [blame]
Brian O'Connor1f165982016-04-06 21:36:09 -07001#!/usr/bin/env python
2#FIXME Add license
3
4##### Templates for features.xml
5FEATURES_HEADER = '''\
6<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
7<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
8 name="%(feature_repo_name)s">
9'''
10FEATURE_HEADER= '''\
11 <feature name="%(feature_name)s" version="%(version)s"
12 description="%(title)s">
13'''
14EXISTING_FEATURE = ' <feature>%s</feature>\n'
15BUNDLE = ' <bundle>%s</bundle>\n'
16FEATURE_FOOTER = ' </feature>\n'
17FEATURES_FOOTER = '</features>'
18
19##### Templates for app.xml
20APP_HEADER = '''\
21<?xml version="1.0" encoding="UTF-8"?>
22<app name="%(app_name)s" origin="%(origin)s" version="%(version)s"
23 title="%(title)s" category="%(category)s" url="%(url)s"
24 featuresRepo="%(feature_repo_name)s"
25 features="%(feature_name)s" apps="%(apps)s">
26 <description>%(description)s</description>
27'''
28ARTIFACT = ' <artifact>%s</artifact>\n'
29APP_FOOTER = '</app>'
30
Brian O'Connorbd6305a2016-04-25 14:28:12 -070031NON_OSGI_TAG = 'NON-OSGI'
Brian O'Connor1f165982016-04-06 21:36:09 -070032
33def mvnUrl(bundle):
Brian O'Connorbd6305a2016-04-25 14:28:12 -070034 #mvn-uri := 'mvn:' [ repository-url '!' ] group-id '/' artifact-id [ '/' [version] [ '/' [type] [ '/' classifier ] ] ] ]
35 parts = bundle.split(':')
36 prefix = 'mvn:'
37 suffix = ''
38 if len(parts) > 3:
39 parts.insert(2, parts.pop()) # move version to the 3rd position
40 if len(parts) >= 5:
41 # check classifier for special non-OSGi tag
42 i = parts[4].find(NON_OSGI_TAG)
43 if i == 0:
44 prefix = 'wrap:' + prefix
45 suffix = '$Bundle-SymbolicName=%s.%s&amp;Bundle-Version=%s' % tuple(parts[0:3])
46 if len(parts[4]) == len(NON_OSGI_TAG):
47 parts.pop() # pop off empty classifier
48 if parts[3].lower() == 'jar':
49 parts.pop() # pop off default extension: jar
50 else:
51 parts[4] = parts[4][len(NON_OSGI_TAG):]
52 return prefix + '/'.join(parts) + suffix
Brian O'Connor1f165982016-04-06 21:36:09 -070053
54def generateFeatureFile(feature_name,
55 version,
56 title,
57 feature_repo_name,
58 features = [],
59 bundles = [],
60 **kwargs):
61 values = {
62 'feature_name' : feature_name,
63 'version' : version,
64 'title' : title,
65 'feature_repo_name' : '-'.join(feature_repo_name.split(':')[1:3]),
66 }
67
68 output = FEATURES_HEADER % values + FEATURE_HEADER % values
69
70 for feature in features:
71 output += EXISTING_FEATURE % feature
72
73 for bundle in bundles:
74 output += BUNDLE % mvnUrl(bundle)
75
76 output += FEATURE_FOOTER + FEATURES_FOOTER
77 return output
78
79def generateAppFile(app_name,
80 origin,
81 version,
82 title,
83 category,
84 url,
85 feature_repo_name,
86 feature_name,
87 description = None,
88 apps = [],
89 artifacts = [],
90 **kwargs):
91 values = {
92 'app_name' : app_name,
93 'origin' : origin,
94 'version' : version,
95 'title' : title,
96 'category' : category,
97 'url' : url,
98 'feature_repo_name' : mvnUrl(feature_repo_name) + '/xml/features',
99 'feature_name' : feature_name,
100 }
101
102 values['description'] = description if description else title
103 values['apps'] = ','.join(apps) if apps else ''
104
105 output = APP_HEADER % values
106
107 for artifact in artifacts:
108 output += ARTIFACT % mvnUrl(artifact)
109
110 output += APP_FOOTER
111 return output
112
113
114if __name__ == '__main__':
115 import sys, optparse
116
117 parser = optparse.OptionParser()
Brian O'Connore124f3d2016-04-06 23:54:26 -0700118 parser.add_option("-n", "--name", dest="feature_coords", help="Feature MVN Coords")
Brian O'Connor1f165982016-04-06 21:36:09 -0700119 parser.add_option("-a", "--app", dest="app_name", help="App Name")
120 parser.add_option("-o", "--origin", dest="origin", help="Origin")
121 parser.add_option("-c", "--category", dest="category", help="Category")
122 parser.add_option("-u", "--url", dest="url", help="URL")
123 parser.add_option("-v", "--version", dest="version", help="Version")
124 parser.add_option("-t", "--title", dest="title", help="Title")
125 parser.add_option("-r", "--repo", dest="repo_name", help="Repo Name")
126
127 parser.add_option('-b', '--bundle',
128 action="append", dest='included_bundles',
129 metavar="BUNDLE", help='Included Bundle (multiple allowed)')
130 parser.add_option('-e', '--excluded-bundle',
131 action="append", dest='excluded_bundles',
132 metavar="BUNDLE", help='Excluded Bundle (multiple allowed)')
133 parser.add_option('-f', '--feature',
134 action="append", dest='features',
135 metavar="FEATURE", help='Existing Feature (multiple allowed)')
136 parser.add_option('-d', '--apps',
137 action="append", dest='apps',
138 metavar="FEATURE", help='Required App (multiple allowed)')
139
140 parser.add_option("-A", "--write-app", dest="write_app", action="store_true")
141 parser.add_option("-F", "--write-features", dest="write_features", action="store_true")
142
143 (options, args) = parser.parse_args()
144
145 values = {}
Brian O'Connore124f3d2016-04-06 23:54:26 -0700146 if options.feature_coords and options.version and options.title:
147 values['feature_name'] = options.feature_coords.split(':')[1]
Brian O'Connor1f165982016-04-06 21:36:09 -0700148 values['version'] = options.version
149 values['title'] = options.title
150 else:
151 sys.stderr.write('ERROR: Feature Name, Version, and Title are required\n')
152 sys.stderr.flush()
153 sys.exit(1)
154
155 if options.app_name and options.origin and options.category and options.url:
156 values['app_name'] = options.app_name
157 values['origin'] = options.origin
158 values['category'] = options.category
159 values['url'] = options.url
160 elif options.write_app:
161 sys.stderr.write('ERROR: Feature Name, Version, and Title are required\n')
162 sys.stderr.flush()
163 sys.exit(1)
164
165 values['feature_repo_name'] = options.repo_name if options.repo_name \
Brian O'Connore124f3d2016-04-06 23:54:26 -0700166 else options.feature_coords
Brian O'Connor1f165982016-04-06 21:36:09 -0700167
168 if options.write_features:
169 bundles = []
170 if options.included_bundles:
171 bundles += options.included_bundles
172 if options.excluded_bundles:
173 bundles += options.excluded_bundles
174 print generateFeatureFile(bundles=bundles,
175 features=options.features,
176 **values)
177 if options.write_app:
178 print generateAppFile(artifacts=options.included_bundles,
179 apps=options.apps,
180 **values)