blob: bbb053c9a65a9e74fe65961c6e3d24de230c1f79 [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'
Heedo Kang3cda3f32017-09-07 22:27:38 +090029SECURITY = '''\
30 <security>
31%s
32 </security>\n'''
Brian O'Connor1f165982016-04-06 21:36:09 -070033APP_FOOTER = '</app>'
34
Brian O'Connorbd6305a2016-04-25 14:28:12 -070035NON_OSGI_TAG = 'NON-OSGI'
Brian O'Connor1f165982016-04-06 21:36:09 -070036
37def mvnUrl(bundle):
Brian O'Connorbd6305a2016-04-25 14:28:12 -070038 #mvn-uri := 'mvn:' [ repository-url '!' ] group-id '/' artifact-id [ '/' [version] [ '/' [type] [ '/' classifier ] ] ] ]
39 parts = bundle.split(':')
40 prefix = 'mvn:'
41 suffix = ''
42 if len(parts) > 3:
43 parts.insert(2, parts.pop()) # move version to the 3rd position
44 if len(parts) >= 5:
45 # check classifier for special non-OSGi tag
46 i = parts[4].find(NON_OSGI_TAG)
47 if i == 0:
48 prefix = 'wrap:' + prefix
49 suffix = '$Bundle-SymbolicName=%s.%s&amp;Bundle-Version=%s' % tuple(parts[0:3])
50 if len(parts[4]) == len(NON_OSGI_TAG):
51 parts.pop() # pop off empty classifier
52 if parts[3].lower() == 'jar':
53 parts.pop() # pop off default extension: jar
54 else:
55 parts[4] = parts[4][len(NON_OSGI_TAG):]
56 return prefix + '/'.join(parts) + suffix
Brian O'Connor1f165982016-04-06 21:36:09 -070057
Brian O'Connorfc7f5fc2016-04-29 17:04:06 -070058def generateFeatureFile(feature_repo_name,
Brian O'Connor1f165982016-04-06 21:36:09 -070059 features = [],
Brian O'Connor1f165982016-04-06 21:36:09 -070060 **kwargs):
61 values = {
Brian O'Connorfc7f5fc2016-04-29 17:04:06 -070062 'feature_repo_name' : '-'.join(feature_repo_name.split(':')[1:3]),
63 }
64
65 output = FEATURES_HEADER % values
66
67 for feature in features:
68 output += feature
69
70 output += FEATURES_FOOTER
71 return output
72
73def generateFeature(feature_name,
74 version,
75 title,
76 features = [],
77 bundles = [],
78 **kwargs):
79 values = {
Brian O'Connor1f165982016-04-06 21:36:09 -070080 'feature_name' : feature_name,
81 'version' : version,
82 'title' : title,
Brian O'Connor1f165982016-04-06 21:36:09 -070083 }
84
Brian O'Connorfc7f5fc2016-04-29 17:04:06 -070085 output = FEATURE_HEADER % values
Brian O'Connor1f165982016-04-06 21:36:09 -070086
Brian O'Connorfc7f5fc2016-04-29 17:04:06 -070087 if features:
88 for feature in features:
89 output += EXISTING_FEATURE % feature
Brian O'Connor1f165982016-04-06 21:36:09 -070090
Brian O'Connorfc7f5fc2016-04-29 17:04:06 -070091 if bundles:
92 for bundle in bundles:
93 output += BUNDLE % mvnUrl(bundle)
Brian O'Connor1f165982016-04-06 21:36:09 -070094
Brian O'Connorfc7f5fc2016-04-29 17:04:06 -070095 output += FEATURE_FOOTER
Brian O'Connor1f165982016-04-06 21:36:09 -070096 return output
97
Brian O'Connorfc7f5fc2016-04-29 17:04:06 -070098
Brian O'Connor1f165982016-04-06 21:36:09 -070099def generateAppFile(app_name,
100 origin,
101 version,
102 title,
103 category,
104 url,
105 feature_repo_name,
106 feature_name,
107 description = None,
108 apps = [],
109 artifacts = [],
Heedo Kang3cda3f32017-09-07 22:27:38 +0900110 security= None,
Brian O'Connor1f165982016-04-06 21:36:09 -0700111 **kwargs):
112 values = {
113 'app_name' : app_name,
114 'origin' : origin,
115 'version' : version,
116 'title' : title,
117 'category' : category,
118 'url' : url,
119 'feature_repo_name' : mvnUrl(feature_repo_name) + '/xml/features',
120 'feature_name' : feature_name,
121 }
122
123 values['description'] = description if description else title
124 values['apps'] = ','.join(apps) if apps else ''
125
126 output = APP_HEADER % values
127
128 for artifact in artifacts:
129 output += ARTIFACT % mvnUrl(artifact)
130
Heedo Kang3cda3f32017-09-07 22:27:38 +0900131 if security is not None:
132 output += SECURITY % security
133
Brian O'Connor1f165982016-04-06 21:36:09 -0700134 output += APP_FOOTER
135 return output
136
137
138if __name__ == '__main__':
139 import sys, optparse
140
141 parser = optparse.OptionParser()
Brian O'Connore124f3d2016-04-06 23:54:26 -0700142 parser.add_option("-n", "--name", dest="feature_coords", help="Feature MVN Coords")
Brian O'Connor1f165982016-04-06 21:36:09 -0700143 parser.add_option("-a", "--app", dest="app_name", help="App Name")
144 parser.add_option("-o", "--origin", dest="origin", help="Origin")
145 parser.add_option("-c", "--category", dest="category", help="Category")
146 parser.add_option("-u", "--url", dest="url", help="URL")
147 parser.add_option("-v", "--version", dest="version", help="Version")
148 parser.add_option("-t", "--title", dest="title", help="Title")
149 parser.add_option("-r", "--repo", dest="repo_name", help="Repo Name")
Thomas Vachuskab0029682017-08-23 17:55:53 -0700150 parser.add_option('-D', '--desc', dest='desc', help='Application description')
Heedo Kang3cda3f32017-09-07 22:27:38 +0900151 parser.add_option('-s', '--security', dest='security', help='Application security')
Brian O'Connor1f165982016-04-06 21:36:09 -0700152
153 parser.add_option('-b', '--bundle',
154 action="append", dest='included_bundles',
155 metavar="BUNDLE", help='Included Bundle (multiple allowed)')
156 parser.add_option('-e', '--excluded-bundle',
157 action="append", dest='excluded_bundles',
158 metavar="BUNDLE", help='Excluded Bundle (multiple allowed)')
159 parser.add_option('-f', '--feature',
160 action="append", dest='features',
161 metavar="FEATURE", help='Existing Feature (multiple allowed)')
162 parser.add_option('-d', '--apps',
163 action="append", dest='apps',
164 metavar="FEATURE", help='Required App (multiple allowed)')
165
166 parser.add_option("-A", "--write-app", dest="write_app", action="store_true")
167 parser.add_option("-F", "--write-features", dest="write_features", action="store_true")
Brian O'Connorfc7f5fc2016-04-29 17:04:06 -0700168 parser.add_option("-E", "--write-feature", dest="write_feature", action="store_true")
Brian O'Connor1f165982016-04-06 21:36:09 -0700169
170 (options, args) = parser.parse_args()
171
172 values = {}
Brian O'Connore124f3d2016-04-06 23:54:26 -0700173 if options.feature_coords and options.version and options.title:
Brian O'Connorfc7f5fc2016-04-29 17:04:06 -0700174 parts = options.feature_coords.split(':')
175 values['feature_name'] = parts[1] if len(parts) > 1 else parts[0]
Brian O'Connor1f165982016-04-06 21:36:09 -0700176 values['version'] = options.version
177 values['title'] = options.title
178 else:
179 sys.stderr.write('ERROR: Feature Name, Version, and Title are required\n')
180 sys.stderr.flush()
181 sys.exit(1)
182
183 if options.app_name and options.origin and options.category and options.url:
184 values['app_name'] = options.app_name
185 values['origin'] = options.origin
186 values['category'] = options.category
187 values['url'] = options.url
188 elif options.write_app:
189 sys.stderr.write('ERROR: Feature Name, Version, and Title are required\n')
190 sys.stderr.flush()
191 sys.exit(1)
192
193 values['feature_repo_name'] = options.repo_name if options.repo_name \
Brian O'Connore124f3d2016-04-06 23:54:26 -0700194 else options.feature_coords
Brian O'Connor1f165982016-04-06 21:36:09 -0700195
Brian O'Connorfc7f5fc2016-04-29 17:04:06 -0700196 bundles = []
197 if options.included_bundles:
198 bundles += options.included_bundles
199 if options.excluded_bundles:
200 bundles += options.excluded_bundles
Thomas Vachuskab0029682017-08-23 17:55:53 -0700201 if options.desc:
202 values['description'] = options.desc
203
Brian O'Connorfc7f5fc2016-04-29 17:04:06 -0700204 feature = generateFeature(bundles=bundles,
205 features=options.features,
206 **values)
207
208 if options.write_feature:
209 print feature
210
Brian O'Connor1f165982016-04-06 21:36:09 -0700211 if options.write_features:
Brian O'Connorfc7f5fc2016-04-29 17:04:06 -0700212 print generateFeatureFile(features=[ feature ],
Brian O'Connor1f165982016-04-06 21:36:09 -0700213 **values)
Brian O'Connorfc7f5fc2016-04-29 17:04:06 -0700214
Brian O'Connor1f165982016-04-06 21:36:09 -0700215 if options.write_app:
216 print generateAppFile(artifacts=options.included_bundles,
217 apps=options.apps,
Heedo Kang3cda3f32017-09-07 22:27:38 +0900218 security=options.security,
Brian O'Connor1f165982016-04-06 21:36:09 -0700219 **values)