Package com.sun.jini.tool

Source Code of com.sun.jini.tool.AbstractTreeWalker

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.sun.jini.tool;

import com.sun.jini.system.FileObserver;
import com.sun.jini.system.FileWalker;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

import java.text.MessageFormat;

import java.util.ArrayList;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.StringTokenizer;

/**
* This class is an abstract class that acts as the base class for
* classes wishing to search a directory tree and generate a list of files
* or fully-qualified package.classnames.
* <p>
* Concrete classes that extend this class are required to provide an
* implementation for the single abstract method that defines additional
* selection policies to apply when constructing the desired list from the
* list resulting from the search.
* <p>
* This class allows a number of arguments to be input on the command
* line that can be used to dynamically control how the methods of this
* class interpret and handle the data that is manipulated. Those
* command line arguments are:
* <p>
<ul>
*    <li> '-drive <drive>'     - the drive letter to prepend to the
*                                directory tree that is searched
*    <li> '-root <rootDir>'    - the root directory to prepend to the relative
*                                directory used as the start point of the
*                                search
*    <li> '-start <startDir>'  - the directory (absolute or relative) from
*                                which to start the search
*    <li> '-suffix <.fileExt>' - will search for only files having this suffix
*                                as extension (ex. .java, .class, .c, etc)
*    <li> '-out <outputFile>'  - the file to which to write the generated list
*    <li> '-noRecurse'         - will search for the desired files only in the
*                                given start directory; that is, it will not
*                                "walk the tree"
*    <li> '-verbose'           - will display status information as
*                                processing proceeds
*    <li>
*    <li>
</ul>
*/
abstract public class AbstractTreeWalker {

    /** PrintWriter to which the fully-qualified package and test names will
     *  be written. Defaults to standard output.
     */
    PrintWriter outPW = new PrintWriter(System.out,true);

    private static ResourceBundle resources;
    private static boolean resinit = false;

    private String drive = new String("c");
    private String rootDir = null;

    /** The absolute path of the directory from which to start the search for
     *  test source files.
     */
    private String startDir = new String(".");
    private String suffix   = new String(".java");
    private String outFilename;
    private boolean recurse = true;
    private boolean verbose = false;

    /* Constructs instance of this class initialized with command line args */
    public AbstractTreeWalker(String[] args) {
        setup(args);
    }//end constructor

    /** Creates the list of fully-qualified package.testnames to be executed */
    abstract void buildPackageList();

    /** Walks the directory tree populating the list with the source files to
     *  analyze
     */
    ArrayList getFilesList() {
        File startFD = new File(startDir);
        if (!startFD.exists()) {
            print("treewalker.not.exist",startDir);
            System.exit(0);
        }
        if (!startFD.isDirectory()) {
            print("treewalker.not.directory",startDir);
            System.exit(0);
        }
        FileWalker fileWalker = new FileWalker();
        FileObserver fileObserver = new FileObserver(suffix);
        fileWalker.addObserver(fileObserver);
        fileWalker.walk(startFD,recurse);
        return fileObserver.getFileList();
    }//end getFilesList

    /** Converts the elements of the given ArrayList from directory format
     *  to package format. If the rootDir is not null, strips off the
     *  directories contained in the rootDir; otherwise, it converts the
     *  whole directory path to packages. Strips off the suffix.
     */
    ArrayList getPkgList(ArrayList dirList) {
        ArrayList pkgList = new ArrayList();
        String rootPkg = ( (rootDir == null) ? null : pathToPkg(rootDir) );
        for(int i=0;i<dirList.size();i++) {
            String pkg = pathToPkg((String)dirList.get(i));
            if(pkg.endsWith(suffix)) { //strip off the suffix
                int indx = pkg.lastIndexOf(suffix);
                pkg = pkg.substring(0,indx);
            }
            if(rootPkg != null) { //strip off the rootDir
                if(pkg.startsWith(rootPkg+".")) {
                    int indx = 1+rootPkg.length();
                    pkg = pkg.substring(indx);
                }
            }//end if
            pkgList.add(pkg);
        }//end loop(i)
        return pkgList;
    }//end getPkgList

    /** Print out string according to resourceBundle format. */
    static void print(String key, Object val) {
        String fmt = getString(key);
        if (fmt == nullfmt = "no text found: \"" + key + "\" {0}";
        System.err.println(MessageFormat.format(fmt, new Object[]{val}));
    }//end print

    /** Print out string according to resourceBundle format. */
    static void print(String key, Object val1, Object val2) {
        String fmt = getString(key);
        if (fmt == nullfmt = "no text found: \"" + key + "\" {0} {1}";
        System.err.println(MessageFormat.format(fmt,new Object[]{val1, val2}));
    }//end print

    /** Get the strings from this class' resource localization bundle. */
    private static String getString(String key) {
        if (!resinit) {
            try {
                resources = ResourceBundle.getBundle
                                   ("com.sun.jini.tool.resources.treewalker");
                resinit = true;
            } catch (MissingResourceException e) {
                e.printStackTrace();
            }
        }//endif
        try {
            return resources.getString(key);
        } catch (MissingResourceException e) {
            return null;
        }
    }//end getString

    /** Convenience method for handling the command line input to this utility.
     *  This method parses the command line and from the values retrieved
     *  from the command line, sets the fields of this class with the
     *  appropriate data.
     */
    private void setup(String[] args) {
        for (int i = 0; i < args.length ; i++ ) {
            String arg = args[i];
            if(arg.equals("-drive")) {
                i++;
                setDrive(args[i]);
            } else if(arg.equals("-root")) {
                i++;
                setRootDir(args[i]);
            } else if(arg.equals("-start")) {
                i++;
                startDir = new String(args[i]);
            } else if(arg.equals("-suffix")) {
                i++;
                suffix = new String(args[i]);
            } else if(arg.equals("-out")) {
                i++;
                setOutPrintWriter(args[i]);
            } else if(arg.equals("-noRecurse")) {
                recurse = false;
            } else if(arg.equals("-verbose")) {
                verbose = true;
            } else if(arg.startsWith("-")) {
                usage();
                System.exit(0);
            }//endif
        }//end loop
        if(!isAbsolute(startDir)) {
            startDir = relativeToAbsolutePath(rootDir,startDir);
        }//endif
        if(verbose) {
            if(dosFileSystem()) print("treewalker.print.drive",drive);
            if(rootDir != null) print("treewalker.print.root",rootDir);
            print("treewalker.print.start",startDir);
            print("treewalker.print.suffix",suffix);
            print("treewalker.print.recurse",new Boolean(recurse));
        }//endif
    }//end setup

    /** Print out the usage for this utility. */
    private static void usage() {
  print("treewalker.usage", null);
    }//end usage

    /** Sets the drive letter for the root directory */
    private void setDrive(String drv) {
        char[] charArray = drv.toCharArray();
        if((drv.length() > 1) || ((charArray[0] < 'A')||(charArray[0] > 'z'))){
            print("treewalker.warning", "illegal drive ("+drv+") -- "
                                    +"must be single letter a-z");
            return;
        }
        drive = new String(drv);
    }//end setDrive

    /** Sets the root directory to prepend to the relative start directory */
    private void setRootDir(String dir) {
        if(!isAbsolute(dir)) {
            print("treewalker.absolute","input root directory -- "+dir);
            System.exit(0);
        }
        rootDir = new String(dir);
    }//end setRootDir

    /** Gets the root directory to prepend to the relative start directory */
    protected String getRootDir() {
        return rootDir;
    }//end getRootDir

    /** Based on the input directory, retrieves and sets the absolute path of
     *  the directory from which to start the search for test source files.
     */
    private void setStartDir(String dir) {
        File startDirFD = new File(dir);
        startDir = startDirFD.getAbsolutePath();
    }//end setStartDir

    /** Based on the input filename, creates and sets a PrintWriter to which
     *  the fully-qualified package and test names will be written.
     */
    private void setOutPrintWriter(String filename) {
        try {
            FileWriter outFW = new FileWriter(filename);
            outPW = new PrintWriter(outFW,true);
        } catch(IOException e) {
            e.printStackTrace();
            print("treewalker.open.failure",filename);
            System.exit(0);
        }
    }//end setOutPrintWriter

    /** Converts components of the given directory path to package format. */
    private String pathToPkg(String path) {
        String dirComponents[] = getDirs(path);
        StringBuffer strBuf = new StringBuffer(dirComponents[0]);
        for(int i=1;i<dirComponents.length;i++) {
            strBuf = strBuf.append("."+dirComponents[i]);
        }//end loop(i)
        return strBuf.toString();
    }//end pathToPkg

    /** Determines whether the <code>path</code> parameter is absolute or
     *  relative.
     *
     *  This method applies the following criteria in making the
     *  determination: if the <code>path</code> parameter contains a drive
     *  designation, the <code>path</code> parameter is always considered
     *  absolute, regardless of the current file system. Additionally,
     *  although the windows operating system considers a path that
     *  begins with two separators ('\\') absolute, and a path that begins
     *  with only a single separator ('\') relative, this method considers
     *  both relative.
     *
     *  @param path <code>String</code> containing the path/filename to analyze
     *
     *  @return <code>true</code> if the <code>path</code> parameter is
     *          absolute; <code>false</code> otherwise.
     */
    private boolean isAbsolute(String path) {
        /* A drive always means absolute no matter what file system. Also,
         * On windows: drive or double separator ==> absolute,
         *             but single separator ==> relative.
         * This method considers only a drive letter absolute.
         */
        if(hasDrive(path)) return true;
        if(!dosFileSystem()) {
            File fd = new File(path);
            return fd.isAbsolute();
        }
        return false;
    }//end isAbsolute

    /** Determines whether the <code>path</code> parameter contains a
     *  drive designator.
     *
     *  @param path <code>String</code> containing the path/filename to analyze
     *
     *  @return <code>true</code> if the <code>path</code> parameter contains a
     *          drive designator; <code>false</code> otherwise.
     */
    private boolean hasDrive(String path) {
        char[] charArray = path.toCharArray();
        if(    ((charArray[0] >= 'A') && (charArray[0] <= 'z'))
            && (    (charArray[1] == ':')
                 && ((charArray[2] == '\\') || (charArray[2] == '/')) ) )
        {
            return true;
        }
        return false;
    }//end hasDrive

    /** Determines whether or not the current file system is a DOS file system.
     *
     *  @return <code>true</code> if the current file system is a DOS file
     *          system; <code>false</code> otherwise.
     */
    private boolean dosFileSystem() {
        String sep = System.getProperty("file.separator");
        String dosSep  = "\\";
        boolean isDos = ( (dosSep.compareTo(sep) == 0) ? true : false);
        return isDos;
    }//end dosFileSystem

    /** Returns a <code>String</code> containing the absolute path associated
     *  with the <code>path</code> parameter. When "computing" the absolute
     *  path of the <code>path</code> parameter, this method considers
     *  the current file system and whether or not the <code>path</code>
     *  parameter contains a drive designation: if the file system does
     *  expect a drive designation, but the <code>path</code> parameter
     *  contains such a drive, this method will strip off the drive designation
     *  and return a path/filename made up with the given components
     *  and path separators appropriate for the current file system.
     *
     *  @param path <code>String</code> containing the path/filename to
     *              process.
     *
     *  @return <code>String</code> containing the absolute path/filename
     *          for the given <code>path</code> parameter.
     */
    private String getAbsolutePath(String path) {
        if( !dosFileSystem() && hasDrive(path) ) {
            /* if on unix & has a drive: strip off the drive */
            String[] components = getDirs(path);
            String sep = System.getProperty("file.separator");
            StringBuffer strBuf = new StringBuffer(sep+components[1]);
            for(int i=2;i<components.length;i++) {
                strBuf = strBuf.append(sep+components[i]);
            }
            return strBuf.toString();
        }
        return (new File(path)).getAbsolutePath();
    }//end getAbsolutePath

    /** Returns a <code>String</code> array whose elements correspond to the
     *  drive/directory/file components making up the <code>path</code>
     *  parameter.
     *
     *  @param path <code>String</code> containing the path/filename to parse.
     *
     *  @return <code>String</code> array containing the drive/directory/file
     *          components making up the <code>path</code> parameter.
     */
    private String[] getDirs(String path) {
        String[] strArray = new String[0];
        String delimiter = "/\\"; // handle mixed path separators
        StringTokenizer st = new StringTokenizer(path,delimiter);
        int n = st.countTokens();
        if (n > 0) {
            strArray = new String[n];
            for(int i=0;((st.hasMoreTokens())&&(i<n));i++) {
                strArray[i] = st.nextToken();
            }
            return strArray;
        } else {
            return strArray;
        }
    }//end getDirs

    /** Returns the drive separator associated with the current file system.
     *  For example, on DOS files systems, ":" would be returned, whereas on
     *  unix file systems, "" would be returned.
     *
     * @return <code>String</code> containing the drive separator associated
     *         with the current file system.
     */
    private String getDriveSeparator() {
        String driveSep = ( dosFileSystem() ? ":" : "" );
        return driveSep;
    }//end getDriveSeparator

    /** Returns the drive letter to use depending on the file system.
     *
     *  @return <code>String</code> containing the drive letter to use.
     */
    private String getFileSystemDrive() {
        String drv = ( dosFileSystem() ? new String(drive) : new String("") );
        return drv;
    }//end getFileSystemDrive

    /**
     * This method constructs a well-formed, absolute path/filename from the
     * given <code>installDir</code> and <code>path</code> parameters. This
     * method is intended to be sensitive to file system dependencies.
     * For example, if the property is written in DOS file format
     * (ex. C:\aaa\bbb\ccc\), but this method is executed on a system with
     * a unix file system, this method will build a String in the unix file
     * system format from the contents of the given String (/aaa/bbb/ccc).
     *
     * In addition to being sensitive to file system differences, this method
     * is also designed to handle both absolute and relative paths in a
     * well-defined manner. If the path/filename corresponding to the given
     * <code>path</code> parameter is absolute, that path/filename will be
     * converted to the appropriate file system format with no other
     * modifications or additions applied. On the other hand, if the
     * <code>path</code> parameter is relative, then the value contained in
     * <code>installDir</code> parameter will be prepended to the
     * <code>path</code> parameter, and the result will be returned in the
     * appropriate file system format.
     *
     * Whether a given path/filename is viewed as relative or absolute is
     * based on the following criteria:
     *
     *  non-DOS file systems  abs/rel    DOS file systems  abs/rel
     *  --------------------  --------   ----------------  --------
     *     /aaa/bbb/ccc       absolute    c:\aaa\bbb\ccc   absolute
     *     aaa/bbb/ccc        relative      \aaa\bbb\ccc   relative
     *                                      \\aaa\bbb\ccc  relative
     *                                        aaa\bbb\ccc  relative
     *
     * Note that this method also attempts to handle the case where the
     * format of the given <code>path</code> parameter is different than
     * the current file system's format. For example,
     *
     * file sys installDir      path      abs/rel         output
     * -------- ---------- -------------- --------  --------------------
     *   DOS     c:\files  c:\aaa\bbb\ccc absolute  c:\aaa\bbb\ccc
     *   unix    c:\files  c:\aaa\bbb\ccc absolute    /aaa/bbb/ccc
     *   DOS     c:\files     aaa\bbb\ccc relative  c:\files\aaa\bbb\ccc
     *   unix    c:\files     aaa\bbb\ccc relative    files/aaa/bbb/ccc
     *
     * @param path       <code>String</code> containing the name of the
     *                   path/filename to modify (if necessary)
     * @param installDir <code>String</code> containing the name of the
     *                   directory to prepend to the <code>path</code>
     *                   parameter
     *
     * @return a <code>String</code> containing a path/filename constructed
     *         from the value of the input parameters in a format that is
     *         appropriate to the current file system.
     */
    private String relativeToAbsolutePath(String installDir, String path) {
        if(path == null) return path;
        String sep = System.getProperty("file.separator");
        if(isAbsolute(path)) {/* Absolute path, don't prepend installDir */
            /* re-build the path with "clean" components */
            StringBuffer pBuf = new StringBuffer();
            String pDir = getAbsolutePath(path);
            String pDirComponents[] = getDirs(pDir);
            int pStart = 0;
            if(hasDrive(pDir)) {
                pBuf = pBuf.append(pDirComponents[0]);
                pStart = 1;
            }
            for(int i=pStart;i<pDirComponents.length;i++) {
                pBuf = pBuf.append(sep+pDirComponents[i]);
            }
            return pBuf.toString();
        } else { /* Relative path, prepend installDir */
            String driveSep = getDriveSeparator();
            String iDir = null;
            if(installDir != null) {
                /* re-build the install directory with "clean" components */
                StringBuffer iBuf = new StringBuffer();
                iDir = getAbsolutePath(installDir);
                String iDirComponents[] = getDirs(iDir);
                int iStart = 0;
                if(hasDrive(iDir)) {
                    iBuf = iBuf.append(iDirComponents[0]);
                    iStart = 1;
                } else if(dosFileSystem()) { // no drive but windows: get drive
                    String iDrive = getFileSystemDrive();
                    iBuf = iBuf.append(iDrive+driveSep);
                }
                for(int i=iStart;i<iDirComponents.length;i++) {
                    iBuf = iBuf.append(sep+iDirComponents[i]);
                }
                iDir = iBuf.toString();
            }
            /* construct the new path by pre-pending the installDir */
            String pDir = path;
            String pDirComponents[] = getDirs(pDir);
            int pStart = 0;
            StringBuffer pBuf = new StringBuffer();
            /* if no install directory, use OS-dependent absolute path */
            if( (iDir == null) || (iDir.length() == 0) ) { // no installDir
                pDir = getAbsolutePath(path);
                pDirComponents = getDirs(pDir);
                if(hasDrive(pDir)) {
                    pBuf = pBuf.append(pDirComponents[0]);
                    pStart = 1;
                } else if(dosFileSystem()) {
                    String pDrive = getFileSystemDrive();
                    pBuf = pBuf.append(pDrive+driveSep);
                }
            } else { // prepend the install directory
                pBuf = pBuf.append(iDir);
            }
            /* re-build path with install directory and "clean" components */
            for(int i=pStart;i<pDirComponents.length;i++) {
                pBuf = pBuf.append(sep+pDirComponents[i]);
            }
            return pBuf.toString();
        }
    }//end relativeToAbsolutePath

}//end class AbstractTreeWalker
TOP

Related Classes of com.sun.jini.tool.AbstractTreeWalker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.