001    /**
002     * Copyright (C) 2009 Progress Software, Inc.
003     * http://fusesource.com
004     * 
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     * 
009     *    http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.fusesource.hawtjni.maven;
018    
019    import java.io.File;
020    import java.util.List;
021    
022    import org.apache.maven.plugin.AbstractMojo;
023    import org.apache.maven.plugin.MojoExecutionException;
024    import org.apache.maven.project.MavenProject;
025    import org.apache.maven.project.MavenProjectHelper;
026    import org.codehaus.plexus.archiver.jar.JarArchiver;
027    import org.codehaus.plexus.archiver.jar.Manifest;
028    import org.codehaus.plexus.archiver.jar.Manifest.Attribute;
029    import org.codehaus.plexus.archiver.manager.ArchiverManager;
030    import org.fusesource.hawtjni.runtime.Library;
031    
032    /**
033     * This goal allows allows you to package the JNI library created by build goal
034     * in a JAR which the HawtJNI runtime can unpack when the library needs to be
035     * loaded.
036     * 
037     * This platform specific jar is attached with a classifier which matches the
038     * current platform.
039     * 
040     * @goal package-jar
041     * @phase package
042     * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
043     */
044    public class PackageJarMojo extends AbstractMojo {
045    
046        /**
047         * The maven project.
048         * 
049         * @parameter expression="${project}"
050         * @required
051         * @readonly
052         */
053        protected MavenProject project;
054    
055        /**
056         * The base name of the library, used to determine generated file names.
057         * 
058         * @parameter default-value="${project.artifactId}"
059         */
060        private String name;
061    
062        /**
063         * @component
064         * @required
065         * @readonly
066         */
067        private ArchiverManager archiverManager;
068    
069        /**
070         * @component
071         * @required
072         * @readonly
073         */
074        private MavenProjectHelper projectHelper;
075    
076        /**
077         * The output directory where the built JNI library will placed. This
078         * directory will be added to as a test resource path so that unit tests can
079         * verify the built JNI library.
080         * 
081         * The library will placed under the META-INF/native/${platform} directory
082         * that the HawtJNI Library uses to find JNI libraries as classpath
083         * resources.
084         * 
085         * @parameter 
086         *            default-value="${project.build.directory}/generated-sources/hawtjni/lib"
087         */
088        private File libDirectory;
089        
090        /**
091         * The platform identifier of this build.  If not specified,
092         * it will be automatically detected.  This will be used as the 
093         * artifact classifier for the platform specific jar.
094         * 
095         * @parameter default-value="${hawtjni-platform}"
096         */
097        private String platform;     
098    
099        /**
100         * The osgi platforms that the library match for.  Example value:
101         * osname=MacOS;processor=x86-64
102         * 
103         * @parameter 
104         */
105        private List<String> osgiPlatforms;
106    
107        public void execute() throws MojoExecutionException {
108            try {
109    
110                Library library = new Library(name);
111                if (platform == null || platform.trim().length()==0 ) {
112                    platform = library.getPlatform();
113                }
114    
115                String packageName = project.getArtifactId() + "-" + project.getVersion() + "-" + platform;
116                JarArchiver archiver = (JarArchiver) archiverManager.getArchiver("jar");
117    
118                File packageFile = new File(new File(project.getBuild().getDirectory()), packageName + ".jar");
119                archiver.setDestFile(packageFile);
120                archiver.setIncludeEmptyDirs(true);
121                archiver.addDirectory(libDirectory);
122    
123                Manifest manifest = new Manifest();
124                manifest.addConfiguredAttribute(new Attribute("Bundle-SymbolicName", project.getArtifactId() + "-" + platform));
125                manifest.addConfiguredAttribute(new Attribute("Bundle-Name", name + " for " + platform));            
126                manifest.addConfiguredAttribute(new Attribute("Bundle-NativeCode", getNativeCodeValue(library)));
127                manifest.addConfiguredAttribute(new Attribute("Bundle-Version", project.getVersion()));
128                manifest.addConfiguredAttribute(new Attribute("Bundle-ManifestVersion", "2"));
129                manifest.addConfiguredAttribute(new Attribute("Bundle-Description", project.getDescription()));
130                archiver.addConfiguredManifest(manifest);
131    
132                archiver.createArchive();
133    
134                projectHelper.attachArtifact(project, "jar", platform, packageFile);
135    
136            } catch (Exception e) {
137                throw new MojoExecutionException("packageing failed: " + e, e);
138            }
139        }
140        
141        public String getNativeCodeValue(Library library) {
142            if (osgiPlatforms == null || osgiPlatforms.isEmpty() ) {
143                return library.getPlatformSpecifcResourcePath(platform) + ";" +"osname=" + getOsgiOSName() + ";processor=" + getOsgiProcessor()+ ",*";
144            }
145            boolean first=true;
146            String rc = "";
147            for (String s : osgiPlatforms) {
148                if( !first ) {
149                    rc += ",";
150                }
151                first = false;
152                if( "*".equals(s) ) {
153                    rc += s;
154                } else {
155                    rc += library.getPlatformSpecifcResourcePath(platform) + ";"+s;
156                }
157            }
158            return rc;
159        }
160    
161        public String getOsgiOSName() {
162            String name = System.getProperty("os.name");
163    
164            String trimmed = name.toLowerCase().trim();
165            if (trimmed.startsWith("win")) {
166                return "Win32";
167            } else if (trimmed.startsWith("linux")) {
168                return "Linux";
169            } else if (trimmed.startsWith("macos") || trimmed.startsWith("mac os")) {
170                return "MacOS";
171            } else if (trimmed.startsWith("aix")) {
172                return "AIX";
173            } else if (trimmed.startsWith("hpux")) {
174                return "HPUX";
175            } else if (trimmed.startsWith("irix")) {
176                return "IRIX";
177            } else if (trimmed.startsWith("netware")) {
178                return "Netware";
179            } else if (trimmed.startsWith("openbsd")) {
180                return "OpenBSD";
181            } else if (trimmed.startsWith("netbsd")) {
182                return "NetBSD";
183            } else if (trimmed.startsWith("os2") || trimmed.startsWith("os/2")) {
184                return "OS2";
185            } else if (trimmed.startsWith("qnx") || trimmed.startsWith("procnto")) {
186                return "QNX";
187            } else if (trimmed.startsWith("solaris")) {
188                return "Solaris";
189            } else if (trimmed.startsWith("sunos")) {
190                return "SunOS";
191            } else if (trimmed.startsWith("vxworks")) {
192                return "VxWorks";
193            }
194            return name;
195        }
196    
197        public String getOsgiProcessor() {
198            String name = System.getProperty("os.arch");
199            String trimmed = name.toLowerCase().trim();
200            if (trimmed.startsWith("x86-64") || trimmed.startsWith("amd64") || trimmed.startsWith("em64") || trimmed.startsWith("x86_64")) {
201                return "x86-64";
202            } else if (trimmed.startsWith("x86") || trimmed.startsWith("pentium") || trimmed.startsWith("i386") 
203                    || trimmed.startsWith("i486") || trimmed.startsWith("i586") || trimmed.startsWith("i686")) {
204                return "x86";
205            } else if (trimmed.startsWith("68k")) {
206                return "68k";
207            } else if (trimmed.startsWith("arm")) {
208                return "ARM";
209            } else if (trimmed.startsWith("alpha")) {
210                return "Alpha";
211            } else if (trimmed.startsWith("ignite") || trimmed.startsWith("psc1k")) {
212                return "Ignite";
213            } else if (trimmed.startsWith("mips")) {
214                return "Mips";
215            } else if (trimmed.startsWith("parisc")) {
216                return "PArisc";
217            } else if (trimmed.startsWith("powerpc") || trimmed.startsWith("power") || trimmed.startsWith("ppc")) {
218                return "PowerPC";
219            } else if (trimmed.startsWith("sparc")) {
220                return "Sparc";
221            }
222            return name;
223        }
224    
225    }