CS 235 - Week 15 Lecture - 2015-12-07

a few words about Java packages and jars

*   course text has more info about these
    topics:
    *   more package info: Ch. 4, pp. 152-162
    *   more jar info: Ch. 10, pp. 495-500

*   Java package provides a way to collect/organize
    related classes together

*   notice: all standard Java packages are inside
    the so-called java and javax package
    hierarchies

*   one benefit of packages
    is to organize related classes for
    better day-to-day ease of use;

    ANOTHER is to help guarantee uniqueness
    of class names,
    (since a class's "complete" name is
    <package_name>.<class_name>

    *   to help in this regard:
        Oracle even recommends using your
	organization's/company's/group's
        Internet domain name written in
	reverse as the package name

    *   course text author has a domain
        horstmann.com,

	he'd use package name

        com.horstmann

        with subpackages such as:
	com.horstmann.corejava
	com.horstmann.absolutejava

        I might put classes related to this
	class in a package
	edu.humboldt.st10.cs235
        edu.humboldt.st10.bigproj

*   note that locating classes in packages
    is (according to course text p. 154)
    an activity of the compiler --

    ...compiled bytecode contains FULL class
    names, including the package!

    javax.swing.JPanel not JPanel

*   all Java classes ARE in a package --
    if a Java class does not have a package
    declaration it is considered to belong
    to the anonymous default package

    (the default package has no package name)

*   SO - say you had a class you wanted to
    put into a package so other classes
    could import it from that package and
    use it?

    *   STEP 1: how do you define a package?

        you put a package statement at the top
	of your source file, BEFORE the code
	that defines the classes:
 
        package <desired_pkg_name>;

        (for example, to make a version of class GameDie
        desired to be in a package edu.humboldt.st10.cs235,
	could put this at the beginning of the source code
	file GameDie.java:

	package edu.humboldt.st10.cs235;
   
        )
        
    *   STEP 2: place this source code file in a subdirectory
        with the PROPER NAME, based on that package
	name

        *   for package com.horstmann.corejava,
	    the code in that package should be
	    in a subdirectory
            com/horstmann/corejava

        *   for package edu.humboldt.st10.cs235,
	    it should be in a subdirectory
	    edu/humboldt/st10/cs235

    *   STEP 3 - compile and run the package's classes
	from the base directory,
	(that is, the directory containing the com
	directory for com.horstmann.edu,
	the directory containing the edu directory
	for edu.humboldt.st10.cs235

    *   how does the JVM (Java Virtual Machine)
        locate the .class files for Java classes?

	There's a concept of a class path,
	a set of directories that JVM
	essentially "tacks" the package
	names onto, and looks in each for
	the .class files...

        How do you set the class path?

	*   you can set it with -classpath
            when you javac, java it

	*   or you can set the CLASSPATH
	    environment variable for your
	    operating system (temporarily within your
            current shell,
	    or "permanently" by adding it to a script
	    that runs when you log in or start up a new shell)

*   trying this in class for GameDie.java and GameDieTest.java
    *   added package command:

        package edu.humboldt.st10.cs235;

        ...to beginning of a copy of GameDie.java

    *   currently working in my directory /Users/smtuttle;
        made subdirectory-tree 

	    edu/humboldt/st10/cs325

	...from this directory

           mkdir edu
           mkdir edu/humboldt
           mkdir edu/humboldt/st10
           mkdir edu/humboldt/st10/cs325

    *   copied GameDie.java version with the package
        command into subdirectory edu/humboldt/st10/cs325

    *   while in /Users/smtuttle, compiled GameDie.java using:

        javac edu/humboldt/st10/cs235/GameDie.java

*   now want to TRY to USE this packaged GameDie class!
    ...so went to a completely different directory,
    (in this lecture's case, 
    /Users/smtuttle/humboldt/f15cs235/235lectures/235lect15

    *   made a copy of old Week 1 Lab version (NOT JUnit version!)
        of GameDieTest.java, a little command-line application that
	JUST exercises GameDie a little bit, in THIS directory

    *   added, to this copy of GameDieTest.java,
        an import statement for GameDie from this new
        package:

        import edu.humboldt.st10.cs235.GameDie;

    *   now -- from GameDieTest.java's directory,
        /Users/smtuttle/humboldt/f15cs235/235lectures/235lect15

        ran:

        javac -classpath .:/Users/smtuttle GameDieTest.java

    *   and then ran:

        java -classpath .:/Users/smtuttle GameDieTest

        AND IT WORKED, hooray! 8-) I see println results from
        rolling GameDie instances cube and dodeca;

*   a few words about jars

    *   jar - acronym, for Java ARchive file
    *   they are compressed
    *   this does use a cross-platform archive 
        format

    *   jar files make it simpler to distribute
        Java programs -- reasonably quickly 
	with regard to Java applets to browsers
	-- and sometimes you can even add security,
	in the form of digital signatures;

    *   jar vcf newJar.jar subdir_name
        jar vcf newJar.jar file1 file2 ....

        if there is an application amongst those
	files, you can make the jar executable...
	    
jar vcfe newJar.jar fullNameOfMainClass <filestoAdd>

*   SO: trying this;

    running from /Users/smtuttle,
    where my edu.humboldt.st10.cs235 package's subdirectory tree starts:

    jar vcf st10Lect15.jar edu

    *   the v above stands for verbose -- here's the output
        displayed when I run the above:

added manifest
adding: edu/(in = 0) (out= 0)(stored 0%)
adding: edu/humboldt/(in = 0) (out= 0)(stored 0%)
adding: edu/humboldt/st10/(in = 0) (out= 0)(stored 0%)
adding: edu/humboldt/st10/cs235/(in = 0) (out= 0)(stored 0%)
adding: edu/humboldt/st10/cs235/GameDie.class(in = 637) (out= 398)(deflated 37%)
adding: edu/humboldt/st10/cs235/GameDie.java(in = 1839) (out= 713)(deflated 61%)

    *   and t option allows you to see the contents of the jar -- if
        I now run:

        jar tf st10Lect15.jar

        ...the following is displayed:

META-INF/
META-INF/MANIFEST.MF
edu/
edu/humboldt/
edu/humboldt/st10/
edu/humboldt/st10/cs235/
edu/humboldt/st10/cs235/GameDie.class
edu/humboldt/st10/cs235/GameDie.java

    *   I should be able to now add this jar to a
        classpath, and a class using classes from
	a package in that jar will work;

        # COPYING the jar to my class's directory
	#    (just have to know the path it can be reached from,
	#    I think -- BUT copying here is one way to know
	#    that, and hopefully shows it CAN be "moved"):

        cp st10Lect15.jar /Users/smtuttle/humboldt/f15cs235/235lectures/235lect15
	   
        # TEMPORARILY "hid" original package edu.humboldt.st10.cs235
	#    (by changing edu directory's name) so can (hopefully)
	#    show I'm using the package from the jar;
   
        # while in /Users/smtuttle
      
        mv edu HIDEedu

        # cd'd to /Users/smtuttle/humboldt/f15cs235/235lectures/235lect15

        cd /Users/smtuttle/humboldt/f15cs235/235lectures/235lect15

        # since have HIDDEN original package, this SHOULD now
	#    fail -- does it?

        javac -classpath .:/Users/smtuttle GameDieTest.java

        # YES -- I'll spare you the 5 errors' error messages
	#    here;

        # CAN it compile and run if I put the jar in the classpath
	#    option?

        javac -classpath .:st10Lect15.jar GameDieTest.java
        java -classpath .:st10Lect15.jar GameDieTest

        AND IT WORKED, hooray! 8-) I see again see println results from
        rolling GameDie instances cube and dodeca;

*   more about executable jars:

    (after class)
    recall:
    
    jar vcfe newJar.jar fullNameOfMainClass <filestoAdd>

    ...should be able to create an executable jar, but (as we saw
    in class) not so much for a command-line application...!

    BUT: we should be able to try this with a Swing GUI application
    such as Week 7 Lab's LayoutTrio.java;

    *   I copied its source code into a new directory
    *   compiled it as usual:
    
        javac LayoutTrio.java

    *   created an executable jar:
        (. is a UNIX nickname for the current directory --
        
        keep in mind, LayoutTrio.java contains one public class
        which happens to be an application class, with a main method, and
	numerous default-visibility and private inner classes,
	EACH of which results in a .class file)

	jar vcfe trioJar.jar LayoutTrio . 
    
        this displays:
added manifest
adding: LayoutTrio$1.class(in = 533) (out= 371)(deflated 30%)
adding: LayoutTrio.class(in = 408) (out= 293)(deflated 28%)
adding: LayoutTrio.java(in = 7386) (out= 2093)(deflated 71%)
adding: LayoutTrioFrame.class(in = 522) (out= 374)(deflated 28%)
adding: LayoutTrioPanel$1.class(in = 188) (out= 151)(deflated 19%)
adding: LayoutTrioPanel$ClearAction.class(in = 831) (out= 473)(deflated 43%)
adding: LayoutTrioPanel$NumButtonAction.class(in = 1246) (out= 649)(deflated 47%)
adding: LayoutTrioPanel.class(in = 2884) (out= 1592)(deflated 44%)

    *   NOW -- if I double click on trioJar.jar, does LayoutTrio
        run?
        *   YES;

    *   can I copy it elsewhere, and does it still run when I
        double-click on it? (is it directory-dependent?)
        *   YES;

    *   ...and I'm posting a link to a copy of trioJar.jar,
        so you can see if it works when you download a copy of
	it;