1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.shared.osgi;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.util.Enumeration;
24 import java.util.HashSet;
25 import java.util.Iterator;
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.jar.JarFile;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31 import java.util.zip.ZipEntry;
32
33 import org.apache.maven.artifact.Artifact;
34
35 import aQute.lib.osgi.Analyzer;
36
37
38
39
40
41
42
43
44
45 public class DefaultMaven2OsgiConverter
46 implements Maven2OsgiConverter
47 {
48
49
50 private static final Pattern OSGI_VERSION_PATTERN = Pattern
51 .compile( "[0-9]+\\.[0-9]+\\.[0-9]+(\\.[0-9A-Za-z_-]+)?" );
52
53
54
55
56 private static final Pattern ONLY_NUMBERS = Pattern.compile( "[0-9]+" );
57
58 private static final String FILE_SEPARATOR = System.getProperty( "file.separator" );
59
60 private String getBundleSymbolicName( String groupId, String artifactId )
61 {
62 return groupId + "." + artifactId;
63 }
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 public String getBundleSymbolicName( Artifact artifact )
80 {
81 if ( ( artifact.getFile() != null ) && artifact.getFile().exists() )
82 {
83 Analyzer analyzer = new Analyzer();
84
85 try
86 {
87 JarFile jar = new JarFile( artifact.getFile(), false );
88
89 if ( jar.getManifest() != null )
90 {
91 String symbolicNameAttribute = jar.getManifest().getMainAttributes()
92 .getValue( Analyzer.BUNDLE_SYMBOLICNAME );
93 Map bundleSymbolicNameHeader = analyzer.parseHeader( symbolicNameAttribute );
94
95 Iterator it = bundleSymbolicNameHeader.keySet().iterator();
96 if ( it.hasNext() )
97 {
98 return (String) it.next();
99 }
100 }
101 }
102 catch ( IOException e )
103 {
104 throw new ManifestReadingException( "Error reading manifest in jar "
105 + artifact.getFile().getAbsolutePath(), e );
106 }
107 }
108
109 int i = artifact.getGroupId().lastIndexOf( '.' );
110 if ( ( i < 0 ) && ( artifact.getFile() != null ) && artifact.getFile().exists() )
111 {
112 String groupIdFromPackage = getGroupIdFromPackage( artifact.getFile() );
113 if ( groupIdFromPackage != null )
114 {
115 return groupIdFromPackage;
116 }
117 }
118 String lastSection = artifact.getGroupId().substring( ++i );
119 if ( artifact.getArtifactId().equals( lastSection ) )
120 {
121 return artifact.getGroupId();
122 }
123 if ( artifact.getArtifactId().startsWith( lastSection ) )
124 {
125 String artifactId = artifact.getArtifactId().substring( lastSection.length() );
126 if ( Character.isLetterOrDigit( artifactId.charAt( 0 ) ) )
127 {
128 return getBundleSymbolicName( artifact.getGroupId(), artifactId );
129 }
130 else
131 {
132 return getBundleSymbolicName( artifact.getGroupId(), artifactId.substring( 1 ) );
133 }
134 }
135 return getBundleSymbolicName( artifact.getGroupId(), artifact.getArtifactId() );
136 }
137
138 private String getGroupIdFromPackage( File artifactFile )
139 {
140 try
141 {
142
143 Set packageNames = new HashSet();
144 JarFile jar = new JarFile( artifactFile, false );
145 Enumeration entries = jar.entries();
146 while ( entries.hasMoreElements() )
147 {
148 ZipEntry entry = (ZipEntry) entries.nextElement();
149 if ( entry.getName().endsWith( ".class" ) )
150 {
151 File f = new File( entry.getName() );
152 String packageName = f.getParent();
153 if ( packageName != null )
154 {
155 packageNames.add( packageName );
156 }
157 }
158 }
159
160
161 String[] groupIdSections = null;
162 for ( Iterator it = packageNames.iterator(); it.hasNext(); )
163 {
164 String packageName = (String) it.next();
165
166 String[] packageNameSections = packageName.split( "\\" + FILE_SEPARATOR );
167 if ( groupIdSections == null )
168 {
169
170 groupIdSections = packageNameSections;
171 }
172 else
173
174 {
175
176
177
178 int i;
179 for ( i = 0; ( i < packageNameSections.length ) && ( i < groupIdSections.length ); i++ )
180 {
181 if ( !packageNameSections[i].equals( groupIdSections[i] ) )
182 {
183 break;
184 }
185 }
186 groupIdSections = new String[i];
187 System.arraycopy( packageNameSections, 0, groupIdSections, 0, i );
188 }
189 }
190
191 if ( ( groupIdSections == null ) || ( groupIdSections.length == 0 ) )
192 {
193 return null;
194 }
195
196
197 if ( groupIdSections.length == 1 )
198 {
199 return null;
200 }
201
202 StringBuffer sb = new StringBuffer();
203 for ( int i = 0; i < groupIdSections.length; i++ )
204 {
205 sb.append( groupIdSections[i] );
206 if ( i < groupIdSections.length - 1 )
207 {
208 sb.append( '.' );
209 }
210 }
211 return sb.toString();
212 }
213 catch ( IOException e )
214 {
215
216 throw new RuntimeException( e );
217 }
218 }
219
220 public String getBundleFileName( Artifact artifact )
221 {
222 return getBundleSymbolicName( artifact ) + "_" + getVersion( artifact.getVersion() ) + ".jar";
223 }
224
225 public String getVersion( Artifact artifact )
226 {
227 return getVersion( artifact.getVersion() );
228 }
229
230 public String getVersion( String version )
231 {
232 String osgiVersion;
233
234
235
236
237
238
239
240
241 Matcher m;
242
243
244 m = OSGI_VERSION_PATTERN.matcher( version );
245 if ( m.matches() )
246 {
247 return version;
248 }
249
250 osgiVersion = version;
251
252
253 Pattern DATED_SNAPSHOT = Pattern.compile( "([0-9])(\\.([0-9]))?(\\.([0-9]))?\\-([0-9]{8}\\.[0-9]{6}\\-[0-9]*)" );
254 m = DATED_SNAPSHOT.matcher( osgiVersion );
255 if ( m.matches() )
256 {
257 String major = m.group( 1 );
258 String minor = ( m.group( 3 ) != null ) ? m.group( 3 ) : "0";
259 String service = ( m.group( 5 ) != null ) ? m.group( 5 ) : "0";
260 String qualifier = m.group( 6 ).replaceAll( "-", "_" ).replaceAll( "\\.", "_" );
261 osgiVersion = major + "." + minor + "." + service + "." + qualifier;
262 }
263
264
265 osgiVersion = osgiVersion.replaceFirst( "-", "\\." );
266 osgiVersion = osgiVersion.replaceAll( "-", "_" );
267 m = OSGI_VERSION_PATTERN.matcher( osgiVersion );
268 if ( m.matches() )
269 {
270 return osgiVersion;
271 }
272
273
274 Pattern DOTS_IN_QUALIFIER = Pattern.compile( "([0-9])(\\.[0-9])?\\.([0-9A-Za-z_-]+)\\.([0-9A-Za-z_-]+)" );
275 m = DOTS_IN_QUALIFIER.matcher( osgiVersion );
276 if ( m.matches() )
277 {
278 String s1 = m.group( 1 );
279 String s2 = m.group( 2 );
280 String s3 = m.group( 3 );
281 String s4 = m.group( 4 );
282
283 Matcher qualifierMatcher = ONLY_NUMBERS.matcher( s3 );
284
285
286
287
288 if ( !qualifierMatcher.matches() )
289 {
290 osgiVersion = s1 + s2 + "." + s3 + "_" + s4;
291 }
292 }
293
294
295
296
297
298
299
300
301 Pattern NEED_TO_FILL_ZEROS = Pattern.compile( "([0-9])(\\.([0-9]))?(\\.([0-9A-Za-z_-]+))?" );
302 m = NEED_TO_FILL_ZEROS.matcher( osgiVersion );
303 if ( m.matches() )
304 {
305 String major = m.group( 1 );
306 String minor = m.group( 3 );
307 String service = null;
308 String qualifier = m.group( 5 );
309
310
311 if ( qualifier == null )
312 {
313 osgiVersion = getVersion( major, minor, service, qualifier );
314 }
315 else
316 {
317
318 Matcher qualifierMatcher = ONLY_NUMBERS.matcher( qualifier );
319 if ( qualifierMatcher.matches() )
320 {
321 if ( minor == null )
322 {
323 minor = qualifier;
324 }
325 else
326 {
327 service = qualifier;
328 }
329 osgiVersion = getVersion( major, minor, service, null );
330 }
331 else
332 {
333 osgiVersion = getVersion( major, minor, service, qualifier );
334 }
335 }
336 }
337
338 m = OSGI_VERSION_PATTERN.matcher( osgiVersion );
339
340 if ( !m.matches() )
341 {
342 String major = "0";
343 String minor = "0";
344 String service = "0";
345 String qualifier = osgiVersion.replaceAll( "\\.", "_" );
346 osgiVersion = major + "." + minor + "." + service + "." + qualifier;
347 }
348
349 return osgiVersion;
350 }
351
352 private String getVersion( String major, String minor, String service, String qualifier )
353 {
354 StringBuffer sb = new StringBuffer();
355 sb.append( major != null ? major : "0" );
356 sb.append( '.' );
357 sb.append( minor != null ? minor : "0" );
358 sb.append( '.' );
359 sb.append( service != null ? service : "0" );
360 if ( qualifier != null )
361 {
362 sb.append( '.' );
363 sb.append( qualifier );
364 }
365 return sb.toString();
366 }
367 }