1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
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.util.LinkedHashMap;
27  import java.util.Map;
28  import java.util.Properties;
29  import java.util.jar.Manifest;
30  
31  import org.apache.maven.plugin.MojoExecutionException;
32  import org.apache.maven.plugin.MojoFailureException;
33  import org.apache.maven.project.MavenProject;
34  
35  import aQute.lib.osgi.Analyzer;
36  import aQute.lib.osgi.Builder;
37  import aQute.lib.osgi.Jar;
38  
39  
40  /**
41   * Generate an OSGi manifest for this project
42   * 
43   * @goal manifest
44   * @phase process-classes
45   * @requiresDependencyResolution test
46   * @threadSafe
47   */
48  public class ManifestPlugin extends BundlePlugin
49  {
50      protected void execute( MavenProject project, Map instructions, Properties properties, Jar[] classpath )
51          throws MojoExecutionException
52      {
53          Manifest manifest;
54          try
55          {
56              if ( supportedProjectTypes.contains( getProject().getArtifact().getType() ) )
57              {
58                  Builder builder = buildOSGiBundle( project, instructions, properties, classpath );
59                  manifest = builder.getJar().getManifest();
60                  builder.close();
61              }
62              else
63              {
64                  manifest = getManifest( project, instructions, properties, classpath );
65              }
66          }
67          catch ( FileNotFoundException e )
68          {
69              throw new MojoExecutionException( "Cannot find " + e.getMessage()
70                  + " (manifest goal must be run after compile phase)", e );
71          }
72          catch ( IOException e )
73          {
74              throw new MojoExecutionException( "Error trying to generate Manifest", e );
75          }
76          catch ( MojoFailureException e )
77          {
78              getLog().error( e.getLocalizedMessage() );
79              throw new MojoExecutionException( "Error(s) found in manifest configuration", e );
80          }
81          catch ( Exception e )
82          {
83              getLog().error( "An internal error occurred", e );
84              throw new MojoExecutionException( "Internal error in maven-bundle-plugin", e );
85          }
86  
87          File outputFile = new File( manifestLocation, "MANIFEST.MF" );
88  
89          try
90          {
91              writeManifest( manifest, outputFile );
92          }
93          catch ( IOException e )
94          {
95              throw new MojoExecutionException( "Error trying to write Manifest to file " + outputFile, e );
96          }
97      }
98  
99  
100     public Manifest getManifest( MavenProject project, Jar[] classpath ) throws IOException, MojoFailureException,
101         MojoExecutionException, Exception
102     {
103         return getManifest( project, new LinkedHashMap(), new Properties(), classpath );
104     }
105 
106 
107     public Manifest getManifest( MavenProject project, Map instructions, Properties properties, Jar[] classpath )
108         throws IOException, MojoFailureException, MojoExecutionException, Exception
109     {
110         Analyzer analyzer = getAnalyzer( project, instructions, properties, classpath );
111         boolean hasErrors = reportErrors( "Manifest " + project.getArtifact(), analyzer );
112         if ( hasErrors )
113         {
114             String failok = analyzer.getProperty( "-failok" );
115             if ( null == failok || "false".equalsIgnoreCase( failok ) )
116             {
117                 throw new MojoFailureException( "Error(s) found in manifest configuration" );
118             }
119         }
120 
121         Manifest manifest = analyzer.getJar().getManifest();
122 
123         // cleanup...
124         analyzer.close();
125 
126         return manifest;
127     }
128 
129 
130     protected Analyzer getAnalyzer( MavenProject project, Jar[] classpath ) throws IOException, MojoExecutionException,
131         Exception
132     {
133         return getAnalyzer( project, new LinkedHashMap(), new Properties(), classpath );
134     }
135 
136 
137     protected Analyzer getAnalyzer( MavenProject project, Map instructions, Properties properties, Jar[] classpath )
138         throws IOException, MojoExecutionException, Exception
139     {
140         File file = project.getArtifact().getFile();
141         if ( file == null )
142         {
143             file = getOutputDirectory();
144         }
145 
146         if ( !file.exists() )
147         {
148             throw new FileNotFoundException( file.getPath() );
149         }
150 
151         Builder analyzer = getOSGiBuilder( project, instructions, properties, classpath );
152 
153         analyzer.setJar( file );
154 
155         if ( analyzer.getProperty( Analyzer.EXPORT_PACKAGE ) == null
156             && analyzer.getProperty( Analyzer.EXPORT_CONTENTS ) == null
157             && analyzer.getProperty( Analyzer.PRIVATE_PACKAGE ) == null )
158         {
159             String export = analyzer.calculateExportsFromContents( analyzer.getJar() );
160             analyzer.setProperty( Analyzer.EXPORT_PACKAGE, export );
161         }
162 
163         addMavenInstructions( project, analyzer );
164 
165         analyzer.mergeManifest( analyzer.getJar().getManifest() );
166         analyzer.calcManifest();
167 
168         mergeMavenManifest( project, analyzer );
169 
170         return analyzer;
171     }
172 
173 
174     public static void writeManifest( Manifest manifest, File outputFile ) throws IOException
175     {
176         outputFile.getParentFile().mkdirs();
177 
178         FileOutputStream os;
179         os = new FileOutputStream( outputFile );
180         try
181         {
182             manifest.write( os );
183         }
184         finally
185         {
186             try
187             {
188                 os.close();
189             }
190             catch ( IOException e )
191             {
192                 // nothing we can do here
193             }
194         }
195     }
196 }