001    /*
002     * Copyright 2002-2006 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    
027    package sun.tools.javap;
028    
029    import java.util.*;
030    import java.io.*;
031    import java.util.jar.*;
032    
033    
034    /**
035     * Strores flag values according to command line options
036     * and sets path where to find classes.
037     *
038     * @author  Sucheta Dambalkar
039     */
040    public class JavapEnvironment {
041    
042        //Access flags
043        public static final int PRIVATE = 0;
044        public static final int PROTECTED  = 1;
045        public static final int PACKAGE = 2;
046        public static final int PUBLIC  = 3;
047    
048        //search path flags.
049        private static final int start = 0;
050        private static final int  cmdboot= 1;
051        private static final int sunboot = 2;
052        private static final int  javaclass= 3;
053        private static final int  cmdextdir= 4;
054        private static final int  javaext= 5;
055        private static final int  cmdclasspath= 6;
056        private static final int  envclasspath= 7;
057        private static final int  javaclasspath= 8;
058        private static final int  currentdir = 9;
059    
060    
061        // JavapEnvironment flag settings
062        boolean showLineAndLocal = false;
063        int showAccess = PACKAGE;
064        boolean showDisassembled = false;
065        boolean showVerbose = false;
066        boolean showInternalSigs = false;
067        String classPathString = null;
068        String bootClassPathString = null;
069        String extDirsString = null;
070        boolean extDirflag = false;
071        boolean nothingToDo = true;
072        boolean showallAttr = false;
073        String classpath = null;
074        int searchpath = start;
075    
076        /**
077         *  According to which flags are set,
078         *  returns file input stream for classfile to disassemble.
079         */
080    
081        public InputStream getFileInputStream(String Name){
082            InputStream fileInStream = null;
083            searchpath = cmdboot;
084            try{
085                if(searchpath == cmdboot){
086                    if(bootClassPathString != null){
087                        //search in specified bootclasspath.
088                        classpath = bootClassPathString;
089                        if((fileInStream = resolvefilename(Name)) != null) return fileInStream;
090                        //no classes found in search path.
091                        else searchpath = cmdextdir;
092                    }
093                    else searchpath = sunboot;
094                }
095    
096                if(searchpath == sunboot){
097                    if(System.getProperty("sun.boot.class.path") != null){
098                        //search in sun.boot.class.path
099                        classpath = System.getProperty("sun.boot.class.path");
100                        if((fileInStream = resolvefilename(Name)) != null) return fileInStream;
101                        //no classes found in search path
102                        else searchpath = cmdextdir;
103                    }
104                    else searchpath = javaclass;
105                }
106    
107                if(searchpath == javaclass){
108                    if(System.getProperty("java.class.path") != null){
109                        //search in java.class.path
110                        classpath =System.getProperty("java.class.path");
111                        if((fileInStream = resolvefilename(Name)) != null) return fileInStream;
112                        //no classes found in search path
113                        else searchpath = cmdextdir;
114                    }
115                    else searchpath = cmdextdir;
116                }
117    
118                if(searchpath == cmdextdir){
119                    if(extDirsString != null){
120                        //search in specified extdir.
121                        classpath = extDirsString;
122                        extDirflag = true;
123                        if((fileInStream = resolvefilename(Name)) != null) return fileInStream;
124                        //no classes found in search path
125                        else {
126                            searchpath = cmdclasspath;
127                            extDirflag = false;
128                        }
129                    }
130                    else searchpath = javaext;
131                }
132    
133                if(searchpath == javaext){
134                    if(System.getProperty("java.ext.dirs") != null){
135                        //search in java.ext.dirs
136                        classpath = System.getProperty("java.ext.dirs");
137                        extDirflag = true;
138                        if((fileInStream = resolvefilename(Name)) != null) return fileInStream;
139                        //no classes found in search path
140                        else {
141                            searchpath = cmdclasspath;
142                            extDirflag = false;
143                        }
144                    }
145                    else searchpath = cmdclasspath;
146                }
147                if(searchpath == cmdclasspath){
148                    if(classPathString != null){
149                        //search in specified classpath.
150                        classpath = classPathString;
151                        if((fileInStream = resolvefilename(Name)) != null) return fileInStream;
152                        //no classes found in search path
153                        else searchpath = 8;
154                    }
155                    else searchpath = envclasspath;
156                }
157    
158                if(searchpath == envclasspath){
159                    if(System.getProperty("env.class.path")!= null){
160                        //search in env.class.path
161                        classpath = System.getProperty("env.class.path");
162                        if((fileInStream = resolvefilename(Name)) != null) return fileInStream;
163                        //no classes found in search path.
164                        else searchpath = javaclasspath;
165                    }
166                    else searchpath = javaclasspath;
167                }
168    
169                if(searchpath == javaclasspath){
170                    if(("application.home") == null){
171                        //search in java.class.path
172                        classpath = System.getProperty("java.class.path");
173                        if((fileInStream = resolvefilename(Name)) != null) return fileInStream;
174                        //no classes found in search path.
175                        else searchpath = currentdir;
176                    }
177                    else searchpath = currentdir;
178                }
179    
180                if(searchpath == currentdir){
181                    classpath = ".";
182                    //search in current dir.
183                    if((fileInStream = resolvefilename(Name)) != null) return fileInStream;
184                    else {
185                        //no classes found in search path.
186                        error("Could not find "+ Name);
187                        System.exit(1);
188                    }
189                }
190            }catch(SecurityException excsec){
191                excsec.printStackTrace();
192                error("fatal exception");
193            }catch(NullPointerException excnull){
194                excnull.printStackTrace();
195                error("fatal exception");
196            }catch(IllegalArgumentException excill){
197                excill.printStackTrace();
198                error("fatal exception");
199            }
200    
201            return null;
202        }
203    
204    
205        public void error(String msg) {
206            System.err.println("ERROR:" +msg);
207        }
208    
209        /**
210         * Resolves file name for classfile to disassemble.
211         */
212        public InputStream resolvefilename(String name){
213            String classname = name.replace('.', '/') + ".class";
214            while (true) {
215                InputStream instream = extDirflag
216                    ? resolveExdirFilename(classname)
217                    : resolveclasspath(classname);
218                if (instream != null)
219                    return instream;
220                int lastindex = classname.lastIndexOf('/');
221                if (lastindex == -1) return null;
222                classname = classname.substring(0, lastindex) + "$" +
223                    classname.substring(lastindex + 1);
224            }
225        }
226    
227        /**
228         * Resolves file name for classfile to disassemble if flag exdir is set.
229         */
230        public InputStream resolveExdirFilename(String classname){
231            if(classpath.indexOf(File.pathSeparator) != -1){
232                //separates path
233                StringTokenizer st = new StringTokenizer(classpath, File.pathSeparator);
234                while(st.hasMoreTokens()){
235                    String path = st.nextToken();
236                    InputStream in = resolveExdirFilenamehelper(path, classname);
237                    if (in != null)
238                        return in;
239                }
240            }else return (resolveExdirFilenamehelper(classpath, classname));
241    
242            return null;
243        }
244    
245        /**
246         * Resolves file name for classfile to disassemble.
247         */
248        public InputStream resolveclasspath(String classname){
249            if(classpath.indexOf(File.pathSeparator) != -1){
250                StringTokenizer st = new StringTokenizer(classpath, File.pathSeparator);
251                //separates path.
252                while(st.hasMoreTokens()){
253                    String path = (st.nextToken()).trim();
254                    InputStream in = resolveclasspathhelper(path, classname);
255                    if(in != null) return in;
256    
257                }
258                return null;
259            }
260            else return (resolveclasspathhelper(classpath, classname));
261        }
262    
263    
264        /**
265         * Returns file input stream for classfile to disassemble if exdir is set.
266         */
267        public InputStream resolveExdirFilenamehelper(String path, String classname){
268            File fileobj = new File(path);
269            if(fileobj.isDirectory()){
270                // gets list of files in that directory.
271                File[] filelist = fileobj.listFiles();
272                for(int i = 0; i < filelist.length; i++){
273                    try{
274                        //file is a jar file.
275                        if(filelist[i].toString().endsWith(".jar")){
276                            JarFile jfile = new JarFile(filelist[i]);
277                            if((jfile.getEntry(classname)) != null){
278    
279                                InputStream filein = jfile.getInputStream(jfile.getEntry(classname));
280                                int bytearraysize = filein.available();
281                                byte []b =  new byte[bytearraysize];
282                                int totalread = 0;
283                                while(totalread < bytearraysize){
284                                    totalread += filein.read(b, totalread, bytearraysize-totalread);
285                                }
286                                InputStream inbyte = new ByteArrayInputStream(b);
287                                filein.close();
288                                return inbyte;
289                            }
290                        } else {
291                            //not a jar file.
292                            String filename = path+"/"+ classname;
293                            File file = new File(filename);
294                            if(file.isFile()){
295                                return (new FileInputStream(file));
296                            }
297                        }
298                    }catch(FileNotFoundException fnexce){
299                        fnexce.printStackTrace();
300                        error("cant read file");
301                        error("fatal exception");
302                    }catch(IOException ioexc){
303                        ioexc.printStackTrace();
304                        error("fatal exception");
305                    }
306                }
307            }
308    
309            return null;
310        }
311    
312    
313        /**
314         * Returns file input stream for classfile to disassemble.
315         */
316        public InputStream resolveclasspathhelper(String path, String classname){
317            File fileobj = new File(path);
318            try{
319                if(fileobj.isDirectory()){
320                    //is a directory.
321                    String filename = path+"/"+ classname;
322                    File file = new File(filename);
323                    if(file.isFile()){
324                        return (new FileInputStream(file));
325                    }
326    
327                }else if(fileobj.isFile()){
328                    if(fileobj.toString().endsWith(".jar")){
329                        //is a jar file.
330                        JarFile jfile = new JarFile(fileobj);
331                        if((jfile.getEntry(classname)) != null){
332                            InputStream filein = jfile.getInputStream(jfile.getEntry(classname));
333                            int bytearraysize = filein.available();
334                            byte []b =  new byte[bytearraysize];
335                            int totalread = 0;
336                            while(totalread < bytearraysize){
337                                    totalread += filein.read(b, totalread, bytearraysize-totalread);
338                            }
339                            InputStream inbyte = new ByteArrayInputStream(b);
340                            filein.close();
341                             return inbyte;
342                        }
343                    }
344                }
345            }catch(FileNotFoundException fnexce){
346                fnexce.printStackTrace();
347                error("cant read file");
348                error("fatal exception");
349            }catch(IOException ioexce){
350                ioexce.printStackTrace();
351                error("fatal exception");
352            }
353            return null;
354        }
355    }