source: trunk/docx4j/src/main/java/org/docx4j/utils/JarCheck.java @ 1721

Revision 1721, 10.4 KB checked in by jharrop, 6 months ago (diff)

Include Java 1.7 class number

Line 
1/*
2 * [JarCheck.java]
3 *
4 * Summary: Ensures javac -target versions of the class files in a jar are as expected.
5 *
6 * Copyright: (c) 2006-2011 Roedy Green, Canadian Mind Products, http://mindprod.com
7 *
8 * Licence: This software may be copied and used freely for any purpose but military.
9 *          http://mindprod.com/contact/nonmil.html
10 *
11 * Requires: JDK 1.5+
12 *
13 * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
14 *
15 * Version History:
16 *  1.0 2006-01-16 initial version
17 *  1.1 2006-01-16
18 *  1.2 2006-03-05 reformat with IntelliJ, add Javadoc
19 *  1.3 2008-04-21 display version number of each class file checked.
20 */
21package org.docx4j.utils;
22
23import java.io.EOFException;
24import java.io.File;
25import java.io.FileInputStream;
26import java.io.IOException;
27import java.util.HashMap;
28import java.util.zip.ZipEntry;
29import java.util.zip.ZipInputStream;
30
31import static java.lang.System.err;
32import static java.lang.System.out;
33/*
34TODO: check class minor version as well.
35     */
36
37/**
38 * Ensures javac -target versions of the class files in a jar are as expected.
39 *
40 * @author Roedy Green, Canadian Mind Products
41 * @version 1.3 2008-04-21 display version number of each class file checked.
42 * @since 2006-01-16
43 *
44 * Modified by Jason Harrop 2011 06 25
45 * Note re Java 1.5, 1.6 behaviour.
46 * In 1.5, you can't put @Override on something which merely
47 * implements an interface
48 * Eclipse will give an error if you do (and have source set to 1.5).
49 * Maven and ant won't give an error, and if you have target=1.5
50 * (as we do for docx4j), will correctly produce 1.5 code.
51 * This class allows us to check that all our dependencies are
52 * also 1.5.
53 * An alternative way of doing it would be to use clirr.sourceforge.net
54 * which can run as an ant task, or from a command line, but I haven't
55 * tried that.
56 *
57 */
58public final class JarCheck
59    {
60    // ------------------------------ CONSTANTS ------------------------------
61
62    /**
63     * how many bytes at beginning of class file we read<br /> 4=ca-fe-ba-be + 2=minor + 2=major
64     */
65    private static final int chunkLength = 8;
66
67    /**
68     * undisplayed copyright notice
69     */
70    public static final String EMBEDDED_COPYRIGHT =
71            "Copyright: (c) 2006-2011 Roedy Green, Canadian Mind Products, http://mindprod.com";
72
73    private static final String RELEASE_DATE = "2008-04-21";
74
75    /**
76     * embedded version string.
77     */
78    public static final String VERSION_STRING = "1.3";
79
80    /**
81     * translate class file major version number to human JVM version
82     */
83    private static final HashMap<Integer, String> convertMachineToHuman =
84            new HashMap<Integer, String>( 23 );
85
86    /**
87     * translate from human JDK version to class file major version number
88     */
89    private static final HashMap<String, Integer> convertHumanToMachine =
90            new HashMap<String, Integer>( 23 );
91
92    /**
93     * expected first 4 bytes of a class file
94     */
95    private static final byte[] expectedMagicNumber =
96            { ( byte ) 0xca, ( byte ) 0xfe, ( byte ) 0xba, ( byte ) 0xbe };
97
98    // -------------------------- STATIC METHODS --------------------------
99
100    static
101        {
102        convertHumanToMachine.put( "1.0", 44 );
103        convertHumanToMachine.put( "1.1", 45 );
104        convertHumanToMachine.put( "1.2", 46 );
105        convertHumanToMachine.put( "1.3", 47 );
106        convertHumanToMachine.put( "1.4", 48 );
107        convertHumanToMachine.put( "1.5", 49 );
108        convertHumanToMachine.put( "1.6", 50 );
109        convertHumanToMachine.put( "1.7", 51 );
110        }
111
112    static
113        {
114        convertMachineToHuman.put( 44, "1.0" );
115        convertMachineToHuman.put( 45, "1.1" );
116        convertMachineToHuman.put( 46, "1.2" );
117        convertMachineToHuman.put( 47, "1.3" );
118        convertMachineToHuman.put( 48, "1.4" );
119        convertMachineToHuman.put( 49, "1.5" );
120        convertMachineToHuman.put( 50, "1.6" );
121        convertMachineToHuman.put( 51, "1.7" );
122        }
123
124    /**
125     * check one jar to make sure all class files have compatible versions.
126     *
127     * @param jarFilename name of jar file whose classes are to be tested.
128     * @param low         low bound for major version e.g. 44
129     * @param high        high bound for major version. e.g. 50
130     *
131     * @return true if all is ok. False if not, with long on System.err of problems.
132     */
133    private static boolean checkJar( String jarFilename, int low, int high )
134        {
135        out.println( "Checking jar " + jarFilename );
136        boolean success = true;
137        FileInputStream fis;
138        ZipInputStream zip = null;
139       
140        int lowest = 1000;
141        int highest = 0;
142       
143        try
144            {
145            try
146                {
147                fis = new FileInputStream( jarFilename );
148                zip = new ZipInputStream( fis );
149
150                // loop for each jar entry
151                entryLoop:
152                       
153                       
154                while ( true )
155                    {
156                    ZipEntry entry = zip.getNextEntry();
157                    if ( entry == null )
158                        {
159                        break;
160                        }
161                    // relative name with slashes to separate dirnames.
162                    String elementName = entry.getName();
163                    //System.out.println(elementName);
164                    if ( !elementName.endsWith( ".class" ) )
165                        {
166                        // ignore anything but a .final class file
167                        continue;
168                        }
169                    byte[] chunk = new byte[ chunkLength ];
170                    int bytesRead = zip.read( chunk, 0, chunkLength );
171                    zip.closeEntry();
172                    if ( bytesRead != chunkLength )
173                        {
174                        err.println( ">> Corrupt class file: "
175                                     + elementName );
176                        success = false;
177                        continue;
178                        }
179                    // make sure magic number signature is as expected.
180                    for ( int i = 0; i < expectedMagicNumber.length; i++ )
181                        {
182                        if ( chunk[ i ] != expectedMagicNumber[ i ] )
183                            {
184                            err.println( ">> Bad magic number in "
185                                         + elementName );
186                            success = false;
187                            continue entryLoop;
188                            }
189                        }
190                    /*
191                    * pick out big-endian ushort major version in last two
192                    * bytes of chunk
193                    */
194                    int major =
195                            ( ( chunk[ chunkLength - 2 ] & 0xff ) << 8 ) + (
196                                    chunk[ chunkLength - 1 ]
197                                    & 0xff );
198                    /* F I N A L L Y. All this has been leading up to this TEST */
199                   
200                    if (major>highest) highest=major;
201                    if (major<lowest) {
202                        lowest=major;
203                    }
204                   
205                    if ( low <= major && major <= high )
206                        {
207//                        out.print( "   OK " );
208//                        out.println( convertMachineToHuman.get( major )
209//                                     + " ("
210//                                     + major
211//                                     + ") "
212//                                     + elementName );
213                        // leave success set as previously
214                        }
215                    else
216                        {
217//                        err.println( ">> Wrong Version " );
218//                        err.println( convertMachineToHuman.get( major )
219//                                     + " ("
220//                                     + major
221//                                     + ") "
222//                                     + elementName );
223//                        success = false;
224                        }
225                    }
226                // end while
227                }
228            catch ( EOFException e )
229                {
230                // normal exit
231               
232                }
233            zip.close();
234           
235                if (lowest==highest) {
236                        System.out.println( convertMachineToHuman.get( highest ));
237                } else {
238                        System.out.println( convertMachineToHuman.get( lowest ) + "-" + convertMachineToHuman.get( highest ));
239                       
240                }
241           
242            return success;
243            }
244        catch ( IOException e )
245            {
246            err.println( ">> Problem reading jar file." );
247            return false;
248            }
249        }
250
251    // --------------------------- main() method ---------------------------
252
253    /**
254     * Main command line jarfileName lowVersion highVersion e.g. myjar.jar 1.0 1.6
255     *
256     * @param args rot used
257     */
258    public static void main( String[] args )
259        {
260//            if ( args.length != 3 )
261//                {
262//                err.println( "usage: java -ea -jar jarcheck.jar jarFileName.jar 1.1 1.6" );
263//                System.exit( 2 );
264//                }
265//            String jarFilename = args[ 0 ];
266
267//          int low = convertHumanToMachine.get( args[ 1 ] );
268//          int high = convertHumanToMachine.get( args[ 2 ] );
269         
270        int low  = convertHumanToMachine.get( "1.3" );
271        int high = convertHumanToMachine.get( "1.5" );
272           
273            String dirPath = System.getProperty("user.dir") + "/dist/";
274           
275            File dir = new File(dirPath);
276           
277            if (dir.isDirectory() ) {
278               
279                File[] files = dir.listFiles();
280                for (int i=0 ; i<files.length; i++) {
281                       
282                        if (files[i].isFile() && files[i].getName().endsWith("jar")) {
283                               
284                        System.out.println(files[i].getName() );
285                        boolean success = checkJar( files[i].getAbsolutePath(), low, high );
286                        System.out.println(success);
287                       
288                    }                           
289                }
290            }
291}
292        }
Note: See TracBrowser for help on using the repository browser.