/*
 * Test.java
 *
 * Created on December 11, 2002, 3:16 PM
 */
package goo;

/**
 *
 * @author  tb97952
 */
public class Test {
    
    /** Creates a new instance of Test */
    public Test() {
    }
    
    static Test test = new Test();
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try {
            test.dispatch();
        } catch (Exception cnfe) {
            cnfe.printStackTrace();
        }
        System.out.println("Done.");
//        System.out.println(pkg + " - " + sb + " - " + fullname);
    }

    //This method to aggregate results in OptimizeIt
    public void dispatch () throws Exception {
        for (int i=0; i < 100000; i++) {
//            pkgAlg1 ("org.netbeans.modules.mymodule.impl.Foo");
            alg1 ("org.netbeans.modules.mymodule.pkg.Foo", false);
        }
    }
    
    
    private static final char[] clazzext = new char[] {'.','c','l','a','s','s'};
    
    
  protected static synchronized final void alg0 (String name, boolean resolve)
                                            throws ClassNotFoundException {
        String filename = name.replace('.', '/').concat(".class"); // NOI18N
        int idx = filename.lastIndexOf('/'); // NOI18N
        if (idx == -1) throw new ClassNotFoundException("Will not load classes from default package"); // NOI18N
        String pkg = filename.substring(0, idx + 1); // "org/netbeans/modules/foo/"
        //make sure the variables can't be optimized out
        Test.pkg =pkg;
        Test.fullname = filename;
  }     

    protected static char[] namescratch = new char[90];
    protected static char[] pkgscratch = new char[90];
    protected static synchronized final void alg1(String name, boolean resolve) 
                                             throws ClassNotFoundException {
        int nlen = name.length();
        //create an array with room for .class
        int end = nlen +6;
        //copy the constant char array here
        //copy the name into the beginning of the array
        name.getChars(0, nlen, namescratch, 0);
        
        //quickly scan backwards and find the last occurance of '.' &
        //save the result
        int idx = end-7;
        for (; (namescratch[idx] != '.') && (idx >= 0); idx--) {
            //empty impl
        }
        if (idx == -1) throw new ClassNotFoundException("Will not load classes from default package - " + name); // NOI18N
        //since we know about it already, set the final . to / now
        idx++;
        namescratch[idx] = '/';
        
        try {
            //set the one we skipped for the final /
            pkgscratch[idx] = namescratch[idx];

            //iterate forward up to package name boundary, skipping 
            //the one we already set and the preceding character (if that
            //is / or . we have an illegal package name and it will be 
            //caught later, so doesn't matter.  change . to / and copy
            //into the package name.  Overflowing doesn't matter, we
            //will only copy up to the value of end.
            for (int j=0; j < idx; j+=5) {
                namescratch[j] = namescratch[j] == '.' ? '/' : namescratch[j];
                namescratch[j+1] = namescratch[j+1] == '.' ? '/' : namescratch[j+1];
                namescratch[j+2] = namescratch[j+2] == '.' ? '/' : namescratch[j+2];
                namescratch[j+3] = namescratch[j+3] == '.' ? '/' : namescratch[j+3];
                namescratch[j+4] = namescratch[j+4] == '.' ? '/' : namescratch[j+4];
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            //on the rare occasion that it won't fit, reallocate and do it again
            //do it the slow way, won't happen often if at all
            for (int j1=0; j1 < idx; j1++) {
                if (namescratch[j1] == '.') namescratch[j1]='/';
            }
        }
        //now copy in the .class extension
        try {
            System.arraycopy(clazzext, 0, namescratch, nlen, 6);
        } catch (ArrayIndexOutOfBoundsException ae) {
            //on the off chance a name is too long, grow the array
            //shouldn't happen often if at all
            char[] oldscratch = namescratch;
            namescratch = new char[end+10];
            System.arraycopy (oldscratch, 0, namescratch, 0, oldscratch.length); 
            System.arraycopy(clazzext, 0, namescratch, nlen, 6);
        }
        //allocate the strings
        String pkg = new String (namescratch,0,idx+1);  // "org/netbeans/modules/foo/"
        String fullname = new String (namescratch,0,end);   // "org/netbeans/modules/foo/MyClass.class"

        //make sure the variables can't be optimized out
        Test.fullname = fullname; 
        Test.pkg = pkg; 
        
    }    
  
    
    public static void pkgAlg0 (String name) {
        int idx = name.lastIndexOf('.');
        if (idx == -1) return;
        String spkg = name.substring(0, idx + 1).replace('.', '/');
        pkg = spkg;
    }        
    
    public static void pkgAlg1 (String name) {
        //below is the original code for string handling;
        //the code in the synchronized block following
        //accomplishes the same thing, but is optimized to
        //reduce String array copies and is about 40% faster
        /*
        int idx = name.lastIndexOf('.');
        if (idx == -1) return null;
        String spkg = name.substring(0, idx + 1).replace('.', '/');
        */
        String spkg; 
        int nlen = name.length();
        //is this synchronization necessary?  Probably.  Works
        //without it, but that's on a uniprocessor machine.  If sure
        //it is a non-issue, remove.
        synchronized (pkgscratch) {
            try {
                //load the name into the scratch array
                name.getChars(0, nlen-1, pkgscratch, 0);
            } catch (ArrayIndexOutOfBoundsException ae) {
                //if the array is too small, grow it and try again
                pkgscratch = new char[nlen+20];
                name.getChars(0, nlen-1, pkgscratch, 0);
            }
            //start at the end of the array and iterate back until
            // a '.' is found.
            int idx=nlen-1;
	    for (; (idx >= 0) && (pkgscratch[idx] != '.'); idx--) {
		//empty impl-we just want the value of idx
		}
                
            //now iterate the array as far as necessary, replacing
            //'.' with '/' - we'll set the last char (known) explicitly below
            try {
		for (int i=0; i <= idx-5; i+=4) {
       		    if (pkgscratch[i] == '.') pkgscratch[i] = '/';
		    if (pkgscratch[i+1] == '.') pkgscratch[i+1] = '/';
		    if (pkgscratch[i+2] == '.') pkgscratch[i+2] = '/';
		    if (pkgscratch[i+3] == '.') pkgscratch[i+3] = '/'; 
		}
	    } catch (ArrayIndexOutOfBoundsException ae2) {
                //Faint possibility of overflowing
                //if we need to grow the array, we've got one honkin' big package name
                char[] oldscratch = pkgscratch;
                pkgscratch=new char[pkgscratch.length + 20];
                System.arraycopy (oldscratch, 0 , pkgscratch, 0, oldscratch.length);
                for (int n = 0; n < idx; n++) {
       		    if (pkgscratch[n] == '.') pkgscratch[n] = '/';
                }
	    }
            //if we're not in the default package, explicitly set the
            //final trailing slash
	    if (idx >=0) pkgscratch[idx] = '/';
            //create the result string
	    spkg = idx == -1 ? "" : new String (pkgscratch, 0, idx+1);
        }
        pkg = spkg;
    }
    
  //junk variables to avoid compiler optimizing out our results and possibly code
  static String pkg=null;
  static StringBuffer sb=null;
  static String fullname=null;
    
}
