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