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.project.MavenProject; 025import org.apache.maven.project.MavenProjectHelper; 026import org.codehaus.plexus.archiver.jar.JarArchiver; 027import org.codehaus.plexus.archiver.jar.Manifest; 028import org.codehaus.plexus.archiver.jar.Manifest.Attribute; 029import org.codehaus.plexus.archiver.manager.ArchiverManager; 030import 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 prepare-package 042 * @author <a href="http://hiramchirino.com">Hiram Chirino</a> 043 */ 044public 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. 093 * 094 * @parameter 095 */ 096 private String platform; 097 098 /** 099 * Should a classifier of the native jar be set 100 * to match the platform? 101 * 102 * @parameter default-value="true" 103 */ 104 private boolean classified; 105 106 /** 107 * The osgi platforms that the library match for. Example value: 108 * osname=MacOS;processor=x86-64 109 * 110 * @parameter 111 */ 112 private List<String> osgiPlatforms; 113 114 public void execute() throws MojoExecutionException { 115 try { 116 117 Library library = new Library(name); 118 if (platform == null) { 119 platform = Library.getPlatform(); 120 } 121 122 String classifier = null; 123 if( classified ) { 124 classifier = platform; 125 126 String packageName = project.getArtifactId() + "-" + project.getVersion() + "-" + platform; 127 JarArchiver archiver = (JarArchiver) archiverManager.getArchiver("jar"); 128 129 File packageFile = new File(new File(project.getBuild().getDirectory()), packageName + ".jar"); 130 archiver.setDestFile(packageFile); 131 archiver.setIncludeEmptyDirs(true); 132 archiver.addDirectory(libDirectory); 133 134 Manifest manifest = new Manifest(); 135 manifest.addConfiguredAttribute(new Attribute("Bundle-SymbolicName", project.getArtifactId() + "-" + platform)); 136 manifest.addConfiguredAttribute(new Attribute("Bundle-Name", name + " for " + platform)); 137 manifest.addConfiguredAttribute(new Attribute("Bundle-NativeCode", getNativeCodeValue(library))); 138 manifest.addConfiguredAttribute(new Attribute("Bundle-Version", project.getVersion())); 139 manifest.addConfiguredAttribute(new Attribute("Bundle-ManifestVersion", "2")); 140 manifest.addConfiguredAttribute(new Attribute("Bundle-Description", project.getDescription())); 141 archiver.addConfiguredManifest(manifest); 142 143 archiver.createArchive(); 144 145 projectHelper.attachArtifact(project, "jar", classifier, packageFile); 146 147 } else { 148 projectHelper.addResource(project, libDirectory.getCanonicalPath(), null, null); 149 } 150 151 } catch (Exception e) { 152 throw new MojoExecutionException("packaging failed: " + e, e); 153 } 154 } 155 156 public String getNativeCodeValue(Library library) { 157 if (osgiPlatforms == null || osgiPlatforms.isEmpty() ) { 158 return library.getPlatformSpecificResourcePath(platform) + ";" +"osname=" + getOsgiOSName() + ";processor=" + getOsgiProcessor()+ ",*"; 159 } 160 boolean first=true; 161 String rc = ""; 162 for (String s : osgiPlatforms) { 163 if( !first ) { 164 rc += ","; 165 } 166 first = false; 167 if( "*".equals(s) ) { 168 rc += s; 169 } else { 170 rc += library.getPlatformSpecificResourcePath(platform) + ";"+s; 171 } 172 } 173 return rc; 174 } 175 176 public String getOsgiOSName() { 177 String name = System.getProperty("os.name"); 178 179 String trimmed = name.toLowerCase().trim(); 180 if (trimmed.startsWith("win")) { 181 return "Win32"; 182 } else if (trimmed.startsWith("linux")) { 183 return "Linux"; 184 } else if (trimmed.startsWith("macos") || trimmed.startsWith("mac os")) { 185 return "MacOS"; 186 } else if (trimmed.startsWith("aix")) { 187 return "AIX"; 188 } else if (trimmed.startsWith("hpux")) { 189 return "HPUX"; 190 } else if (trimmed.startsWith("irix")) { 191 return "IRIX"; 192 } else if (trimmed.startsWith("netware")) { 193 return "Netware"; 194 } else if (trimmed.startsWith("openbsd")) { 195 return "OpenBSD"; 196 } else if (trimmed.startsWith("netbsd")) { 197 return "NetBSD"; 198 } else if (trimmed.startsWith("os2") || trimmed.startsWith("os/2")) { 199 return "OS2"; 200 } else if (trimmed.startsWith("qnx") || trimmed.startsWith("procnto")) { 201 return "QNX"; 202 } else if (trimmed.startsWith("solaris")) { 203 return "Solaris"; 204 } else if (trimmed.startsWith("sunos")) { 205 return "SunOS"; 206 } else if (trimmed.startsWith("vxworks")) { 207 return "VxWorks"; 208 } 209 return name; 210 } 211 212 public String getOsgiProcessor() { 213 String name = System.getProperty("os.arch"); 214 String trimmed = name.toLowerCase().trim(); 215 if (trimmed.startsWith("x86-64") || trimmed.startsWith("amd64") || trimmed.startsWith("em64") || trimmed.startsWith("x86_64")) { 216 return "x86-64"; 217 } else if (trimmed.startsWith("x86") || trimmed.startsWith("pentium") || trimmed.startsWith("i386") 218 || trimmed.startsWith("i486") || trimmed.startsWith("i586") || trimmed.startsWith("i686")) { 219 return "x86"; 220 } else if (trimmed.startsWith("68k")) { 221 return "68k"; 222 } else if (trimmed.startsWith("arm")) { 223 return "ARM"; 224 } else if (trimmed.startsWith("alpha")) { 225 return "Alpha"; 226 } else if (trimmed.startsWith("ignite") || trimmed.startsWith("psc1k")) { 227 return "Ignite"; 228 } else if (trimmed.startsWith("mips")) { 229 return "Mips"; 230 } else if (trimmed.startsWith("parisc")) { 231 return "PArisc"; 232 } else if (trimmed.startsWith("powerpc") || trimmed.startsWith("power") || trimmed.startsWith("ppc")) { 233 return "PowerPC"; 234 } else if (trimmed.startsWith("sparc")) { 235 return "Sparc"; 236 } 237 return name; 238 } 239 240}