~ubuntu-branches/ubuntu/quantal/hawtjni/quantal

« back to all changes in this revision

Viewing changes to maven-hawtjni-plugin/src/main/java/org/fusesource/hawtjni/maven/GenerateMojo.java

  • Committer: Bazaar Package Importer
  • Author(s): Miguel Landaeta
  • Date: 2010-08-05 19:40:25 UTC
  • Revision ID: james.westby@ubuntu.com-20100805194025-3004hn889accwu2i
Tags: upstream-1.0~+git0c502e20c4
ImportĀ upstreamĀ versionĀ 1.0~+git0c502e20c4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * Copyright (C) 2009 Progress Software, Inc.
 
3
 * http://fusesource.com
 
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
 */
 
17
package org.fusesource.hawtjni.maven;
 
18
 
 
19
import java.io.File;
 
20
import java.io.IOException;
 
21
import java.io.Reader;
 
22
import java.net.URL;
 
23
import java.util.ArrayList;
 
24
import java.util.HashMap;
 
25
import java.util.List;
 
26
import java.util.Map;
 
27
import java.util.Set;
 
28
 
 
29
import org.apache.maven.artifact.Artifact;
 
30
import org.apache.maven.plugin.AbstractMojo;
 
31
import org.apache.maven.plugin.MojoExecutionException;
 
32
import org.apache.maven.project.MavenProject;
 
33
import org.codehaus.plexus.interpolation.InterpolatorFilterReader;
 
34
import org.codehaus.plexus.interpolation.MapBasedValueSource;
 
35
import org.codehaus.plexus.interpolation.StringSearchInterpolator;
 
36
import org.codehaus.plexus.util.FileUtils;
 
37
import org.codehaus.plexus.util.FileUtils.FilterWrapper;
 
38
import org.fusesource.hawtjni.generator.HawtJNI;
 
39
import org.fusesource.hawtjni.generator.ProgressMonitor;
 
40
 
 
41
/**
 
42
 * This goal generates the native source code and a
 
43
 * autoconf/msbuild based build system needed to 
 
44
 * build a JNI library for any HawtJNI annotated
 
45
 * classes in your maven project.
 
46
 * 
 
47
 * @goal generate
 
48
 * @phase process-classes
 
49
 * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
 
50
 */
 
51
public class GenerateMojo extends AbstractMojo {
 
52
 
 
53
    /**
 
54
     * The maven project.
 
55
     * 
 
56
     * @parameter expression="${project}"
 
57
     * @required
 
58
     * @readonly
 
59
     */
 
60
    protected MavenProject project;
 
61
 
 
62
    /**
 
63
     * The directory where the generated native source files are located.
 
64
     * 
 
65
     * @parameter default-value="${project.build.directory}/generated-sources/hawtjni/native-src"
 
66
     */
 
67
    private File generatedNativeSourceDirectory;
 
68
 
 
69
    /**
 
70
     * The base name of the library, used to determine generated file names.
 
71
     * 
 
72
     * @parameter default-value="${project.artifactId}"
 
73
     */
 
74
    private String name;
 
75
 
 
76
    /**
 
77
     * The copyright header template that will be added to the generated source files.
 
78
     * Use the '%END_YEAR%' token to have it replaced with the current year.  
 
79
     * 
 
80
     * @parameter default-value=""
 
81
     */
 
82
    private String copyright;
 
83
 
 
84
    /**
 
85
     * Restrict looking for JNI classes to the specified package.
 
86
     *  
 
87
     * @parameter
 
88
     */
 
89
    private List<String> packages = new ArrayList<String>();
 
90
 
 
91
    /**
 
92
     * The directory where the java classes files are located.
 
93
     * 
 
94
     * @parameter default-value="${project.build.outputDirectory}"
 
95
     */
 
96
    private File classesDirectory;
 
97
    
 
98
    /**
 
99
     * The directory where the generated build package is located..
 
100
     * 
 
101
     * @parameter default-value="${project.build.directory}/generated-sources/hawtjni/native-package"
 
102
     */
 
103
    private File packageDirectory;
 
104
    
 
105
    /**
 
106
     * The list of additional files to be included in the package will be
 
107
     * placed.
 
108
     * 
 
109
     * @parameter default-value="${basedir}/src/main/native-package"
 
110
     */
 
111
    private File customPackageDirectory;
 
112
 
 
113
    /**
 
114
     * The text encoding of the files.
 
115
     * 
 
116
     * @parameter default-value="UTF-8"
 
117
     */
 
118
    private String encoding;
 
119
 
 
120
    /**
 
121
     * Should we skip executing the autogen.sh file.
 
122
     * 
 
123
     * @parameter default-value="${skip-autogen}"
 
124
     */
 
125
    private boolean skipAutogen;
 
126
    
 
127
    /**
 
128
     * Should we force executing the autogen.sh file.
 
129
     * 
 
130
     * @parameter default-value="${force-autogen}"
 
131
     */
 
132
    private boolean forceAutogen;
 
133
 
 
134
    /**
 
135
     * Should we display all the native build output?
 
136
     * 
 
137
     * @parameter default-value="${hawtjni-verbose}"
 
138
     */
 
139
    private boolean verbose;
 
140
 
 
141
    /**
 
142
     * Extra arguments you want to pass to the autogen.sh command.
 
143
     * 
 
144
     * @parameter
 
145
     */
 
146
    private List<String> autogenArgs;
 
147
    
 
148
    /**
 
149
     * Set this value to false to disable the callback support in HawtJNI.
 
150
     * Disabling callback support can substantially reduce the size
 
151
     * of the generated native library.  
 
152
     * 
 
153
     * @parameter default-value="true"
 
154
     */
 
155
    private boolean callbacks;
 
156
    
 
157
    private File targetSrcDir;
 
158
    
 
159
    private CLI cli = new CLI();
 
160
 
 
161
    public void execute() throws MojoExecutionException {
 
162
        cli.verbose = verbose;
 
163
        cli.log = getLog();
 
164
        generateNativeSourceFiles();
 
165
        generateBuildSystem(); 
 
166
    }
 
167
 
 
168
    private void generateNativeSourceFiles() throws MojoExecutionException {
 
169
        HawtJNI generator = new HawtJNI();
 
170
        generator.setClasspaths(getClasspath());
 
171
        generator.setName(name);
 
172
        generator.setCopyright(copyright);
 
173
        generator.setNativeOutput(generatedNativeSourceDirectory);
 
174
        generator.setPackages(packages);
 
175
        generator.setCallbacks(callbacks);
 
176
        generator.setProgress(new ProgressMonitor() {
 
177
            public void step() {
 
178
            }
 
179
            public void setTotal(int total) {
 
180
            }
 
181
            public void setMessage(String message) {
 
182
                getLog().info(message);
 
183
            }
 
184
        });
 
185
        try {
 
186
            generator.generate();
 
187
        } catch (Exception e) {
 
188
            throw new MojoExecutionException("Native source code generation failed: "+e, e);
 
189
        }
 
190
    }
 
191
 
 
192
    private void generateBuildSystem() throws MojoExecutionException {
 
193
        try {
 
194
            packageDirectory.mkdirs();
 
195
            new File(packageDirectory, "m4").mkdirs();
 
196
            targetSrcDir = new File(packageDirectory, "src");
 
197
            targetSrcDir.mkdirs();
 
198
 
 
199
            if( customPackageDirectory!=null && customPackageDirectory.isDirectory() ) {
 
200
                FileUtils.copyDirectoryStructureIfModified(customPackageDirectory, packageDirectory);
 
201
            }
 
202
 
 
203
            if( generatedNativeSourceDirectory!=null && generatedNativeSourceDirectory.isDirectory() ) {
 
204
                FileUtils.copyDirectoryStructureIfModified(generatedNativeSourceDirectory, targetSrcDir);
 
205
            }
 
206
            
 
207
            copyTemplateResource("readme.md", false);
 
208
            copyTemplateResource("configure.ac", true);
 
209
            copyTemplateResource("Makefile.am", true);
 
210
            copyTemplateResource("m4/custom.m4", false);
 
211
            copyTemplateResource("m4/jni.m4", false);
 
212
            copyTemplateResource("m4/osx-universal.m4", false);
 
213
 
 
214
            // To support windows based builds..
 
215
            copyTemplateResource("vs2008.vcproj", true);
 
216
                        
 
217
            File autogen = new File(packageDirectory, "autogen.sh");
 
218
            File configure = new File(packageDirectory, "configure");
 
219
            if( !autogen.exists() ) {
 
220
                copyTemplateResource("autogen.sh", false);
 
221
                cli.setExecutable(autogen);
 
222
            }
 
223
            if( !skipAutogen ) {
 
224
                if( (!configure.exists() && !CLI.IS_WINDOWS) || forceAutogen ) {
 
225
                    try {
 
226
                        cli.system(packageDirectory, new String[] {"./autogen.sh"}, autogenArgs);
 
227
                    } catch (Exception e) {
 
228
                        e.printStackTrace();
 
229
                    }
 
230
                }
 
231
            }
 
232
            
 
233
            
 
234
        } catch (Exception e) {
 
235
            throw new MojoExecutionException("Native build system generation failed: "+e, e);
 
236
        }
 
237
    }
 
238
 
 
239
    @SuppressWarnings("unchecked")
 
240
    private ArrayList<String> getClasspath() throws MojoExecutionException {
 
241
        ArrayList<String> artifacts = new ArrayList<String>();
 
242
        try {
 
243
            artifacts.add(classesDirectory.getCanonicalPath());
 
244
            for (Artifact artifact : (Set<Artifact>) project.getArtifacts()) {
 
245
                File file = artifact.getFile();
 
246
                getLog().debug("Including: " + file);
 
247
                artifacts.add(file.getCanonicalPath());
 
248
            }
 
249
        } catch (IOException e) {
 
250
            throw new MojoExecutionException("Could not determine project classath.", e);
 
251
        }
 
252
        return artifacts;
 
253
    }
 
254
 
 
255
    private void copyTemplateResource(String file, boolean filter) throws MojoExecutionException {
 
256
        try {
 
257
            File target = FileUtils.resolveFile(packageDirectory, file);
 
258
            if( target.isFile() && target.canRead() ) {
 
259
                return;
 
260
            }
 
261
            URL source = getClass().getClassLoader().getResource("project-template/" + file);
 
262
            File tmp = FileUtils.createTempFile("tmp", "txt", new File(project.getBuild().getDirectory()));
 
263
            try {
 
264
                FileUtils.copyURLToFile(source, tmp);
 
265
                FileUtils.copyFile(tmp, target, encoding, filters(filter), true);
 
266
            } finally {
 
267
                tmp.delete();
 
268
            }
 
269
        } catch (IOException e) {
 
270
            throw new MojoExecutionException("Could not extract template resource: "+file, e);
 
271
        }
 
272
    }
 
273
 
 
274
    @SuppressWarnings("unchecked")
 
275
    private FilterWrapper[] filters(boolean filter) throws IOException {
 
276
        if( !filter ) {
 
277
            return new FilterWrapper[0];
 
278
        }
 
279
        
 
280
        final String startExp = "@";
 
281
        final String endExp = "@";
 
282
        final String escapeString = "\\";
 
283
        final Map<String,String> values = new HashMap<String,String>();
 
284
        values.put("PROJECT_NAME", name);
 
285
        values.put("PROJECT_NAME_UNDER_SCORE", name.replaceAll("\\W", "_"));
 
286
        values.put("VERSION", project.getVersion());
 
287
        
 
288
        List<String> files = new ArrayList<String>();
 
289
        files.addAll(FileUtils.getFileNames(targetSrcDir, "**/*.c", null, false));
 
290
        files.addAll(FileUtils.getFileNames(targetSrcDir, "**/*.cpp", null, false));
 
291
        files.addAll(FileUtils.getFileNames(targetSrcDir, "**/*.cxx", null, false));
 
292
        String sources = "";
 
293
        String xml_sources = "";
 
294
        boolean first = true;
 
295
        for (String f : files) {
 
296
            if( !first ) {
 
297
                sources += "\\\n";
 
298
            } else {
 
299
                values.put("FIRST_SOURCE_FILE", "src/"+f.replace('\\', '/'));
 
300
                first=false;
 
301
            }
 
302
            sources += "  src/"+f;
 
303
            
 
304
            xml_sources+="      <File RelativePath=\".\\src\\"+ (f.replace('/', '\\')) +"\"/>\n";
 
305
        }
 
306
        
 
307
        values.put("PROJECT_SOURCES", sources);
 
308
        values.put("PROJECT_XML_SOURCES", xml_sources);
 
309
 
 
310
        
 
311
        FileUtils.FilterWrapper wrapper = new FileUtils.FilterWrapper() {
 
312
            public Reader getReader(Reader reader) {
 
313
                StringSearchInterpolator propertiesInterpolator = new StringSearchInterpolator(startExp, endExp);
 
314
                propertiesInterpolator.addValueSource(new MapBasedValueSource(values));
 
315
                propertiesInterpolator.setEscapeString(escapeString);
 
316
                InterpolatorFilterReader interpolatorFilterReader = new InterpolatorFilterReader(reader, propertiesInterpolator, startExp, endExp);
 
317
                interpolatorFilterReader.setInterpolateWithPrefixPattern(false);
 
318
                return interpolatorFilterReader;
 
319
            }
 
320
        };
 
321
        return new FilterWrapper[] { wrapper };
 
322
    }
 
323
    
 
324
 
 
325
}