1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.felix.bundleplugin;
20
21
22 import java.io.File;
23 import java.io.FileNotFoundException;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.OutputStream;
27 import java.util.Iterator;
28 import java.util.LinkedHashMap;
29 import java.util.Map;
30 import java.util.Map.Entry;
31 import java.util.Properties;
32 import java.util.jar.Manifest;
33
34 import org.apache.maven.plugin.MojoExecutionException;
35 import org.apache.maven.plugin.MojoFailureException;
36 import org.apache.maven.project.MavenProject;
37
38 import aQute.lib.osgi.Analyzer;
39 import aQute.lib.osgi.Builder;
40 import aQute.lib.osgi.Jar;
41 import aQute.lib.osgi.Resource;
42
43
44
45
46
47
48
49
50
51
52 public class ManifestPlugin extends BundlePlugin
53 {
54
55
56
57
58
59 protected boolean rebuildBundle;
60
61
62 @Override
63 protected void execute( MavenProject project, Map instructions, Properties properties, Jar[] classpath )
64 throws MojoExecutionException
65 {
66 Manifest manifest;
67 try
68 {
69 manifest = getManifest( project, instructions, properties, classpath );
70 }
71 catch ( FileNotFoundException e )
72 {
73 throw new MojoExecutionException( "Cannot find " + e.getMessage()
74 + " (manifest goal must be run after compile phase)", e );
75 }
76 catch ( IOException e )
77 {
78 throw new MojoExecutionException( "Error trying to generate Manifest", e );
79 }
80 catch ( MojoFailureException e )
81 {
82 getLog().error( e.getLocalizedMessage() );
83 throw new MojoExecutionException( "Error(s) found in manifest configuration", e );
84 }
85 catch ( Exception e )
86 {
87 getLog().error( "An internal error occurred", e );
88 throw new MojoExecutionException( "Internal error in maven-bundle-plugin", e );
89 }
90
91 File outputFile = new File( manifestLocation, "MANIFEST.MF" );
92
93 try
94 {
95 writeManifest( manifest, outputFile );
96 }
97 catch ( IOException e )
98 {
99 throw new MojoExecutionException( "Error trying to write Manifest to file " + outputFile, e );
100 }
101 }
102
103
104 public Manifest getManifest( MavenProject project, Jar[] classpath ) throws IOException, MojoFailureException,
105 MojoExecutionException, Exception
106 {
107 return getManifest( project, new LinkedHashMap(), new Properties(), classpath );
108 }
109
110
111 public Manifest getManifest( MavenProject project, Map instructions, Properties properties, Jar[] classpath )
112 throws IOException, MojoFailureException, MojoExecutionException, Exception
113 {
114 Analyzer analyzer = getAnalyzer( project, instructions, properties, classpath );
115 boolean hasErrors = reportErrors( "Manifest " + project.getArtifact(), analyzer );
116 if ( hasErrors )
117 {
118 String failok = analyzer.getProperty( "-failok" );
119 if ( null == failok || "false".equalsIgnoreCase( failok ) )
120 {
121 throw new MojoFailureException( "Error(s) found in manifest configuration" );
122 }
123 }
124
125 Jar jar = analyzer.getJar();
126
127 if ( unpackBundle )
128 {
129 File outputFile = getOutputDirectory();
130 for ( Entry<String, Resource> entry : jar.getResources().entrySet() )
131 {
132 File entryFile = new File( outputFile, entry.getKey() );
133 if ( !entryFile.exists() || entry.getValue().lastModified() == 0 )
134 {
135 entryFile.getParentFile().mkdirs();
136 OutputStream os = new FileOutputStream( entryFile );
137 entry.getValue().write( os );
138 os.close();
139 }
140 }
141 }
142
143 Manifest manifest = jar.getManifest();
144
145
146 analyzer.close();
147
148 return manifest;
149 }
150
151
152 protected Analyzer getAnalyzer( MavenProject project, Jar[] classpath ) throws IOException, MojoExecutionException,
153 Exception
154 {
155 return getAnalyzer( project, new LinkedHashMap(), new Properties(), classpath );
156 }
157
158
159 protected Analyzer getAnalyzer( MavenProject project, Map instructions, Properties properties, Jar[] classpath )
160 throws IOException, MojoExecutionException, Exception
161 {
162 if ( rebuildBundle && supportedProjectTypes.contains( project.getArtifact().getType() ) )
163 {
164 return buildOSGiBundle( project, instructions, properties, classpath );
165 }
166
167 File file = project.getArtifact().getFile();
168 if ( file == null )
169 {
170 file = getOutputDirectory();
171 }
172
173 if ( !file.exists() )
174 {
175 throw new FileNotFoundException( file.getPath() );
176 }
177
178 Builder analyzer = getOSGiBuilder( project, instructions, properties, classpath );
179
180 analyzer.setJar( file );
181
182
183
184
185
186 boolean isOutputDirectory = file.equals( getOutputDirectory() );
187
188 if ( analyzer.getProperty( Analyzer.EXPORT_PACKAGE ) == null
189 && analyzer.getProperty( Analyzer.EXPORT_CONTENTS ) == null
190 && analyzer.getProperty( Analyzer.PRIVATE_PACKAGE ) == null && !isOutputDirectory )
191 {
192 String export = calculateExportsFromContents( analyzer.getJar() );
193 analyzer.setProperty( Analyzer.EXPORT_PACKAGE, export );
194 }
195
196 addMavenInstructions( project, analyzer );
197
198
199 if ( analyzer.getProperty( DependencyEmbedder.EMBED_DEPENDENCY ) != null && isOutputDirectory )
200 {
201 analyzer.build();
202 }
203 else
204 {
205 analyzer.mergeManifest( analyzer.getJar().getManifest() );
206 analyzer.calcManifest();
207 }
208
209 mergeMavenManifest( project, analyzer );
210
211 return analyzer;
212 }
213
214
215 public static void writeManifest( Manifest manifest, File outputFile ) throws IOException
216 {
217 outputFile.getParentFile().mkdirs();
218
219 FileOutputStream os;
220 os = new FileOutputStream( outputFile );
221 try
222 {
223 Jar.writeManifest( manifest, os );
224 }
225 finally
226 {
227 try
228 {
229 os.close();
230 }
231 catch ( IOException e )
232 {
233
234 }
235 }
236 }
237
238
239
240
241
242 public static String calculateExportsFromContents( Jar bundle )
243 {
244 String ddel = "";
245 StringBuffer sb = new StringBuffer();
246 Map<String, Map<String, Resource>> map = bundle.getDirectories();
247 for ( Iterator<Entry<String, Map<String, Resource>>> i = map.entrySet().iterator(); i.hasNext(); )
248 {
249
250
251
252 Entry<String, Map<String, Resource>> entry = i.next();
253 if ( entry.getValue() == null || entry.getValue().isEmpty() )
254 continue;
255
256 String directory = entry.getKey();
257 if ( directory.equals( "META-INF" ) || directory.startsWith( "META-INF/" ) )
258 continue;
259 if ( directory.equals( "OSGI-OPT" ) || directory.startsWith( "OSGI-OPT/" ) )
260 continue;
261 if ( directory.equals( "/" ) )
262 continue;
263
264 if ( directory.endsWith( "/" ) )
265 directory = directory.substring( 0, directory.length() - 1 );
266
267 directory = directory.replace( '/', '.' );
268 sb.append( ddel );
269 sb.append( directory );
270 ddel = ",";
271 }
272 return sb.toString();
273 }
274 }