blob: 9979ab516c6fcf59fc86000c545884f8d2dbac77 [file] [log] [blame]
Ray Milkeyad83ef92018-06-05 11:05:51 -07001#!/usr/bin/env python
Thomas Vachuska8e022a92018-07-10 14:47:38 -07002"""
3 Copyright 2018-present Open Networking Foundation
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16"""
Ray Milkeyad83ef92018-06-05 11:05:51 -070017
18##### Templates for features.xml
19FEATURES_HEADER = '''\
20<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
21<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
22 name="%(feature_repo_name)s">
23'''
24FEATURE_HEADER= '''\
25 <feature name="%(feature_name)s" version="%(version)s"
26 description="%(title)s">
27'''
28EXISTING_FEATURE = ' <feature>%s</feature>\n'
29BUNDLE = ' <bundle>%s</bundle>\n'
30FEATURE_FOOTER = ' </feature>\n'
Ray Milkey1d52ddd2018-06-07 10:37:24 -070031FEATURES_FOOTER = '</features>\n'
Ray Milkeyad83ef92018-06-05 11:05:51 -070032
33##### Templates for app.xml
34APP_HEADER = '''\
35<?xml version="1.0" encoding="UTF-8"?>
36<app name="%(app_name)s" origin="%(origin)s" version="%(version)s"
37 title="%(title)s" category="%(category)s" url="%(url)s"
38 featuresRepo="%(feature_repo_name)s"
39 features="%(feature_name)s" apps="%(apps)s">
40 <description>%(description)s</description>
41'''
42ARTIFACT = ' <artifact>%s</artifact>\n'
43SECURITY = '''\
44 <security>
45%s
46 </security>\n'''
Ray Milkey1d52ddd2018-06-07 10:37:24 -070047APP_FOOTER = '</app>\n'
Ray Milkeyad83ef92018-06-05 11:05:51 -070048
49NON_OSGI_TAG = 'NON-OSGI'
50
51def mvnUrl(bundle):
52 #mvn-uri := 'mvn:' [ repository-url '!' ] group-id '/' artifact-id [ '/' [version] [ '/' [type] [ '/' classifier ] ] ] ]
Thomas Vachuska510419f2018-06-28 17:05:09 -070053 parts = bundle.split(':')[1:]
Ray Milkeyad83ef92018-06-05 11:05:51 -070054 prefix = 'mvn:'
55 suffix = ''
56 if len(parts) > 3:
57 parts.insert(2, parts.pop()) # move version to the 3rd position
58 if len(parts) >= 5:
59 # check classifier for special non-OSGi tag
60 i = parts[4].find(NON_OSGI_TAG)
61 if i == 0:
62 prefix = 'wrap:' + prefix
63 suffix = '$Bundle-SymbolicName=%s.%s&amp;Bundle-Version=%s' % tuple(parts[0:3])
64 if len(parts[4]) == len(NON_OSGI_TAG):
65 parts.pop() # pop off empty classifier
66 if parts[3].lower() == 'jar':
67 parts.pop() # pop off default extension: jar
68 else:
69 parts[4] = parts[4][len(NON_OSGI_TAG):]
70 return prefix + '/'.join(parts) + suffix
71
72def generateFeatureFile(feature_repo_name,
73 features = [],
74 **kwargs):
75 values = {
76 'feature_repo_name' : '-'.join(feature_repo_name.split(':')[1:3]),
77 }
78
79 output = FEATURES_HEADER % values
80
81 for feature in features:
82 output += feature
83
84 output += FEATURES_FOOTER
85 return output
86
87def generateFeature(feature_name,
88 version,
89 title,
90 features = [],
91 bundles = [],
92 **kwargs):
93 values = {
94 'feature_name' : feature_name,
95 'version' : version,
96 'title' : title,
97 }
98
99 output = FEATURE_HEADER % values
100
101 if features:
102 for feature in features:
103 output += EXISTING_FEATURE % feature
104
105 if bundles:
106 for bundle in bundles:
107 output += BUNDLE % mvnUrl(bundle)
108
109 output += FEATURE_FOOTER
110 return output
111
112
113def generateAppFile(app_name,
114 origin,
115 version,
116 title,
117 category,
118 url,
119 feature_repo_name,
120 feature_name,
121 description = None,
122 apps = [],
123 artifacts = [],
124 security= None,
125 **kwargs):
126 values = {
127 'app_name' : app_name,
128 'origin' : origin,
129 'version' : version,
130 'title' : title,
131 'category' : category,
132 'url' : url,
133 'feature_repo_name' : mvnUrl(feature_repo_name) + '/xml/features',
134 'feature_name' : feature_name,
135 }
136
137 values['description'] = description if description else title
138 values['apps'] = ','.join(apps) if apps else ''
139
140 output = APP_HEADER % values
141
142 for artifact in artifacts:
143 output += ARTIFACT % mvnUrl(artifact)
144
145 if security is not None:
146 output += SECURITY % security
147
148 output += APP_FOOTER
149 return output
150
Thomas Vachuskaaab45d12018-06-05 16:39:46 -0700151def write(name, msg):
152 if name is not None:
153 with open(name, "w") as file:
154 file.write(msg)
155 else:
Laszlo Papp066fe4a2018-09-05 13:21:27 +0100156 print(msg)
Ray Milkeyad83ef92018-06-05 11:05:51 -0700157
158if __name__ == '__main__':
159 import sys, optparse
160
161 parser = optparse.OptionParser()
Thomas Vachuskaaab45d12018-06-05 16:39:46 -0700162 parser.add_option("-O", "--output", dest="output", help="Output file")
Ray Milkeyad83ef92018-06-05 11:05:51 -0700163 parser.add_option("-n", "--name", dest="feature_coords", help="Feature MVN Coords")
164 parser.add_option("-a", "--app", dest="app_name", help="App Name")
165 parser.add_option("-o", "--origin", dest="origin", help="Origin")
166 parser.add_option("-c", "--category", dest="category", help="Category")
167 parser.add_option("-u", "--url", dest="url", help="URL")
168 parser.add_option("-v", "--version", dest="version", help="Version")
169 parser.add_option("-t", "--title", dest="title", help="Title")
170 parser.add_option("-r", "--repo", dest="repo_name", help="Repo Name")
171 parser.add_option('-D', '--desc', dest='desc', help='Application description')
172 parser.add_option('-s', '--security', dest='security', help='Application security')
173
174 parser.add_option('-b', '--bundle',
175 action="append", dest='included_bundles',
176 metavar="BUNDLE", help='Included Bundle (multiple allowed)')
177 parser.add_option('-e', '--excluded-bundle',
178 action="append", dest='excluded_bundles',
179 metavar="BUNDLE", help='Excluded Bundle (multiple allowed)')
180 parser.add_option('-f', '--feature',
181 action="append", dest='features',
182 metavar="FEATURE", help='Existing Feature (multiple allowed)')
183 parser.add_option('-d', '--apps',
184 action="append", dest='apps',
185 metavar="FEATURE", help='Required App (multiple allowed)')
186
187 parser.add_option("-A", "--write-app", dest="write_app", action="store_true")
188 parser.add_option("-F", "--write-features", dest="write_features", action="store_true")
189 parser.add_option("-E", "--write-feature", dest="write_feature", action="store_true")
190
191 (options, args) = parser.parse_args()
192
193 values = {}
194 if options.feature_coords and options.version and options.title:
195 parts = options.feature_coords.split(':')
Thomas Vachuska8e022a92018-07-10 14:47:38 -0700196 values['feature_name'] = parts[2] if len(parts) > 2 else parts[0]
Ray Milkeyad83ef92018-06-05 11:05:51 -0700197 values['version'] = options.version
198 values['title'] = options.title
199 else:
200 sys.stderr.write('ERROR: Feature Name, Version, and Title are required\n')
201 sys.stderr.flush()
202 sys.exit(1)
203
204 if options.app_name and options.origin and options.category and options.url:
205 values['app_name'] = options.app_name
206 values['origin'] = options.origin
207 values['category'] = options.category
208 values['url'] = options.url
209 elif options.write_app:
210 sys.stderr.write('ERROR: Feature Name, Version, and Title are required\n')
211 sys.stderr.flush()
212 sys.exit(1)
213
214 values['feature_repo_name'] = options.repo_name if options.repo_name \
215 else options.feature_coords
216
217 bundles = []
218 if options.included_bundles:
219 bundles += options.included_bundles
220 if options.excluded_bundles:
221 bundles += options.excluded_bundles
222 if options.desc:
223 values['description'] = options.desc
224
225 feature = generateFeature(bundles=bundles,
226 features=options.features,
227 **values)
228
229 if options.write_feature:
Thomas Vachuskaaab45d12018-06-05 16:39:46 -0700230 write(options.output, feature)
Ray Milkeyad83ef92018-06-05 11:05:51 -0700231
232 if options.write_features:
Thomas Vachuskaaab45d12018-06-05 16:39:46 -0700233 write(options.output,
234 generateFeatureFile(features=[ feature ], **values))
Ray Milkeyad83ef92018-06-05 11:05:51 -0700235
236 if options.write_app:
Thomas Vachuskaaab45d12018-06-05 16:39:46 -0700237 write(options.output,
238 generateAppFile(artifacts=options.included_bundles,
Ray Milkeyad83ef92018-06-05 11:05:51 -0700239 apps=options.apps,
240 security=options.security,
Laszlo Papp066fe4a2018-09-05 13:21:27 +0100241 **values))