001 /* 002 * Copyright 2001,2004 The Apache Software Foundation. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.apache.commons.jjar; 018 019 import java.lang.Package; 020 021 import java.util.ArrayList; 022 import java.util.Iterator; 023 import java.util.Collection; 024 import java.util.Map; 025 import java.util.List; 026 import java.util.StringTokenizer; 027 import java.util.Enumeration; 028 029 import java.util.jar.JarFile; 030 import java.util.jar.Manifest; 031 import java.util.jar.Attributes; 032 import java.util.jar.JarInputStream; 033 import java.util.jar.JarOutputStream; 034 import java.util.jar.JarEntry; 035 036 import java.io.File; 037 import java.io.FileOutputStream; 038 import java.io.BufferedInputStream; 039 import java.io.BufferedOutputStream; 040 import java.io.InputStream; 041 import java.io.ByteArrayOutputStream; 042 043 import java.net.JarURLConnection; 044 import java.net.URLConnection; 045 import java.net.URL; 046 047 048 /** 049 * classpath support for JJAR. This is currently a jumble - will 050 * clean up. 051 * 052 * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a> 053 * @version $Id: ClasspathUtil.java 155454 2005-02-26 13:23:34Z dirkv $ 054 */ 055 public class ClasspathUtil 056 { 057 /** 058 * current default repository 059 */ 060 061 public static String getDefaultRepository() 062 { 063 return "http://jakarta.apache.org/jjar/"; 064 } 065 066 /** 067 * lists the jars currently in the classpath 068 */ 069 public static void listJars( String path ) 070 { 071 List jars = getJarList( path ); 072 073 Iterator i = jars.iterator(); 074 075 while( i.hasNext() ) 076 { 077 String jar = (String) i.next(); 078 System.out.println(" inspecting : " + jar ); 079 } 080 081 return; 082 } 083 084 /** 085 * checks to see if the classpath <code>path</code> contains 086 * the package / version 087 */ 088 public static boolean containsVersionedJar( String path, String pkg, String version) 089 { 090 List jars = getJarList( path ); 091 092 /* 093 * now, with this set of jars, see if we can find those that match 094 * the package name 095 */ 096 097 Iterator i = jars.iterator(); 098 099 while( i.hasNext() ) 100 { 101 String jar = (String) i.next(); 102 103 try 104 { 105 URL url = new URL("jar:file:" + jar + "!/"); 106 JarURLConnection conn = (JarURLConnection) url.openConnection(); 107 108 if (packageMatch( conn, pkg, version ) ) 109 { 110 // System.out.println( jar + " : pkg = " + pkg + " ver = " + version ); 111 112 return true; 113 } 114 } 115 catch( Exception e ) 116 { 117 //System.out.println("Exception (continuing) : " + e ); 118 } 119 } 120 121 return false; 122 } 123 124 /** 125 * returns a JJARPackage( info ) for a given jar 126 */ 127 public static JJARPackage getPackage( String jarname ) 128 throws Exception 129 { 130 URL url = new URL("jar:file:" + jarname + "!/"); 131 JarURLConnection conn = (JarURLConnection) url.openConnection(); 132 133 return getPackage( conn ); 134 } 135 136 public static JJARPackage getPackage( JarURLConnection jarConn ) 137 throws Exception 138 { 139 if (jarConn == null) 140 return null; 141 142 Manifest mfst = jarConn.getManifest(); 143 144 if (mfst == null) 145 { 146 return null; 147 } 148 149 /* 150 * get the attributes we care about 151 */ 152 153 Attributes att = mfst.getMainAttributes(); 154 155 String jarpkg = att.getValue( Attributes.Name.IMPLEMENTATION_TITLE ); 156 String jarver = att.getValue( Attributes.Name.IMPLEMENTATION_VERSION ); 157 158 if (jarpkg == null || jarver == null) 159 { 160 /* 161 * unusable 162 */ 163 164 return null; 165 } 166 167 return new JJARPackage( jarpkg, jarver ); 168 } 169 170 /** 171 * determines if two packages are equal 172 */ 173 public static boolean packageMatch( JarURLConnection jarConn, String pkg, String version ) 174 throws Exception 175 { 176 JJARPackage jjarp = getPackage( jarConn ); 177 178 if ( jjarp == null) 179 return false; 180 181 /* 182 * compare 183 */ 184 185 return jjarp.equals( pkg, version ); 186 } 187 188 189 /** 190 * returns a list of jars in the specified claspath. 191 * will check the system classpath by default 192 */ 193 public static List getJarList( String path ) 194 { 195 if (path == null) 196 { 197 path = "java.class.path"; 198 } 199 200 String classpath = System.getProperty( path ); 201 String pathSep = System.getProperty("path.separator"); 202 203 /* 204 * take the classpath, and look for jars 205 */ 206 207 StringTokenizer st = new StringTokenizer( classpath, pathSep ); 208 209 ArrayList jars = new ArrayList(); 210 211 while( st.hasMoreTokens() ) 212 { 213 String foo = st.nextToken(); 214 215 if ( foo.indexOf("jar") != -1 ) 216 jars.add(foo); 217 } 218 219 return jars; 220 } 221 222 public static void main( String args[] ) 223 { 224 /* 225 * see if the default classpath has the jar we need 226 */ 227 if ( ClasspathUtil.containsVersionedJar( null, "commons-beanutils", "0.1") ) 228 System.out.println("Found commons-beanutils v0.1"); 229 else 230 { 231 /* 232 * didn't find it... 233 */ 234 235 try 236 { 237 /* 238 * so go to the repository 239 */ 240 241 URL url = new URL("jar:file:/home/gmj/jakarta/jakarta-commons/beanutils/dist/commons-beanutils.jar!/"); 242 JarURLConnection conn = (JarURLConnection) url.openConnection(); 243 244 /* 245 * ensure that it's right 246 */ 247 248 if (!packageMatch( conn, "commons-beanutils", "0.1" )) 249 { 250 System.out.println("repository doesn't have it"); 251 return; 252 } 253 254 System.out.println("jar in repository correct. Fetching"); 255 256 String jar = "commons-beanutils-0.1.jar"; 257 258 url = new URL("file:/home/gmj/jakarta/jakarta-commons/beanutils/dist/commons-beanutils.jar"); 259 URLConnection uconn = (URLConnection) url.openConnection(); 260 261 Transport.fetchJar( uconn, jar ); 262 263 /* 264 * add to classpath and verify 265 */ 266 267 String classpath = System.getProperty( "java.class.path" ); 268 String pathSep = System.getProperty("path.separator"); 269 270 classpath = classpath + pathSep + jar; 271 272 System.setProperty("java.class.path", classpath); 273 274 if ( ClasspathUtil.containsVersionedJar( null, "commons-beanutils", "0.1") ) 275 System.out.println("Found commons-beanutils v0.1"); 276 277 } 278 catch( Exception e ) 279 { 280 System.out.println("exception " + e ); 281 } 282 } 283 284 } 285 286 /** 287 * doesn't work. don't use 288 */ 289 public static boolean markJar( String jarname, String packagename, String version ) 290 throws Exception 291 { 292 JarFile jf = new JarFile( jarname ); 293 294 Manifest mfst = jf.getManifest(); 295 296 if (mfst == null) 297 { 298 return false; 299 } 300 301 /* 302 * set the attributes we care about 303 */ 304 305 Attributes att = mfst.getMainAttributes(); 306 307 Object a = att.put( Attributes.Name.IMPLEMENTATION_TITLE, packagename ); 308 Object b = att.put( Attributes.Name.IMPLEMENTATION_VERSION, version ); 309 310 System.out.println(" Object a " + a ); 311 System.out.println(" Object b " + b ); 312 313 JarOutputStream jos = new JarOutputStream( new FileOutputStream( new File( jarname + "-jjar"))); 314 byte[] buffer = new byte[1024]; 315 int bytesRead; 316 317 for( Enumeration e = jf.entries(); e.hasMoreElements(); ) 318 { 319 JarEntry entry = (JarEntry) e.nextElement(); 320 321 if( entry.getName().equals("META-INF/MANIFEST.MF")) 322 { 323 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 324 325 mfst.write( baos ); 326 327 JarEntry ee = new JarEntry( entry ); 328 329 ee.setSize(baos.size() ); 330 331 jos.putNextEntry(ee ); 332 mfst.write( jos ); 333 continue; 334 } 335 336 System.out.println(" Name : " + entry.getName() ); 337 338 InputStream entryStream = jf.getInputStream( entry); 339 340 jos.putNextEntry(entry ); 341 342 while ((bytesRead = entryStream.read(buffer)) != -1) 343 { 344 jos.write(buffer, 0, bytesRead); 345 } 346 } 347 348 jos.close(); 349 jf.close(); 350 351 return true; 352 } 353 } 354 355 356 357 358 359 360 361