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