Sunday, October 25, 2009

Section 12.1. Date and Time Functions Grouped by Type







Chapter 12. Date and Time Functions

By using temporal data type columns, you can use several built-in functions
offered by MySQL. This chapter presents those functions. Currently, five
temporal data types are available: DATE,
TIME, DATETIME,
TIMESTAMP, and YEAR. You would set a column to one of these data types when
creating or altering a table. See the descriptions of CREATE
TABLE
and ALTER TABLE in Chapter 6 for more details. The DATE
column type can be used for recording just the date. It uses the
yyyy-mm-dd format. The TIME
column type is for recording time in the
hhh:mm:ss format. To record a combination of date
and time, use DATETIME: yyyy-mm-dd
hh:mm:ss
. The TIMESTAMP column is similar
to DATETIME, but it is more limited in its range of
allowable time: it starts at the Unix epoch time (i.e., 1970-01-01) and
stops at the end of 2037. Plus, it has the distinction of resetting its
value automatically when the row in which it is contained is updated, unless
you specifically instruct MySQL otherwise. Finally, the
YEAR data type is used only for recording the year in a
column. For more information on date and time data types, see Appendix B.

Any function that calls for a date or a time data type will also
accept a combined datetime data type. MySQL requires that months range from
0 to 12 and that days range from 0 to 31. Therefore, a date such as February
30 would be accepted prior to version 5.0.2 of MySQL. Beginning in version
5.0.2, MySQL offers more refined validation that would reject such a date.
However, some date functions accept 0 for some or all components of a date,
or incomplete date information (e.g., 2008-06-00). As a general rule, the
date and time functions that extract part of a date value usually accept
incomplete dates, but date and time functions that require complete date
information return NULL when given an incomplete date. The descriptions of
these functions in this chapter indicate which require valid dates and which
don't, as well as which return 0 or NULL for invalid dates.

The bulk of this chapter consists of an alphabetical listing of date
and time functions, with explanations of each. Each of the explanations
include an example of the function's use, along with a resulting display, if
any. For the examples in this chapter, I used the scenario of a professional
services firm (e.g., a law firm or an investment advisory firm) that tracks
appointments and seminars in MySQL. For help locating the appropriate
function, see the next section or the index at the end of this book.


12.1. Date and Time Functions Grouped by Type

Following are lists of date and time functions, grouped according to
their purpose: to retrieve the date or time, to extract an element from a
given date or time, or to perform calculations on given dates or
times.

12.1.1. Determining the Date or Time

[click here], [click here],
[click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here].

12.1.2. Extracting and Formatting the Date or Time

[click here], [click here],
[click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here].

12.1.3. Calculating and Modifying the Date or Time

[click here], [click here],
[click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here], [click here].








14.10 Security Considerations











 < Day Day Up > 





14.10 Security Considerations



A Web Services security model should address security issues starting from an end client to a target service, including the intermediary services that route the service requests. This chapter has proposed a mechanism for the client to provide authentication data, based on the service definition, and at the same time, for the service provider to retrieve that data. A proposed authorization approach, based on a declarative authorization policy model, can be used by the service provider to enforce authorization constraints. Understanding the necessity and complexity in established trust in the Web Services model, this chapter has also proposed how XML Signature and XML Encryption can be used to achieve a level of trust. Additionally, this chapter has illustrated that, as part of its evolution, the Web Services paradigm for application development can be seen as an opportunity to introduce a method of coupling security technologies�authentication, authorization, digital signatures, and so on�with business trust issues, such as PKI policy, role-based access control, and firewalls. This leads to the creation of core Web security services configured through policies expressed in XML. As the base Web Services technology evolves, more complex scenarios will need to be thought about and handled in the future.













     < Day Day Up > 



    Section 14.7. Advanced Pseudostates










    14.7. Advanced Pseudostates








    You've already seen initial pseudostates, which mark the start of a state diagram. There are additional pseudostates that are useful for directing the flow of traffic between states.


    A choice pseudostate is used to emphasize that a Boolean condition determines which transition is followed. A choice has guards on each of its outgoing transitions, and the transition that is followed depends on the guard. In Figure 14-19, the CD player will go back to the Playing state if another disc is available or will go to the Stopped state if there are no more discs. Notice that this is an alternate, and cleaner, way to model the transition choice in Figure 14-11.



    Figure 14-19. The path followed after a choice depends on the guard



    At least one of the guards following a choice must evaluate to true for your model to be well-formed. If more than one guard following a choice evaluates to true, then one of them is selected arbitrarily. If this situation doesn't make sense for your model, then it's a sign that you need to redefine your guards so that exactly one guard at a time evaluates to true.



    Fork and join pseudostates show branching into concurrent states and then rejoining. For example, in Figure 14-20, the fork breaks the incoming transition into two transitions, allowing Searching and Pacing to happen simultaneously. The join then merges its two incoming transitions into one outgoing transition.


    Figure 14-20 is an alternate way to model Figure 14-18. In Figure 14-18, forking and joining are implied by showing the initial pseudostates and final states.



    Figure 14-20. Forks and joins show concurrent states













    &quot; These Aren't My Files!













    “These Aren’t My Files!”

    Normally, when you log in, you start working in your home directory. If you type the following line, you return to the home directory from whichever directory you may have roamed to:



    cd

    If cd doesn’t get you back home, you may not be who you think you are. Try typing whoami or who am i. If someone else’s username appears, your computer thinks that that’s who you are! A coworker may have logged in to your computer to do some work for a moment.


    You then have several options:




    • Send some malicious e-mail, which will arrive looking as though your coworker sent it. Delete all her files that look important, and then log out and pretend that nothing happened.




    • Log out without fouling anything up, and then log in as yourself. Type this line:



      logout

      Maybe you have to type exit or just press Ctrl+D. At any rate, when you see the login screen, log in as yourself.




    Most courses in business ethics tell you that the second option is preferred by all except the slimiest of bottom-feeding MBAs, but the urge to send goofy e-mail is sometimes irresistible. Remember: You may be caught.











    Project Goals











     < Day Day Up > 





    Project Goals



    In this project, we're looking for ways to present a collection of photographs for sale. Our client has given us the following requirements:



    • We need to have three different possible presentations: a Contact Sheet view for the artist to check what's available and to show off to his peers, a Gallery view for users to be able to see all the offerings, and a more detailed Catalog view to allow for ordering.

    • In the Gallery and Contact Sheet views, as many photographs as possible should appear "above the fold" and without requiring a horizontal scroll, no matter the browser window size. It is acceptable to show only the photo and its title in this view. However, the pictures should arrange themselves into a regular grid.

    • In the Catalog view, every photograph should be presented along with its title, catalog number, and price. Scrolling is not a problem in this view.

    • The same markup should drive all three views because our client doesn't want to pay for a dynamic site and therefore wants the page markup to be produced only once.



    For this project, we're only working on the photo collection piece of the layout, so we don't have to worry about anything but that piece. We will assume that the layout will go into a main central column in a larger layout, but that doesn't really change anything for this project.



    Due to the constraints of the project, particularly those of the Gallery and Contact Sheet views, we won't be able to use tables to lay out these photos. Why not? Because of the request to get as many pictures as possible "above the fold" (that is, into the browser window at page load).



    So, instead of tables, we'll need to float the pictures and their information for those two "compact" views. Floating them will allow us to get as many pictures in each "row" as will fit in the browser window. In other words, a user with an 800x600 browser window might get four images per row, while a 1280x1024 user will get six or seven. Using floats allows for this kind of "flow" behavior, whereas using tables does not. As an added bonus, we can set up the floats so that each one is the same width. This will ensure that they lay themselves out in a grid-like fashion.













       < Day Day Up > 



      15.6 Access to System Resources











       < Day Day Up > 





      15.6 Access to System Resources



      Depending on the trust level on the deployed applications, one would have to protect malicious applications from accessing system resources, such as files and sockets, as well as resources within the container, such as internal data structures used by the container. The Java 2 security model can be used to achieve this level of security (see Chapter 8 on page 253). By granting appropriate Java permissions to trusted applications, as well as by checking for relevant permissions when a protected resource is being accessed, the container can protect sensitive resources. For example, if the container is configured to provide access to the class-loading mechanism or other internal classes only to trusted applications, the container can define and check for the relevant permissions before allowing access.



      In addition to checking for permissions before accessing sensitive resources, the container should provide the right context when such checks are performed. For example, to maintain location transparency, so that local or remote enterprise beans behave the same way when permissions are checked, the container needs to limit the java.security.ProtectionDomains on the call stack when authorization tests are performed (see Section 8.5 on page 265). As an example, let us consider two applications: ApplicationA and ApplicationB. Furthermore, let us assume that ApplicationA calls ApplicationB and that ApplicationB accesses a resource R1 requiring permission P1. When a call to the SecurityManager's checkPermission() method is made to check whether P1 is granted, the java.security.AccessController class will check all the ProtectionDomains on the call stack. In the case of local calls, ApplicationA (the caller) will be on the stack when such a check is performed. Therefore, both ApplicationA and ApplicationB will be on the call stack. However, if ApplicationA invokes ApplicationB remotely, ApplicationA will not be in the call stack and hence will not affect the authorization evaluation.



      In order to maintain location transparency, the container needs to perform an AccessController.doPrivileged() call at the boundary where ApplicationA calls into ApplicationB, as shown in Figure 15.5. Invoking doPrivileged() sets up the environment such that ApplicationA's ProtectionDomain will not be on the stack, regardless of whether ApplicationA calls ApplicationB locally or remotely.



      Figure 15.5. Accessing System Resources




      Containers are also expected to insert necessary AccessController.doPrivileged() calls so that applications are not required to be granted a Permission for a task that the container is expected to perform. For instance, if the container has configuration information in a directory /config, the container should retrieve configuration information from the files in that directory without requiring that the permissions be granted to applications. In order to achieve this, containers should access such container-specific resources within an AccessController.doPrivileged() call, as shown in Figure 15.6.



      Figure 15.6. Preventing Permission-Requirement Propagation




      This ensures that only the container is required to be granted necessary Permissions to access the resources required to perform its tasks. Applications will not be required to be granted those Permissions.













         < Day Day Up > 



        6.5 Waypoint Navigation











         < Day Day Up > 







        6.5 Waypoint Navigation



        Pathfinding can be a very time-consuming and CPU-intensive operation. One way to reduce this problem is to precalculate paths whenever possible. Waypoint navigation reduces this problem by carefully placing nodes in the game environment and then using precalculated paths or inexpensive pathfinding methods to move between each node. Figure 6-19 illustrates how to place nodes on a simple map consisting of seven rooms.





        Figure 6-19. Placing nodes







        In Figure 6-19, you'll notice that every point on the map is in the line of sight of at least one node. Also, every node is in the line of sight of at least one other node. With a game environment constructed in this way, a game-controlled character always will be able to reach any position on the map using a simple line-of-sight algorithm. The game AI simply needs to know how the nodes connect to one another. Figure 6-20 illustrates how to label and connect each node on the map.





        Figure 6-20. Labeling nodes







        Using the node labels and links shown in Figure 6-20, we can now determine a path from any room to any other room. For example, moving from the room containing node A to the room containing node E entails moving through nodes ABCE. The path between nodes is calculated by a line-of-sight algorithm, or it can be a series of precalculated steps. Figure 6-21 shows how a computer-controlled character, indicated by the triangle, would calculate a path to the player-controlled character, indicated by the square.





        Figure 6-21. Building a path







        The computer-controlled character first calculates which node is nearest its current location and in its line of sight. In this case, that is node A. It then calculates which node is nearest the player's current location and in the player's line of sight. That is node E. The computer then plots a course from its current position to node A. Then it follows the node connections from node A to node E. In this case, that is A B C E. Once it reaches the end node, it can plot a line-of-sight path from the final node to the player.



        This seems simple enough, but how does the computer know which nodes to follow? In other words, how does the computer know that to get from node A to node E, it must first pass through nodes B and C? The answer lies in a simple table format for the data that enables us to quickly and easily determine the shortest path between any two nodes. Figure 6-22 shows our initial empty node connection table.





        Figure 6-22. Empty node table







        The purpose of the table is to establish the connections between the nodes. Filling in the table becomes a simple matter of determining the first node to visit when moving from any starting node to any ending node. The starting nodes are listed along the left side of the table, while the ending notes are shown across the top. We will determine the best path to follow by looking at the intersection on the table between the starting and ending nodes. You'll notice that the diagonal on the table contains dashes. These table elements don't need to be filled in because the starting and ending positions are equal. Take the upper-left table element, for example. Both the starting and ending nodes are A. You will never have to move from node A to node A, so that element is left blank. The next table element in the top row, however, shows a starting node of A and an ending node of B. We now look at Figure 6-21 to determine the first step to make when moving from node A to node B. In this case, the next move is to node B, so we fill in B on the second element of the top row. The next table element shows a starting node of A and an ending node of C. Again, Figure 6-21 shows us that the first step to take is to node B. When filling in the table we aren't concerned with determining the entire path between every two nodes. We only need to determine the first node to visit when moving from any node to any other node. Figure 6-23 shows the first table row completed.





        Figure 6-23. Filling in the node table







        Figure 6-23 shows us that when moving from node A to any other node, we must first visit node B. Examining Figure 6-21 confirms this fact. The only node connected to node A is node B, so we must always pass through node B when moving from node A to any other node. Simply knowing that we must visit node B when moving from node A to node E doesn't get us to the destination. We must finish filling in the table. Moving to the second row in the table, we see that moving from node B to node A requires a move to node A. Moving from node B to node C requires a move to C. We continue doing this until each element in the table is complete. Figure 6-24 shows the completed node connection table.





        Figure 6-24. Completed node table







        By using the completed table shown in Figure 6-24, we can determine the path to follow to get from any node to any other node. Figure 6-25 shows an example of a desired path. In this figure, a hypothetical computer-controlled character, indicated by the triangle, wants to build a path to the player, indicated by the square.





        Figure 6-25. Finding the path







        To build a path we simply need to refer to the completed node connection table shown in Figure 6-24. As shown in Figure 6-25, we want to build a path from node B to node G. We start by finding the intersection on the table between node B and node G. The table shows node C at the intersection. So, the first link to traverse when moving from node B to node G is B C. Once we arrive at node C, we refer to the table again to find the intersection between node C and the desired destination, node G. In the case, we find node E at the intersection. We then proceed to move from C E. We repeat this process until the destination is reached. Figure 6-26 shows the individual path segments that are followed when building a path from node B to node G.





        Figure 6-26. Finding the path







        As Figure 6-26 shows, the computer-controlled character needs to follow four path segments to reach its destination.



        Each method we discussed here has its advantages and disadvantages, and it's clear that no single method is best suited for all possible pathfinding problems. Another method we mentioned at the beginning of this chapter, the A* algorithm, is applicable to a wide range of pathfinding problems. The A* algorithm is an extremely popular pathfinding algorithm used in games, and we devote the entire next chapter to the method.















           < Day Day Up > 



          Section 17.1.&nbsp; Overview










          17.1. Overview


          Before introducing declarative actions, let's take a step back and look at what an action is all about. The primary role of actions is to expose application behavior to the user. When you click on a menu item or toolbar item or invoke a key sequence, an action is run. Further, you can set up a system such that the same action is placed in a menu, a toolbar, and bound to a key sequenceactions allow you to separate behavior from placement. Actions also determine if they are enabled, figure out what elements to work on, run the work, and display the results.


          Below is a list of the basic responsibilities of actions. As you explore the various ways of defining and using actions, remember that these responsibilities apply regardless of how or where they are defined and usedonly the syntax is different.


          Placement Actions can be placed in many areas of the Workbench: in views, editors, context menus, and in top-level menus and toolbars. When they are created, they are given a reference to the container in which they are placed, allowing them to query for selection or access other information.

          Rendering There are several types of actions, for example, menus, toolbar buttons, radio buttons, drop-down menu buttons, and so on. When you create an action, you have to decide what type of action it is and how it will be rendered in the UI. Actions also contain basic information, such as a label, an icon, and a tool tip, which is used in displaying and describing the action to the user.

          Input and enablement Actions usually perform work on a set of objects. The input to an action is defined by the selection in the related UI part. For example, if an action is in a view, then the related selection is that of the widgets in the view. An action in the Workbench window uses the selection that comes from the active view or editor. As an action's context changes (e.g., its input changes or its container state changes), the action must update its enablement state.

          Behavior When an action is eventually run, it performs some operation on its input. If the action is long-running, it should show progress to the user.

          Binding An action can be controlled by the keyboard instead of by its explicit UI element. Actions can also be bound to other mechanisms that control when they are run.


          When you add an action, you have to implement each of these responsibilities. Figure 17-1 shows how the "Build" action from the IDE product implements these responsibilities.



          Figure 17-1. Action responsibilities

          [View full size image]




          The Build action is placed in the top-level toolbar and menu, it is rendered as a push button with a name and image, it's enabled when at least one project is selected, and its input is the selected project. Its behavior is to build the selected project.












          Chapter 4: Explore Range Objects












          Chapter 4: Explore Range Objects




          Chapter at a Glance







          In this chapter, you will learn to:




          • Use several properties to refer to Range objects from macro statements.




          • Put values and formulas into cells.




          • Simplify macros that record selections.




          • Apply formatting to ranges.




          • Use the Object Browser to learn about objects, properties, and methods.




          The world would be much simpler if people were all the same size. You wouldn’t need adjustable seats in your car; your head would never get bumped on a door frame; your feet would never dangle from a chair. Of course, you’d have new problems as well: When you went to exchange that hideous outfit you got for your birthday, you wouldn’t be able to claim it was the wrong size.


          When using Microsoft Visual Basic for Applications (VBA) to write macros for Microsoft Office Excel, you don’t need to worry about Range objects as long as all your worksheets and data files are the same size. For example, if you never insert new rows into a budget, if you always put yearly totals in column M, and if every month’s transaction file has exactly 12 columns and 120 rows, you can skip this chapter because the macro recorder can take care of dealing with ranges for you.


          But in the real-live human world, people are different sizes, and consequently clothes come in different sizes and cars have adjustable seats. And in the real-live worksheet world, models and data files have different-and changing-sizes, and your macros need to fit them. Excel provides many methods and properties for working with Range objects. In this chapter, you’ll explore Range objects and in the process learn how you can use the Object Browser to learn about any new, unfamiliar object.






          On The CD-Important 

          Before you complete this chapter, you need to install the practice files from the book’s companion CD to their default locations. See “Using the Book’s CD” on page xv for more information.




          USE the Ranges.xlsx workbook. This practice file is located in the Documents\MSP\ ExcelVBA07SBS folder.



          BE SURE TO save a macro-enabled copy of the Ranges.xlsx workbook as Chapter4.xlsm in the trusted folder location you created in Chapter 1.



          OPEN the Chapter4.xlsm workbook.
















          Conditionally Including the Body of a Custom Tag



          [ Team LiB ]





          Conditionally Including the Body of a Custom Tag


          A tag like the one just demonstrated can be useful in many applications where you want to output "template" text generated within the tag handler or where you want it to perform a function. For example, you could write a tag that outputs the current date and time. Beyond this, custom tags also allow you to interact with the body of a tag.


          Earlier in Listing 16.1, you saw that the doStartTag method in the custom tag returns a value of SKIP_BODY and the doEndTag method returns a value of EVAL_PAGE. These values tell the JSP engine how to handle the content between the start and end of the custom tag and also whether to continue evaluating the rest of the page after the custom closing tag. When doStartTag returns SKIP_BODY, it tells the JSP engine to ignore the content between the start and end of the custom tag. If the doStartTag returns EVAL_BODY_INCLUDE, the data between the start and end tags is evaluated and the results are copied to the response.


          When doEndTag returns EVAL_PAGE, it tells the JSP engine to continue evaluating the rest of the page. If doEndTag returns SKIP_PAGE, the JSP engine ignores everything else in the JSP after the closing tag and returns the response to the browser.


          Because you can control whether the JSP engine includes body text between the start and end of a tag, you can create tags that include text only if certain conditions are met.


          Listing 16.5 shows a custom tag that includes its content only when the time of day is between 6 a.m. and 6 p.m.


          Listing 16.5 Source Code for DayTag.java



          package examples.taglibs;

          import javax.servlet.jsp.tagext.*;
          import javax.servlet.jsp.*;
          import java.util.*;

          public class DayTag extends TagSupport
          {
          public int doStartTag()
          throws JspException
          {
          // Get the time of day.
          GregorianCalendar currTime = new GregorianCalendar();

          // Get the hour of day.
          int hour = currTime.get(Calendar.HOUR_OF_DAY);

          // If the time is between 6 a.m. and 6 p.m., tell the JSP engine to
          // include the text between the start and end tag.
          if ((hour >= 6) && (hour <= 18))
          {
          return EVAL_BODY_INCLUDE;
          }
          else
          {
          // Otherwise, ignore the body text.
          return SKIP_BODY;
          }
          }

          public int doEndTag()
          {
          return EVAL_PAGE;
          }
          }

          To process body content, it is necessary to make a slight change to the TLD. Instead of declaring the body content to be empty, it must now indicate that the body is meaningful. A TLD that works for this example appears in Listing 16.6


          Listing 16.6 Source Code for DayTag.java



          <?xml version="1.0" encoding="ISO-8859-1"?>

          <taglib xmlns=http://java.sun.com/xml/ns/j2ee
          xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
          xsi:schemaLocation=http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd
          version="2.0">
          <tlib-version>1.0</tlib-version>
          <short-name>DayTag</short-name>
          <description>
          A tag to that conditionally includes the body.
          </description>
          <tag>
          <name>DayTag</name>
          <tag-class>examples.taglibs.DayTag</tag-class>
          <body-content>jsp</body-content>
          </tag>
          </taglib>

          You can see that the body-content element has been changed to jsp, which causes the container to evaluate the body content as JSP source. You can instruct the container to output the body verbatim by using the value tagdependant, or cause the container to treat the body as though it had no scripting elements by declaring the body scriptless. Later in the hour, you'll see how to use tags whose bodies are scriptless.


          Listing 16.7 is a sample JSP that you can use to exercise this tag.


          Listing 16.7 Source Code for TestDayTag.jsp



          <%@ taglib uri="/daytag" prefix="daytag" %>
          <html>
          <body>
          <daytag:DayTag>
          It's between the hours of 6 am and 6 pm!
          </daytag:DayTag>
          </body>
          </html>




            [ Team LiB ]



            Recipe 22.1. Writing a C Extension for Ruby










            Recipe 22.1. Writing a C Extension for Ruby




            Credit: Garrett Rooney



            Problem


            You want to implement part of your Ruby program in C. This might be the part of your program that needs to run really fast, it might contain some very platformspecific code, or you might just have a C implementation already, and you don't want to also write one in Ruby.




            Solution


            Write a C extension that implements that portion of your program. Compile it with extconf.rb and require it in your Ruby program as though it were a Ruby library. You'll need to have the Ruby header files installed on your system.


            Here's a simple Ruby program that requires a library called example. It instantiates an instance of Example::Class from that library, and calls a method on that library:



            require 'example'
            e = Example::Class.new
            e.print_string("Hello World\n")
            # Hello World



            What would the example library look like if it were written in Ruby? Something like this:



            # example.rb
            module Example
            class Class
            def print_string(s)
            print s
            end
            end
            end



            Let's implement that same functionality in C code. This small C library, example.c, defines a Ruby module, class, and method using the functions made available by ruby.h:



            #include <ruby.h>
            #include <stdio.h>

            static VALUE rb_mExample;
            static VALUE rb_cClass;

            static VALUE
            print_string(VALUE class, VALUE arg)
            {
            printf("%s", RSTRING(arg)->ptr);
            return Qnil;
            }
            void
            Init_example()
            {
            rb_mExample = rb_define_module("Example");

            rb_
            cClass = rb_define_class_under(rb_mExample, "Class", rb_cObject);

            rb_define_method(rb_cClass, "print_string", print_string, 1);
            }



            To build the extension, you also need to create an extconf.rb file:



            # extconf.rb
            require 'mkmf'

            dir_config('example')
            create_makefile('example')



            Then you can build your library by running extconf.rb, then make:



            $ ls
            example.c extconf.rb

            $ ruby extconf.rb
            creating Makefile

            $ make
            gcc -fPIC -Wall -g -O2 -fPIC -I. -I/usr/lib/ruby/1.8/i486-linux
            -I/usr/lib/ruby/1.8/i486-linux -I. -c example

            gcc -shared -L"/usr/lib" -o example.so example.o -lruby1.8
            -lpthread -ldl -lcrypt -lm -lc

            $ ls
            Makefile example.c example.o example.so extconf.rb



            The example.so file contains your extension. As long as it's in your Ruby include path (and there's no example.rb that might mask it), you can use it like any other Ruby library:



            require 'example'
            e = Example::Class.new
            e.print_string("Hello World\n")
            # Hello World





            Discussion


            Most programs can be implemented using plain old Ruby code, but occasionally it turns out that it's better to implement part of the program in C. The example library above simply provides an interface to C's printf function, and Ruby already has a perfectly good IO#printf method.


            Perhaps you need to perform a calculation hundreds of thousands of times, and implementing it in Ruby would be too slow (the Example::Class#print_string method is faster than IO#printf). Or maybe you need to interact with some platformspecific API that's not exposed by the Ruby standard library. There are a number of reasons you might want to fall back to C code, so Ruby provides you with a reasonably simple way of doing it.


            Unfortunately, the fact that it's easy doesn't always mean it's a good idea. You must remember that when writing C-level code, you're playing with fire. The Ruby interpreter does its best to limit the damage you can do if you write bad Ruby code. About the worst you can do is cause an exception: another part of your program can catch the exception, handle it, and carry on. But C code runs outside the Ruby interpreter, and an error in C code can crash the Ruby interpreter.


            With that in mind, let's go over some of the details you need to know to write a
            C extension.


            A Ruby extension is just a small, dynamically loadable library, which the Ruby interpreter loads via dlopen or something similar. The entry point to your extension is via its Init function. For our example module, we defined an Init_example function to set everything up. Init_example is the first function to be called by the Ruby interpreter when it loads our extension.


            The Init_example function uses a number of functions provided by the Ruby interpreter to declare modules, classes, and methods, just as you might in Ruby code. The difference, of course, is that here the methods are implemented in C. In this example, we used rb_define_module to create the Example module, then rb_define_class_under to define the Example::Class class (which inherits from Object), and finally rb_define_ method to give Example::Class a print_string method.


            The first thing to notice in the C code is all the VALUE variables lying around. A VALUE is the C equivalent of a Ruby reference, and it can point to any Ruby object. Ruby provides you with a number of functions and macros for manipulating VALUEs.


            The rb_cObject variable is a VALUE, a reference to Ruby's Object class. When we pass it into rb_define_class_under, we're telling the Ruby interpreter to define a new subclass of Object. The ruby.h header file defines similar variables for many other Rubylevel modules (named using the rb_mFoo convention) and classes (the convention is rb_cFoo).


            To manipulate a VALUE, you need to know something about it. It makes no more sense in C code than in Ruby code to call a method of File on a value that refers to a string. The simplest way to check a Ruby object's type is to use the Check_Type macro, which lets you see whether or not a VALUE points to an instance of a particular Ruby class. For convenience, the ruby.h file defines constants T_STRING, T_ARRAY, and so on, to denote built-in Ruby classes.


            But that's not what we'd do in Ruby code. Ruby enforces duck typing, in which objects are judged on the methods they respond to, rather than the class they instantiate. C code can operate on Ruby objects the same way. To check whether an object responds to a
            particular message, use the
            function rb_respond_to. To send the message, use rb_funcall. It looks like this:



            static VALUE
            write_string(VALUE object, VALUE str)
            {
            if (rb_respond_to(object, rb_intern("<<")))
            {
            rb_funcall(object, rb_intern("<<"), 1, str);
            }
            return Qnil;
            }



            That's the C-level equivalent of the following Ruby code:



            def write_string(object, str)
            object << str if object.respond_to?('<<')
            return nil
            end



            A few more miscellaneous tips: the rb_intern function takes a symbol name as a C string and returns the corresponding Ruby symbol ID. You use this with functions like rb_respond_to and rb_funcall to refer to a Ruby method. Qnil is just the C-level name for Ruby's special nil object. There are a few similar constants, like Qfalse and Qtrue, which do just about what you'd think they'd do.


            There are a number of other C level functions that let you create and manipulate strings (look in for functions that start with rb_str), arrays (rb_ary), and hashes (rb_ hash). These APIs are pretty self-explanatory, so we won't go into them in depth here, but you can find them in the Ruby header files, specifically ruby.h and intern.h.


            Ruby also defines some macros to do convenient things with common data types. For example, the StringValuePtr macro takes a VALUE that refers to a ruby String and returns a C-style char pointer. This can be useful for interacting with C-level APIs. You can find this and other similar helpers in the ruby.h header.




            See Also


            • The file README.EXT file in the Ruby source tree

            • Recipe 22.2, "Using a C
              Library from Ruby"













            Distributing Tomcat





























            Chapter 1 -
            Apache and Jakarta Tomcat
            byVivek Chopra, Ben Galbraithet al.
            Wrox Press 2003































            Distributing Tomcat



            Tomcat is open source software, and as such is free and freely distributable. However, if you have much experience in dealing with open source software, you're probably aware that the terms of distribution can vary from project to project.


            Most open source software is released with an accompanying license that states what may and may not be done to the software. There are at least forty different open source licenses out there, each of which has slightly different terms.


            Providing a primer on all of the various open source licenses is beyond the scope of this chapter, but the license governing Tomcat will be discussed here and compared with a few of the more popular open source licenses.


            Tomcat is distributed under the Apache License, which can be read from the $CATALINA_HOME/LICENSE file. The key points of this license state that:




            • The Apache License must be included with any redistributions of Tomcat's sourcecode or binaries




            • Any documentation included with a redistribution must give a nod to the ASF




            • Products derived from the Tomcat sourcecode can't use the terms "The Jakarta Project", "Apache", or "Apache Software Foundation" to endorse or promote their software without prior written permission from the ASF




            • Tomcat has no warranty of any kind




            However, through omission, the license contains these additional implicit permissions:




            • Tomcat can be used by any entity, commercial or non-commercial, for free without limitation




            • Those who make modifications to Tomcat and distribute their modified version do not have to include the sourcecode of their modifications




            • Those who make modifications to Tomcat do not have to donate their modifications back to the ASF




            Thus, you're free to deploy Tomcat in your company in any way you see fit. It can be your production web server or your test servlet container used by your developers. You can also redistribute Tomcat with any commercial application that you may be selling, provided that you include the license and give credit to the ASF. You can even use the Tomcat sourcecode as the foundation for your own commercial product




            Comparison with Other Licenses


            Among the previously mentioned rather large group of other open source licenses, there are two licenses which are particularly popular at the present time: the GNU General Public License (GPL) and the GNU Lesser General Public License (LGPL). Let's take a look at how each of these licenses compare to the Apache License.




            GPL


            The GNU Project created and actively evangelizes the GPL. The GNU Project is somewhat similar to the ASF, with the exception that the GNU Project would like all of the non-free (that is, closed source or proprietary) software in the world to become free; the ASF has no (stated) desire to do this and simply wants to provide free software.



            What Does It Mean to Be Free?

            Free software can mean one of two entirely different things: software that doesn't cost anything, and software that can be freely copied, distributed, and modified by anyone (thus the sourcecode is included or available); such software can be distributed either for free or for a fee. A simpler way to explain the difference between these two types of free is "free as in free beer" and "free as in free speech". The GNU Project's goal is to create free software of the latter category. All uses of the phrase "free software" in the remainder of this section will use this definition.


            The differences between the Apache License and the GPL thus mirror the distinct philosophies of the two organizations. Specifically, the GPL has these key differences from the Apache License:




            • No non-free software may contain GPL-licensed products or use GPL-licensed sourcecode. If non-free software is found to contain GPL-licensed binaries or code, it must remove such elements or become free software itself.




            • All modifications made to GPL-licensed products must be released as free software if the modifications are also publicly released.




            These two differences have huge implications for commercial enterprises. If Tomcat were licensed under the GPL, any product that contained Tomcat would also have to be free software.


            Furthermore, while the Apache License permits an organization to make modifications to Tomcat and sell it under a different name as a closed source product, the GPL would not allow any such act to occur; the new derived product would also have to be released as free software.







            LGPL


            The LGPL is similar to the GPL, with one major difference: non-free software may contain LGPL-licensed products. The LGPL license is intended primarily for software libraries that are themselves free software but whose authors want them to be available for use by companies who produce non-free software.


            If Tomcat were licensed under the LGPL, it could be embedded in non-free software, but Tomcat could not itself be modified and released as a non-free software product.




            For more information on the GPL and LGPL licenses, see http://www.gnu.org/.






            Other Licenses


            Understanding and comparing open source licenses can be a rather complex task. The explanations above are an attempt to simplify the issues. For more detailed information on these and other licenses, there are two specific resources that can help you:




            • The Open Source Initiative (OSI) maintains a database of open source licenses. Visit them at http://www.opensource.org/.




            • The GNU Project, mentioned above, has an extensive comparison of open source licenses with the GPL license. See it at http://www.gnu.org/licenses/license-list.html.























            The goals of J2EE











             < Day Day Up > 





            The goals of J2EE



            As the old saying goes, it helps to know where we've been (and why we got there) in order to know where next to go. I want to explain the "why" and "how" of J2EE, in order to make sure that certain concepts (like lookup, which is important in Item 16, for example) are clear.



            Throughout the history of computer science, the overriding goal of any language, tool, or library has largely been to raise the level of abstraction away from details that distract us from the Real Work at hand. Consider the classic OSI seven-layer network stack, for example. It's not that when you "open a socket" you actually open something that directly pipes over to another machine; instead, that act serves as an abstraction over the four or five layers of software (and hardware, once you reach the physical layer) that each provide a certain amount of support to make all this stuff work.



            In the early days of enterprise systems, layers were painfully absent�all data access was done directly against files of fixed-length records, and anything that happened to those records was your business and yours alone. No layering was present because the systems we ran on in those days didn't have much in terms of CPU cycles or memory to spare. Everything had to be as tightly focused as it could be.



            As hardware capacity grew and demand for more complex processing grew with it, we found it necessary and desirable to have certain behavior guaranteed. So a layer of software was put on top of the traditional flat-file collection, and we called it a transaction processing system; it managed concurrent access to the data, making sure that the data obeyed the logical constraints we put into it via the code we wrote. Over time, this was formalized even further to include a powerful query syntax, and thus was the modern relational database, and SQL, born.



            Then we started wanting to let end users work with the data stored in the database, rather than feeding to data processing clerks the stacks of paper containing the data to be entered. Not only did college students lose a viable form of employment over the summer, but a new form of programming, the client/server architecture, was born. A program executed on the client machine, responsible for presentation and data capture, and turned that into statements of work to execute against the database system. Typically this program is of the graphical user interface variety, written in some higher-level language built specifically for this purpose, customized to the particular system being developed for the company.



            As the numbers of clients against these client/server systems grew, however, we began to run into a limitation: thanks to the internal processing that accompanies client action against a client/server database, the number of physical network connections (and the associated software costs) against the database have a definitive upper limit, thus placing an arbitrary cap on the number of users that can use the system at the same time. We can say that n clients was the upper limit of users against the system, where n was this maximum number of connections, and as soon as client n+1 wants to log in, we need a new database for him or her.



            Even the largest Fortune 50 companies could accept this state of affairs for a short period of time because the largest number of users against an enterprise system usually didn't crest four digits; despite the costs involved in doing so, it's usually possible, though not desirable, to push a new installation out to a thousand internal clients. As soon as we started adopting the Web as a public interface to enterprise systems, however, the situation changed radically�the Web is all about extending the corporation's "reach," and that meant users could, virtually speaking, visit the corporation from all over the world, all at once. Where we used to have thousands of clients, the Web meant that now we had millions.



            This exponential jump in the number of possible concurrent clients means that the old "one client, one connection" architecture isn't credibly possible anymore. A new breed of software architecture was necessary if this "bring the system to the end user via the Web" ideal was to have any chance of working.



            An old maxim in computer science states, "There is no problem that cannot be solved by adding an additional layer of indirection." In this case, because client programs don't typically make use of the connection they hold to the server 100% of the time, the layer of indirection introduced was a layer of software in between the clients and the server. (Note the deliberate terminology; see Item 3 for details.) This layer of resource-managing software, after a few years of wrestling for a good name, came to be known as middleware.













               < Day Day Up > 



              Monitoring Your Application









              Monitoring Your Application


              The most important thing in the server is your application, so we'll start our tour of JBoss's management and monitoring capabilities by looking at what JBoss can tell you about the state of currently running applications.



              How do I do that?


              If you drill down into the J2EE Domains section, you'll find an entry for the currently running JBoss instance. Inside that you'll find all the application packages deployed in the server: EAR files, WAR files, EJB jar files, and JBoss SAR (service archive) files. For deployments that are nested, such as with an EAR file, you can expand the parent archive to see the internal applications.


              If the ToDo application is still deployed, you should find todo.ear near the top of the list. Selecting todo.ear will display some basic deployment information, including the application.xml deployment descriptor, in the details section on the right.


              An EAR file is really just a container for other deployments, so there isn't much to see here. What you'll want to see are the contents of the EAR file. When you expand todo.ear, you'll see the two primary application components: todo.jar and todo.war.


              Selecting either of these will show deployment information for the archive, just as you saw for the EAR file. Even better, expanding either of these archives will show all the EJBs or servlets provided by that application. Figure 8-2 shows the view of the TaskMaster bean.



              Developer's Notebook 8-2. EJB statistics provided by the Web Console




              The Bean Statistics section shows the status of the bean pool. JBoss currently has six instances of the TaskMaster bean waiting to serve requests. CreateCount shows the number of times a TaskMaster bean has been created, meaning an object was taken from the bean pool and made ready to service client requests.


              Below that are the bean's invocation statistics. For each bean method, the total number of invocations processed is recorded, along with the minimum, maximum, and average processing time. You can see that, on average, it takes 145ms to create a new task, but 301ms to load all the tasks for a user. That load time seems a bit high, but it is actually skewed somewhat by the initial loading of data from the database. Once JBoss has cached the data, load times trend toward the minimum access time. You can verify this by resetting the statistics, using the Reset Stats link, and accessing the application again.


              You can find similar processing statistics for a servlet by selecting a servlet under todo.war. The ToDo application doesn't use servlets extensively. The only interesting servlet is FacesServlet, which processes JavaServer Faces requests. If you select it, you will see the minimum, maximum, and average response times for the servlet, as well as an invocation count.



              Note: If you are a J2EE guru, you might recognize this as the JSR-77 J2EE Management data.



              What just happened?


              You saw how to get basic usage statistics out of the server, down to the bean and servlet level. The available information isn't exhaustive, but it will help you locate performance problems for further investigation.










                1.17 Telling mysql to Read Queries from Other Programs




                I l@ve RuBoard










                1.17 Telling mysql to Read Queries from Other Programs




                1.17.1 Problem



                You want to shove the output from another program into
                mysql.





                1.17.2 Solution



                Use a pipe.





                1.17.3 Discussion



                An earlier section used the following command to show how
                mysql can read SQL statements from a file:



                % mysql cookbook < limbs.sql


                mysql can also read a pipe, to receive output from
                other programs as its input. As a trivial example, the preceding
                command is equivalent to this one:



                % cat limbs.sql | mysql cookbook


                Before you tell me that I've qualified for this
                week's "useless use of
                cat award,"[5]
                allow me to observe that you can substitute other commands for
                cat. The point is that any
                command that produces output consisting of semicolon-terminated SQL
                statements can be used as an input source for
                mysql. This can be useful in many ways. For
                example, the
                mysqldump
                utility is used to generate database backups. It writes a backup as a
                set of SQL statements that recreate the database, so to process
                mysqldump output, you feed it to
                mysql. This means you can use the combination of
                mysqldump and mysql to copy a
                database over the network to another MySQL server:


                [5] Under
                Windows, the equivalent would be the "useless use of
                type award":



                % mysqldump cookbook | mysql -h some.other.host.com cookbook


                Program-generated SQL also can be useful when you need to populate a
                table with test data but don't want to write the
                INSERT statements by hand. Instead, write a short
                program that generates the statements and send its output to
                mysql using a pipe:



                % generate-test-data | mysql cookbook




                1.17.4 See Also



                mysqldump is discussed further in Chapter 10.










                  I l@ve RuBoard



                  12.2 The File Chooser Package




                  I l@ve RuBoard










                  12.2 The File Chooser Package



                  Under
                  javax.swing, you'll
                  find a package of helper classes for the
                  JFileChooser. The
                  javax.swing.filechooser package contains several
                  classes for displaying and filtering files.




                  12.2.1 The FileFilter Class



                  The FileFilter class
                  can be used to create
                  filters for
                  JFileChooser dialogs. The class contains only two
                  abstract methods. It's important to note that
                  extensions are not the only way to judge a file's
                  fitness for a particular filter. The Mac filesystem, for example, can
                  understand the creator of a file regardless of the
                  file's name. On Unix systems, you might write a
                  filter to display only files that are readable by the current user.




                  12.2.1.1 Constructor



                  public FileFilter( )


                  The FileFilter class receives this default
                  constructor at compile time; it is not defined in the class itself.








                  12.2.1.2 Filter methods


                  public abstract boolean accept(File f)


                  Return true if file f matches
                  this filter. Note that you must explicitly accept directories
                  (f.isDirectory( ) == true) if you want to allow
                  the user to navigate into any subfolders.



                  public abstract String getDescription( )


                  Return a short description to appear in the filters pulldown on the
                  chooser. An example would be "Java Source
                  Code" for any .java files.





                  Figure 12-5 shows a file chooser with custom filters
                  for multimedia file types.




                  Figure 12-5. A custom set of filters for use with JFileChooser



                  Here's the code for the application. Before we make
                  this chooser visible, we create and insert the three new filters for
                  our media types. Other than that, it's pretty much
                  the same code as our previous applications. The Swing demos included
                  in the SDK provide access to a similar extension-based file filter
                  class. However, we use this example anyway, as it illustrates the
                  inner workings of a filter that should seem familiar to most
                  programmers.




                  // MyFilterChooser.java
                  // Just a simple example to see what it takes to make one of these filters work
                  //
                  import java.awt.*;
                  import java.awt.event.*;
                  import java.io.*;
                  import javax.swing.*;

                  public class MyFilterChooser extends JFrame {
                  public MyFilterChooser( ) {
                  super("Filter Test Frame");
                  setSize(350, 200);
                  setDefaultCloseOperation(EXIT_ON_CLOSE);

                  Container c = getContentPane( );
                  c.setLayout(new FlowLayout( ));

                  JButton openButton = new JButton("Open");
                  final JLabel statusbar = new JLabel("Output of your selection will go here");

                  openButton.addActionListener(new ActionListener( ) {
                  public void actionPerformed(ActionEvent ae) {
                  String[] pics = new String[] {"gif", "jpg", "tif"};
                  String[] audios = new String[] {"au", "aiff", "wav"};
                  JFileChooser chooser = new JFileChooser( );
                  chooser.addChoosableFileFilter(new SimpleFileFilter(pics,
                  "Images (*.gif, *.jpg, *.tif)"));
                  chooser.addChoosableFileFilter(new SimpleFileFilter(".MOV"));
                  chooser.addChoosableFileFilter(new SimpleFileFilter(audios,
                  "Sounds (*.aiff, *.au, *.wav)"));
                  int option = chooser.showOpenDialog(MyFilterChooser.this);
                  if (option == JFileChooser.APPROVE_OPTION) {
                  if (chooser.getSelectedFile( )!=null)
                  statusbar.setText("You chose " + chooser.getSelectedFile( ).getName( ));
                  }
                  else {
                  statusbar.setText("You canceled.");
                  }
                  }
                  });

                  c.add(openButton);
                  c.add(statusbar);
                  setVisible(true);
                  }

                  public static void main(String args[]) {
                  MyFilterChooser mfc = new MyFilterChooser( );
                  }
                  }


                  Here's the implementation of the filter class. You
                  pass in an extension (or list of extensions) and a description of the
                  extension(s) to the constructor. If you don't supply
                  a description, the constructor builds a simple one for you based on
                  the extensions you passed in. The only real work this class does
                  happens in the accept( ) method, where we look to
                  see if the file presented matches one of the supplied extensions.



                  // SimpleFileFilter.java
                  // A straightforward, extension-based example of a file filter. This should be
                  // replaced by a "first class" Swing class in a later release of Swing.
                  //
                  import javax.swing.filechooser.*;
                  import java.io.File;

                  public class SimpleFileFilter extends FileFilter {

                  String[] extensions;
                  String description;

                  public SimpleFileFilter(String ext) {
                  this (new String[] {ext}, null);
                  }

                  public SimpleFileFilter(String[] exts, String descr) {
                  // Clone and lowercase the extensions
                  extensions = new String[exts.length];
                  for (int i = exts.length - 1; i >= 0; i--) {
                  extensions[i] = exts[i].toLowerCase( );
                  }
                  // Make sure we have a valid (if simplistic) description.
                  description = (descr == null ? exts[0] + " files" : descr);
                  }

                  public boolean accept(File f) {
                  // We always allow directories, regardless of their extensions.
                  if (f.isDirectory( )) { return true; }

                  // It's a regular file, so check the extension.
                  String name = f.getName( ).toLowerCase( );
                  for (int i = extensions.length - 1; i >= 0; i--) {
                  if (name.endsWith(extensions[i])) {
                  return true;
                  }
                  }
                  return false;
                  }

                  public String getDescription( ) { return description; }
                  }





                  12.2.2 The FileView Class



                  Another abstract helper class in the
                  javax.swing.filechooser package is the
                  FileView class. This class is implemented by the
                  various L&Fs to supply

                  icons and descriptions
                  for the basic file and folder entries in the filesystem. While each
                  L&F has a default implementation of this class, you can write
                  your own and attach it to a file chooser to supply custom icons and
                  descriptions for interesting types of files.




                  12.2.2.1 Constructor



                  public FileView( )


                  The FileView class has only this default
                  constructor.








                  12.2.2.2 Methods


                  All of the methods for the FileView class are
                  abstract and take one File as an argument. You
                  fill in these methods to present a clean, consistent view of all
                  files throughout the file chooser. Most custom views end up making
                  decisions based on file information, such as the
                  file's name or extension, before returning a result
                  from these methods.




                  public abstract String getName(File f)


                  Return the name of file f. While
                  it's quite easy to return f.getName( ), you might want to return an all-uppercase version or a
                  cross-platform, CD-ROM-compliant (ISO 9660) name, etc.



                  public abstract String getDescription(File f)


                  Return a description of the file. The description could be a short
                  abstract of the file's contents. Your file chooser
                  might not necessarily display this information.



                  public abstract String getTypeDescription(File f)


                  Return a description of the type of the file, such as
                  "Directory" or
                  "Bitmap Image."



                  public abstract Icon getIcon(File f)


                  Return an icon appropriate for file f. This could
                  be a folder icon, a file icon, or some specific icon based on other
                  file information, such as its extension.



                  public abstract boolean isTraversable(File f)


                  Answer questions about whether a directory can be opened. For
                  example, Unix and Windows NT/2000 can prevent users from accessing
                  directories for which they don't have permission.
                  You could check permissions and return false if
                  the user is not allowed to open a given folder. Rather than get an
                  error when trying to open the folder, the user
                  doesn't get the chance to try.





                  Figure 12-6 is an example of a custom
                  FileView that (slowly!) displays tiny
                  representations of any .gif or
                  .jpg files in the directory instead of the
                  generic icons. Since it loads the real image and scales it, rather
                  than storing some separate set of real icons, you
                  shouldn't try this on your collection of 5,000 JPEG
                  clip-art images. It's great for small directories,
                  though. This example also relies on the
                  MetalIconFactory, so it does not run (properly)
                  under other L&Fs. To avoid this problem, we force the use of the
                  Metal L&F in the main( ) method by setting the
                  swing.defaultlaf system property.




                  Figure 12-6. A custom file view for a file chooser that displays icons of image files



                  Following is the code for this particular file view. Look at the
                  getIcon( ) method. That's where
                  we decide which icon to return for a particular file. In this
                  implementation, we list all directories as traversable and return a
                  rather generic type description for our files. Notice that in the
                  getName( ) method we check for an empty string. On
                  Windows platforms, this empty string corresponds to one of the drive
                  letters. The "name" of the file is
                  empty, but the path contains the appropriate information, so we
                  return that. If you're curious about the
                  MetalIconFactory that we use to get the file and
                  folder icons, check out Chapter 26.



                  You might notice that we store a Component object
                  (rather than JComponent) as our image observer.
                  The reason for this is twofold. First, that's one
                  class the createImage( ) method is defined in.
                  Second, one obvious choice for the observer is the frame containing
                  the application, which is frequently a JFrame, and
                  JFrame does not descend from
                  JComponent.




                  // ThumbNailFileView.java
                  // A simple implementation of the FileView class that provides a 16 x 16 image of
                  // each GIF or JPG file for its icon. This could be SLOW for large images, as we
                  // simply load the real image and then scale it.
                  //
                  import java.io.File;
                  import java.awt.*;
                  import javax.swing.*;
                  import javax.swing.filechooser.*;
                  import javax.swing.plaf.metal.MetalIconFactory;

                  public class ThumbNailFileView extends FileView {

                  private Icon fileIcon = MetalIconFactory.getTreeLeafIcon( );
                  private Icon folderIcon = MetalIconFactory.getTreeFolderIcon( );
                  private Component observer;

                  public ThumbNailFileView(Component c) {
                  // We need a component to create our icon's image.
                  observer = c;
                  }

                  public String getDescription(File f) {
                  // We won't store individual descriptions, so just return the
                  // type description.
                  return getTypeDescription(f);
                  }

                  public Icon getIcon(File f) {
                  // Is it a folder?
                  if (f.isDirectory( )) { return folderIcon; }

                  // It's a file, so return a custom icon if it's an image file.
                  String name = f.getName( ).toLowerCase( );
                  if (name.endsWith(".jpg") || name.endsWith(".gif")) {
                  return new Icon16(f.getAbsolutePath( ));
                  }

                  // Return the generic file icon if it's not.
                  return fileIcon;
                  }

                  public String getName(File f) {
                  String name = f.getName( );
                  return name.equals("") ? f.getPath( ) : name;
                  }

                  public String getTypeDescription(File f) {
                  String name = f.getName( ).toLowerCase( );
                  if (f.isDirectory( )) { return "Folder"; }
                  if (name.endsWith(".jpg")) { return "JPEG Image"; }
                  if (name.endsWith(".gif")) { return "GIF Image"; }
                  return "Generic File";
                  }

                  public Boolean isTraversable(File f) {
                  // We'll mark all directories as traversable.
                  return f.isDirectory( ) ? Boolean.TRUE : Boolean.FALSE;
                  }

                  public class Icon16 extends ImageIcon {
                  public Icon16(String f) {
                  super(f);
                  Image i = observer.createImage(16, 16);
                  i.getGraphics( ).drawImage(getImage( ), 0, 0, 16, 16, observer);
                  setImage(i);
                  }

                  public int getIconHeight( ) { return 16; }
                  public int getIconWidth( ) { return 16; }

                  public void paintIcon(Component c, Graphics g, int x, int y) {
                  g.drawImage(getImage( ), x, y, c);
                  }
                  }
                  }


                  Here's the application that uses this file view
                  implementation. The only real change from the previous applications
                  is in the properties we set for the chooser and our forced use of the
                  Metal L&F.



                  // MyViewChooser.java
                  // A simple example to see what it takes to make one of these FileViews work
                  //
                  import java.awt.*;
                  import java.awt.event.*;
                  import java.io.*;
                  import javax.swing.*;

                  public class MyViewChooser extends JFrame {
                  JFrame parent;
                  public MyViewChooser( ) {
                  super("File View Test Frame");
                  setSize(350, 200);
                  setDefaultCloseOperation(EXIT_ON_CLOSE);
                  parent = this;

                  Container c = getContentPane( );
                  c.setLayout(new FlowLayout( ));

                  JButton openButton = new JButton("Open");
                  final JLabel statusbar = new JLabel("Output of your selection will go here");

                  openButton.addActionListener(new ActionListener( ) {
                  public void actionPerformed(ActionEvent ae) {
                  JFileChooser chooser = new JFileChooser( );

                  // Set up our own file view for the chooser.
                  chooser.setFileView(new ThumbNailFileView(MyViewChooser.this));

                  int option = chooser.showOpenDialog(parent);
                  if (option == JFileChooser.APPROVE_OPTION) {
                  statusbar.setText("You chose " + chooser.getSelectedFile( ).getName( ));
                  }
                  else {
                  statusbar.setText("You cancelled.");
                  }
                  }
                  });

                  c.add(openButton);
                  c.add(statusbar);
                  }

                  public static void main(String args[]) {
                  System.setProperty("swing.defaultlaf",
                  "javax.swing.plaf.metal.MetalLookAndFeel");
                  MyViewChooser vc = new MyViewChooser( );
                  vc.setVisible(true);
                  }
                  }





                  12.2.3 The FileSystemView Class



                  Another
                  detail missing from the normal
                  FileChooser dialog is a system-independent way of
                  asking for a look at the entire filesystem. On Windows machines, for
                  example, there are several "root"
                  directories�one for each floppy drive, hard drive, CD drive,
                  etc. On Unix systems (which includes Mac
                  OS X), there is only one root directory, named
                  "/". The abstract
                  FileSystemView class is meant to be a source for
                  system-independent views that map nicely to the real filesystem
                  underneath your application. Currently, both Unix and Win32 systems
                  have real implementations, and others are planned for release. (MacOS
                  X relies on a Unix view of things.) Systems that do not have a full
                  implementation use a generic filesystem view, similar to what is
                  available through the standard java.io.File class.




                  12.2.3.1 Class instantiation method



                  public static FileSystemView getFileSystemView( )


                  The default implementation
                  checks the file separator character to decide which filesystem view
                  to return. A / returns a Unix view,
                  \ returns a Win32 view, and everything else gets
                  the generic view.








                  12.2.3.2 File and folder methods


                  If you
                  do plan to build your own filesystem view, the following methods are
                  the key pieces to look at:



                  public abstract File createNewFolder(File containingDir) throws IOException


                  Create a new folder with some default name appropriate to the
                  filesystem.



                  public File[] getFiles(File dir, boolean useFileHiding)


                  Return a list of all of the files in dir. If
                  useFileHiding is true, each
                  file in dir is checked with isHiddenFile( ) before being added to the list.



                  public File[] getRoots( )


                  Return a list of "root"
                  directories. On Unix or Mac OS X systems, this is the
                  / directory. On Windows machines, this is a list
                  of the active drive letters. In OS X, secondary partitions (including
                  mounted removable media) are listed in the
                  /Volumes directory. Users are accustomed to
                  thinking of these as separate entities, so you might want to add your
                  own code to include them as separate
                  "roots."



                  public boolean isHiddenFile(File f)


                  Return true if file f is a
                  hidden file. What makes a file a hidden file differs from system to
                  system.



                  public boolean isRoot(File f)


                  Return true if file f maps
                  to a root directory.













                    I l@ve RuBoard