Wednesday, January 20, 2010

Chapter 5.  An Introduction to Java Imaging









Chapter 5. An Introduction to Java Imaging


This chapter presents an overview of image loading and processing in Java, areas that have seen major changes in recent releases of the SDK, mainly driven by the wish for speed. It's principally about introducing concepts that are illustrated in more detail in Chapter 6.


I begin by reviewing the (rather outmoded) AWT imaging model, which is being superseded by the BufferedImage and VolatileImage classes, ImageIO, and the wide range of BufferedImageOp image operations offered by Java 2D. If these aren't enough, then Java Advanced Imaging (JAI) has even more capabilities.


Many of the topics discussed here are utilized in Chapter 6, where I develop a ImagesLoader class. It loads images from a Java ARchive (JAR) file using ImageIO's read( ) and holds them as BufferedImage objects.


Chapter 6 utilizes ImagesLoader in an ImagesTests application, which demonstrates 11 different visual effects, including zapping, teleportation, reddening, blurring, and flipping. The effects are derived from Java 2D operations, such as convolution and affine transformation.










    A.3 Advantages of the New Join Syntax











     < Day Day Up > 







    A.3 Advantages of the New Join Syntax





    The ANSI join syntax



    represents a bit of an adjustment to

    developers who are used to using Oracle's

    traditional join syntax, including the outer join operator

    (+). However, there are several advantages to

    using the syntax introduced in Oracle9i

    Database:





    • The new join syntax follows the ANSI standard, making your code more

      portable.

    • The ON and USING clauses keep join conditions away from the filter

      conditions in the WHERE clause. This enhances development

      productivity and the maintainability of your code.

    • The ANSI/ISO syntax makes it possible to perform a full outer join

      without having to perform a UNION of two SELECT queries.



    We recommend that while working with Oracle9i

    Database and later Oracle releases,

    you use the new join syntax instead of the traditional join syntax.



















       < Day Day Up > 



      Watching the Server









      Watching the Server


      A TourWatcher tHRead monitors the server's output, waiting for messages. The message types are listed below with a brief description of what the TourWatcher does in response:



      create n x z


      Create a distributed sprite in the local world with name n at position (x, 0, z). By default, the sprite will face forward along the positive z-axis.



      wantDetails A P


      The client at IP address A and port P is requesting information about the local sprite on this machine. Gather the data and send the data back in a "detailsFor" message.



      detailsFor n1 x1 z1 r


      Create a distributed sprite with the name n1 at location (x1,0,z1), rotated r radians away from the positive z-axis.



      n <move or rotation command>


      <command> can be one of forward, back, left, right, rotCClock, or rotClock. The distributed sprite with name n is moved or rotated. rotCClock is a counter-clockwise rotation, and rotClock is clockwise.



      n bye


      A client has left the world, so the distributed sprite with name n is detached (deleted).



      The activities using these messages are shown in Figures Figure 32-6, 32-7, and 32-8.


      Almost all the messages are related to distributed sprites in the local world: creation, movement, rotation, and deletion. Therefore, these tasks are handled by TourWatcher, which maintains its sprites in a HashMap, mapping sprite names to DistTourSprite objects:



      private HashMap visitors; // stores (name, sprite object) pairs



      The run( ) method in TourWatcher accepts a message from the server and tests the first word in the message to decide what to do:



      public void run( )
      { String line;
      try {
      while ((line = in.readLine( )) != null) {
      if (line.startsWith("create"))
      createVisitor( line.trim( ) );
      else if (line.startsWith("wantDetails"))
      sendDetails( line.trim( ) );
      else if (line.startsWith("detailsFor"))
      receiveDetails( line.trim( ) );
      else
      doCommand( line.trim( ) );
      }
      }
      catch(Exception e) // socket closure causes termination of while
      { System.out.println("Link to Server Lost");
      System.exit( 0 );
      }
      }




      Creating a Distributed Sprite


      A distributed sprite is made in response to a create n x z message by creating a DistTourSprite object with name n at location (x, 0, z) oriented along the positive z-axis. The name and sprite object are stored in the visitors HashMap for future reference.



      private void createVisitor(String line)
      {
      StringTokenizer st = new StringTokenizer(line);


      st.nextToken( ); // skip "create" word
      String userName = st.nextToken( );
      double xPosn = Double.parseDouble( st.nextToken( ) );
      double zPosn = Double.parseDouble( st.nextToken( ) );

      if (visitors.containsKey(userName))
      System.out.println("Duplicate name -- ignoring it");
      else {
      DistTourSprite dtSprite =
      w3d.addVisitor(userName, xPosn, zPosn, 0);
      visitors.put( userName, dtSprite);
      }
      }



      A potential problem is if the proposed name has been used for another sprite. TourWatcher only prints an error message to standard output; it would be better if a message was sent back to the originating client.




      The Distributed Sprites Class


      DistTourSprite is a simplified version of TourSprite: its sprite movement and rotation interface is the same as TourSprite's, but DistTourSprite doesn't send messages to the server. The complete class appears in Example 32-2.



      Example 32-2. The DistTourSprite class


      public class DistTourSprite extends Sprite3D
      {
      private final static double MOVERATE = 0.3;
      private final static double ROTATE_AMT = Math.PI / 16.0;

      public DistTourSprite(String userName, String fnm, Obstacles obs,
      double xPosn, double zPosn)
      { super(userName, fnm, obs);
      setPosition(xPosn, zPosn);
      }

      // moves
      public boolean moveForward( )
      { return moveBy(0.0, MOVERATE); }

      public boolean moveBackward( )
      { return moveBy(0.0, -MOVERATE); }

      public boolean moveLeft( )
      { return moveBy(-MOVERATE,0.0); }

      public boolean moveRight( )
      { return moveBy(MOVERATE,0.0); }

      // rotations in Y-axis only
      public void rotClock( )
      { doRotateY(-ROTATE_AMT); } // clockwise


      public void rotCounterClock( )
      { doRotateY(ROTATE_AMT); } // counter-clockwise

      } // end of DistTourSprite class






      Moving and Rotating a Distributed Sprite


      doCommand( ) in TourWatcher distinguishes between the various move and rotation messages and detects bye:



      private void doCommand(String line)
      {
      StringTokenizer st = new StringTokenizer(line);
      String userName = st.nextToken( );
      String command = st.nextToken( );

      DistTourSprite dtSprite =
      (DistTourSprite) visitors.get(userName);
      if (dtSprite == null)
      System.out.println(userName + " is not here");
      else {
      if (command.equals("forward"))
      dtSprite.moveForward( );
      else if (command.equals("back"))
      dtSprite.moveBackward( );
      else if (command.equals("left"))
      dtSprite.moveLeft( );
      else if (command.equals("right"))
      dtSprite.moveRight( );
      else if (command.equals("rotCClock"))
      dtSprite.rotCounterClock( );
      else if (command.equals("rotClock"))
      dtSprite.rotClock( );
      else if (command.equals("bye")) {
      System.out.println("Removing info on " + userName);
      dtSprite.detach( );
      visitors.remove(userName);
      }
      else
      System.out.println("Do not recognise the command");
      }
      } // end of doCommand( )



      All of the commands start with the sprite's name, which is used to look up the DistTourSprite object in the visitors HashMap. If the object cannot be found then TourWatcher notifies only the local machine; it should probably send an error message back to the original client.


      The various moves and rotations are mapped to calls to methods in the DistTourSprite object. The bye message causes the sprite to be detached from the local world's scene graph and removed from the HashMap.




      Responding to Sprite Detail Requests


      Figure 32-6 shows that a wantDetails A P message causes TourWatcher to collect information about the sprite local to this machine. The details are sent back as a detailsFor A P x1 z1 r message to the client at IP address A and port P. The information states that the sprite is currently positioned at (x1, 0, z1) and rotated r radians away from the positive z-axis.


      TourWatcher doesn't manage the local sprite, so passes the wantDetails request to the WrapNetTour3D object for processing:



      private void sendDetails(String line)
      { StringTokenizer st = new StringTokenizer(line);
      st.nextToken( ); // skip 'wantDetails' word
      String cliAddr = st.nextToken( );
      String strPort = st.nextToken( ); // don't parse

      w3d.sendDetails(cliAddr, strPort);
      }



      sendDetails( ) in WrapNetTour3D accesses the local sprite (referred to as bob) and constructs the necessary reply:



      public void sendDetails(String cliAddr, String strPort)
      { Point3d currLoc = bob.getCurrLoc( );
      double currRotation = bob.getCurrRotation( );
      String msg = new String("detailsFor " + cliAddr + " " +
      strPort + " " +
      df.format(currLoc.x) + " " +
      df.format(currLoc.z) + " " +
      df.format(currRotation) );
      out.println(msg);
      }



      The (x, z) location is formatted to four decimal places to reduce the length of the string sent over the network.




      Receiving Other Client's Sprite Details


      Figure 32-6 shows that when a user joins the world, it will be sent detailsFor messages by the existing clients. Each of these messages is received by TourWatcher, and leads to the creation of a distributed sprite.


      TourWatcher's receiveDetails( ) method pulls apart a detailsFor n1 x1 z1 r message and creates a DistTourSprite with name n1 at (x1, 0, z1) and rotation r:



      private void receiveDetails(String line)
      {
      StringTokenizer st = new StringTokenizer(line);

      st.nextToken( ); // skip 'detailsFor' word
      String userName = st.nextToken( );
      double xPosn = Double.parseDouble( st.nextToken( ) );

      double zPosn = Double.parseDouble( st.nextToken( ) );
      double rotRadians = Double.parseDouble( st.nextToken( ) );

      if (visitors.containsKey(userName))
      System.out.println("Duplicate name -- ignoring it");
      else {
      DistTourSprite dtSprite =
      w3d.addVisitor(userName, xPosn, zPosn, rotRadians);
      visitors.put( userName, dtSprite);
      }
      }



      The new sprite must be added to the local world's scene graph, so it is created in WrapNetTour3D by addVisitor( ):



      public DistTourSprite addVisitor(String userName,
      double xPosn, double zPosn, double rotRadians)
      {
      DistTourSprite dtSprite =
      new DistTourSprite(userName,"Coolrobo.3ds", obs, xPosn, zPosn);
      if (rotRadians != 0)
      dtSprite.setCurrRotation(rotRadians);

      BranchGroup sBG = dtSprite.getBG( );
      sBG.compile( ); // generally a good idea
      try {
      Thread.sleep(200); // delay a little, so world is finished
      }
      catch(InterruptedException e) {}
      sceneBG.addChild( sBG );

      if (!sBG.isLive( )) // just in case, but problem seems solved
      System.out.println("Visitor Sprite is NOT live");
      else
      System.out.println("Visitor Sprite is now live");

      return dtSprite;
      }



      Two important elements of this code are that the sub-branch for the distributed sprite is compiled, and the method delays for 200 ms before adding it to the scene. Without these extras, the new BranchGroup, sBG, sometimes fails to become live, which means that it subsequently cannot be manipulated (e.g., its TRansformGroup cannot be adjusted to move or rotate the sprite).


      The problem appears to be due to the threaded nature of the client: WrapNetTour3D may be building the world's scene graph at the same time that TourWatcher is receiving detailsFor messages, so it is adding new branches to the same graph. It is (just about) possible that addVisitor( ) is called before the scene graph has been compiled (and made live) in createSceneGraph( ). This means Java 3D will be asked to add a branch (sBG) to a node (sceneBG) which is not yet live, causing the attachment to fail.


      My solution is to delay the attachment by 200 ms, which solves the problem, at least in the many tests I've carried out.



      Another thread-related problem of this type is when multiple threads attempt to add branches to the same live node simultaneously. This may cause one or more of the attachments to fail to become live. The solution is to add the synchronization code to the method doing the attachment, preventing multiple threads from executing it concurrently. Fortunately, this problem doesn't arise in NetTour3D since new branches are only added to a client by a single TourWatcher thread.










        Puzzle 69: Fade to Black











         < Day Day Up > 







        Puzzle 69: Fade to Black



        Suppose that you can't modify classes X and C in the previous puzzle (Puzzle 68). Can you write a class whose main method reads the value of the field Z in class X.Y and prints it? Do not use reflection.













        Solution 69: Fade to Black



        At first, this puzzle may appear impossible. After all, the class X.Y is obscured by a field of the same name, so an attempt to name it will refer to the field instead.



        In fact, it is possible to refer to an obscured type name. The trick is to use the name in a syntactic context where a type is allowed but a variable is not. One such context is the region between the parentheses in a cast expression. The following program solves the puzzle by using this technique and prints Black as expected:





        public class FadeToBlack {

        public static void main(String[] args){

        System.out.println(((X.Y)null).Z);

        }

        }




        Note that we are accessing the Z field of class X.Y by using an expression of type X.Y. As we saw in Puzzles 48 and 54, accessing a static member using an expression in place of a type name is a legal but questionable practice.



        You can also solve this puzzle without resorting to questionable practices, by using the obscured class in the extends clause of a class declaration. Because a base class is always a type, names appearing in extends clauses are never resolved as variable names. The following program demonstrates this technique. It too prints Black:





        public class FadeToBlack {

        static class Xy extends X.Y { }



        public static void main(String[] args){

        System.out.println(Xy.Z);

        }

        }




        If you are using release 5.0 or a later release you can also solve the puzzle by using X.Y in the extends clause of a type variable declaration:





        public class FadeToBlack {

        public static <T extends X.Y> void main(String[] args) {

        System.out.println(T.Z);

        }

        }




        In summary, to solve a problem caused by the obscuring of a type by a variable, rename the type and variable in accordance with standard naming conventions, as discussed in Puzzle 68. If this is not possible, use the obscured type name in a context where only type names are allowed. With any luck, you will never have to resort to such contortions, as most library authors are sane enough to avoid the questionable practices that make them necessary. If, however, you do find yourself in this situation, it's nice to know that there is a workaround.

















           < Day Day Up > 



          Definer and Invoker Rights













          Definer and Invoker Rights

          PL/SQL subprograms, by default, were executed in the schema of the owner of these objects prior to Oracle8i. This is referred to as definer rights, meaning these programs were executed in and according to the authorization and authentication of the schema defining these programs. Also, any underlying objects to be created, altered, or dropped in the process of execution were in the definer schema. This approach has a disadvantage, however.


          The output of these subprograms became available as kind of centralized in the definer schema. That is, even executed by different schemas, the output becomes available in the tables in the owner schema. This centralization of data is unsuitable if each user requires a local disparate copy of the output in his or her own schema.




          Invoker Rights Model


          Oracle8i introduced the concept of invoker rights, which enables subprograms to be executed in and according to the authorization and authentication of the schema invoking (i.e., executing) the subprogram. Invoker rights are specified by the AUTHID clause. The syntax for this clause is as follows:



          AUTHID CURRENT_USER | DEFINER

          You can specify the AUTHID clause for a procedure, function, package, or object type only. Here, CURRENT_USER is the schema name of the user executing the subprogram or object type, and DEFINER is the schema name of the user owning the subprogram or object type. DEFINER is the default.





          One Application Program, Multiple Schemas



          Consider an order entry application that processes orders for different regions. Each region should operate its own separate schema, so there are tables such as ORDERS and ORDER_ITEMS. It isn't so simple, however. These tables have to be created having the region_name as part of the table name and in the schema of each individual region. This means that the table names have to be dynamically generated. Not only this—the DML operations should be performed on these tables in the schema of the individual region. To dynamically generate the table names, the immediate solution seems to be using DBMS_SQL. What about creating the tables and performing the DML on these tables in the schema of the individual region? AUTHID does the job.


          For simplicity, let's assume that there are two regions: region1 and region2. The corresponding schema names are region1 and region2. Also, there is a third user, which is the common user whose schema owns the common code. Let's signify this common user with the username "name" and the password "plsql9i/plsql9i."


          Here's the code to create the schemas region1 and region2:



          connect system/manager;
          create user region1 identified by region1;
          grant connect, resource to region1;

          create user region2 identified by region2;
          grant connect, resource to region2;

          The following code illustrates a sample procedure implementing both of the preceding requirements:




          Create or replace Procedure create_dyn_table
          (i_region_name VARCHAR2,
          retcd OUT NUMBER,
          errmsg OUT VARCHAR2)
          authid current_user
          Is
          cur_id INTEGER;
          ret_code INTEGER;
          Dyn_string VARCHAR2(1000);
          Dyn_Table_name VARCHAR2(21);
          Begin
          dyn_table_name := 'ORDERS_FOR_'||i_region_name;
          dyn_string := ' CREATE TABLE ' ||dyn_table_name||
          ' (order_id NUMBER(10) PRIMARY KEY,
          order_date DATE NOT NULL,
          total_qty NUMBER,
          total_price NUMBER(15,2))';
          cur_id := DBMS_SQL.OPEN_CURSOR;
          DBMS_SQL.PARSE(cur_id, dyn_string, DBMS_SQL.V7);
          ret_code := DBMS_SQL.EXECUTE(cur_id);
          DBMS_SQL.CLOSE_CURSOR(cur_id);
          retcd := 0;
          EXCEPTION WHEN OTHERS THEN
          retcd := SQLCODE;
          errmsg := 'ERR: Creating table '||dyn_table_name ||' - '||SQLERRM;
          End;
          /


          Now this procedure is created in the schema plsql9i/plsql9i, and the individual users region1 and region2 can execute this procedure in their own schemas. The following script does the job:




          /* File name authid.sql */
          connect plsql9i/plsql9i;
          Create or replace Procedure create_dyn_table
          (i_region_name VARCHAR2,
          retcd OUT NUMBER,
          errmsg OUT VARCHAR2)
          authid current_user
          is
          cur_id INTEGER;
          ret_code INTEGER;
          dyn_string VARCHAR2(1000);
          dyn_Table_name VARCHAR2(21);
          Begin
          dyn_table_name := 'ORDERS_FOR_'||i_region_name;
          dyn_string := ' CREATE TABLE ' ||dyn_table_name||
          ' (order_id NUMBER(10) PRIMARY KEY,
          order_date DATE NOT NULL,
          total_qty NUMBER,
          total_price NUMBER(15,2))';
          cur_id := DBMS_SQL.OPEN_CURSOR;
          DBMS_SQL.PARSE(cur_id, dyn_string, DBMS_SQL.V7);
          ret_code := DBMS_SQL.EXECUTE(cur_id);
          DBMS_SQL.CLOSE_CURSOR(cur_id);
          retcd := 0;
          EXCEPTION WHEN OTHERS THEN
          retcd := SQLCODE;
          errmsg := 'ERR: Creating table '||dyn_table_name ||' - '||SQLERRM;
          End;
          /
          grant execute on create_dyn_table to public;
          connect region1/region1;
          create synonym create_dyn_table for plsql9i.create_dyn_table;
          declare
          retcd NUMBER;
          errmsg VARCHAR2(100);
          begin
          create_dyn_table('REGION1',retcd, errmsg);
          end;
          /
          select table_name from user_tables where table_name like '%REGION1';
          connect region2/region2;
          create synonym create_dyn_table for plsql9i.create_dyn_table;
          declare
          retcd NUMBER;
          errmsg VARCHAR2(100);
          begin
          create_dyn_table('REGION2',retcd, errmsg);
          end;
          /
          select table_name from user_tables where table_name like '%REGION2';


          Here's the output of the preceding script:









          Thus, you can see that the invoker rights model provides centralization of code (application programs) and decentralization (in fact, localization) of data. Semantic external references in the code are resolved in the schema of the invoker of the code.












          Tip�


          When no AUTHID clause is specified, the default is AUTHID DEFINER.







          Tip�

          Invoker rights checks for privileges at program execution time. This is in contrast to definer rights, where external references are resolved at compile time. Also, only data element references (of tables and views) can be resolved, not those of program elements.







          Tip�

          When you use invoker rights, external references in SQL statements are resolved with the privileges of the invoker. References in PL/SQL statements are still resolved with the privileges of the owner. Granting via roles is allowed as long as it doesn't affect the compile time resolution of the invoker rights routine.






          Invoker Rights and Dynamic SQL


          The create_dyn_table used the AUTHID clause to take advantage of invoker rights. This procedure made use of dynamic SQL using DBMS_SQL to explain invoker rights. Once dynamic SQL comes into the picture, many issues are involved, such as




          • Which user is the owner of the program?




          • Which user is executing the program?




          • Under which schema is the application output being created?





          As the example in the preceding section illustrates, invoker rights provide the answer to all these questions. As a rule of the thumb, follow the next Tip when you use dynamic SQL, either native dynamic SQL or DBMS_SQL.






          Tip�

          When you use dynamic SQL and/or dynamic PL/SQL, either using native dynamic SQL or DBMS_SQL, always specify AUTHID CURRENT_USER for all stored subprograms.













          Dynamic Method Dispatch













          Dynamic Method Dispatch

          Inheritance with type hierarchies leads to dynamic method dispatch. Dynamic method dispatch is the method by which Oracle implements dynamic polymorphism. Polymorphism is ability to use multiple methods with the same name with different data. There are two types of polymorphism: static and dynamic. Static polymorphism refers to choosing the appropriate method based on the data at compile time and ideally is implemented using method overloading. Dynamic polymorphism refers to selecting the appropriate method to be executed depending on the data at runtime. In PL/SQL 9i this is implemented using dynamic method dispatch. In other words, dynamic method dispatch is the ability to determine at runtime and execute the most specific method in the object hierarchy that corresponds to the instance of the object type that invokes the method.


          As evident from the previous section, you can override a method of an object type in the subtypes in a type hierarchy. In the Book hierarchy described earlier, the display_info method is first specified in the supertype book_type and overridden in each of the subtypes literature_type, fiction_type, novel_type, and mystery_type. This resulted in multiple implementations of display_info depending on the subtype. Now, when you use the type hierarchy, objects are defined based on the supertypes and subtypes. Then member methods are invoked based on the type of object defined. The method call is dispatched to the corresponding type's implementation and then executed.


          How does PL/SQL determine which method implementation to use on the particular object instance? As an example, in the case of the lit_classic and classic_book objects defined earlier, how does PL/SQL know what method implementation of the display_info method is to be used? It does this by using dynamic method dispatch. PL/SQL uses that method implementation in the type hierarchy that is "nearest" to the type of object on which the method is invoked. It does this by checking, starting with the current type and navigating through the hierarchy to its supertypes, if any. This is done at runtime depending on the object instance on which the particular method is invoked. Here's an example:




          declare
          lit_classic literature_type;
          classic_book mystery_type;
          begin
          lit_classic := literature_type('DREAMS UNLIMITED','Bulusu Lakshman',
          0112224444,'Books International', 'Y',
          'Fiction','Booker Prize');
          lit_classic.display_info;
          classic_book := mystery_type('DREAMS UNLIMITED','Bulusu Lakshman',
          0112224444,'Books International', 'Y','Fiction',
          'Booker Prize','Scientific','Y','Medical Related');
          classic_book.display_info;
          end;
          /


          Here's the output of this program:








          The following points are worth noting:




          • Two different book objects are defined using the subtypes literature_type and mystery_type. Each of these objects is instantiated and its attributes populated using the appropriate constructor for the corresponding object type.





          • The display_info method is invoked on each object instance. The method name is the same for both the lit_classic and classic_book objects. For the lit_classic object, this displays the attribute information for its type as well as its supertype (i.e., book_type). For the classic_book object, this works out from the root of the type hierarchy and displays all information from all of its supertypes as well as its own specific attributes.




          • Compiling the types in the type hierarchy resolves the display_info method in each of the types and the code compiles successfully. But during execution of the previous PL/SQL block, dynamic method dispatch comes into play. The PL/SQL runtime engine does the following:




            • For the method call lit_classic.display_info, it knows the type of the object instance as literature_type. It checks whether this method is defined in literature_type. It is, and so it executes that implementation of this method.




            • For the method call classic_book.display_info, it recognizes the object instance as of type mystery_type and thus executes the implementation of display_info that's specific to the mystery_type object type.










          Tip�

          If a method is defined in one of the supertypes and not defined in a subtype, but the subtype calls this method, PL/SQL still executes the implementation of this method that's "nearest" to the supertype implementation. For example, consider a method called display_basic_lit_info in literature_type that isn't defined in any of its subtypes. If the classic_book object calls the display_basic_lit_info method and then the display_info method, the implementation of the display_basic_lit_info method is the one found in literature_type, but the implementation of the display_info method is the one given in mystery_type. This holds true for supertype methods calling methods that are overridden in the subtypes.












          Day 8



          [ Team LiB ]






          Day 8


          1:

          What different types of relationships can you represent in a table?

          A1:

          You can have one-to-one, one-to-many, and many-to-many relationships represented in a table.

          2:

          Where are foreign keys defined?

          A2:

          Foreign keys are defined on the dependent table and rely on the data in the parent table. A foreign key references a primary key or a unique key in the same or another table. A foreign key assignment indicates that referential integrity is to be maintained according to the specified referential constraints.

          3:

          Why should you normalize your tables?

          A3:

          You should normalize your table to avoid redundancies and inconsistencies in your data.

          4:

          Is it a good idea to use a phone number as a primary key? Why or why not?

          A4:

          Using a phone number as a primary key isn't a great idea, mainly because a phone number may not be unique (you may have several people sharing a phone, for example). Also, phone numbers change as people move or if the phone company needs to change the area code.

          5:

          What data types should be used for data such as photos or movies?

          A5:

          GRAPHIC and BLOB data types are meant for binary data such as photos and movies.

          6:

          What is the difference between data types CHARACTER and VARCHAR?

          A6:

          The VARCHAR and CHARACTER data types hold the same types of data, but VARCHAR is more efficient. Suppose that you create two 10-character columns, defining one column as VARCHAR and the other as CHARACTER. Ten bytes are reserved for the CHARACTER column regardless of the data inserted into the column. For the VARCHAR column, only the amount of space required to store the data is used for the column. CHARACTER columns are a fixed-length and can contain up to 254 bytes per column. VARCHAR columns are variable-length and can contain up to 4,000 bytes per column.







            [ Team LiB ]



            Recipe 8.2. Reading Cookie Values










            Recipe 8.2. Reading Cookie Values



            8.2.1. Problem


            You want to read
            the value of a cookie that you've previously set.




            8.2.2. Solution


            Look in the $_COOKIE
            auto-global array, as shown in Example 8-5.


            Reading a cookie value



            <?php
            if (isset($_COOKIE['flavor'])) {
            print "You ate a {$_COOKIE['flavor']} cookie.";
            }
            ?>






            8.2.3. Discussion


            A cookie's value isn't available in $_COOKIE during the request in which the cookie is set. In other words, the
            setcookie( )
            function doesn't alter the value of $_COOKIE. On subsequent requests, however, each cookie sent back to the server is stored in $_COOKIE. If register_globals is on, cookie values are also assigned to global variables.


            When a browser sends a cookie back to the server, it sends only the value. You can't access the cookie's domain, path, expiration time, or secure status through $_COOKIE because the browser doesn't send that to the server.


            To print the names and values of all cookies sent in a particular request, loop through the $_COOKIE array, as in Example 8-6.


            Reading all cookie values



            <?php
            foreach ($_COOKIE as $cookie_name => $cookie_value) {
            print "$cookie_name = $cookie_value <br/>";
            }
            ?>






            8.2.4. See Also


            Recipe 8.1 shows how to set cookies; Recipe 8.3 shows how to delete cookies; Recipe 8.12 explains output buffering; Recipe 9.15 for information on register_globals.













            Recipe 15.5. Throwing SOAP Faults










            Recipe 15.5. Throwing SOAP Faults



            15.5.1. Problem


            You want
            to generate a SOAP fault, which is the mechanism SOAP uses to indicate errors.




            15.5.2. Solution


            Call the
            SOAPServer::fault( )
            method:


            <?php
            class pc_SOAP_return_time {
            public function return_time() {
            $date = date('Ymd\THis');
            if ($date === false) {
            $GLOBALS['server']->fault(1, 'Bad dates.');
            }
            return $date;
            }
            }

            $server = new SOAPServer(null,array('uri'=>'urn:pc_SOAP_return_time'));
            $server->setClass('pc_SOAP_return_time');

            ?>



            Or throw a SOAPFault:


            <?php
            class pc_SOAP_return_time {
            public function return_time() {
            $date = date('Ymd\THis');
            if ($date === false) {
            throw new SOAPFault(1, 'Bad dates.');
            }
            return $date;
            }
            }

            $server = new SOAPServer(null,array('uri'=>'urn:pc_SOAP_return_time'));
            $server->setClass('pc_SOAP_return_time');

            ?>



            You can also return a
            SOAPFault instead of throwing it.




            15.5.3. Discussion


            The SOAP specification has a standard way of indicating errors: SOAP faults. SOAP faults are very similar to the OO concept of exceptions. In fact,
            ext/soap allows you to treat SOAP faults, from both a SOAP server and SOAP client perspective, in a very similar manner to how PHP handles exceptions.


            While you can indicate SOAP faults in a number of ways, the easiest is to tHRow an instance of the SOAPFault class, passing an error code and an error string to the constructor, as shown in Example 15-8.


            Throwing a SOAP fault



            <?php
            class pc_SOAP_return_time {
            public function return_time() {
            $date = date('Ymd\THis');
            if ($date === false) {
            throw new SOAPFault(1, 'Bad dates.');
            }
            return $date;
            }
            }

            $server = new SOAPServer(null, array('uri'=>'urn:pc_SOAP_return_time'));
            $server->setClass('pc_SOAP_return_time');

            $server->handle();
            }
            ?>




            In Example 15-8, you throw a SOAPFault when
            date( ) returns false. The error code is 1, and in a moment of Indiana Jonesinspired whimsy, the error message is Bad dates..


            These two values are mapped to the SOAP 1.1 specification's faultcode and faultstring elements, respectively. At the time of this writing, there is not support for SOAP 1.2style SOAP faults.


            Normally, the error code is used to allow a program to process the error, while the error message is used to let a human understand what occurred'usually through a logfile or by printing it out.


            Unlike HTTP and status codes, there is no convention for SOAP error codes. For example, the 500 block is not reserved for server errors. You have the freedom to make up whatever set of codes you want.


            However, the SOAP extension will automatically set the HTTP status code to 500 when you issue a SOAP fault. This is required by the SOAP specification. You cannot use an HTTP status code other than 500.


            Besides throwing a SOAPFault, you can also return one from your method, or invoke the SOAPServer::fault( ) method. These all generate the same SOAP fault data, so it's a matter of personal preference or coding situation.


            Instead of using SOAPFault directly, you can also subclass it and use that class instead. This allows you to implement an integrated logging system, for example:


            <?php
            class pc_My_SOAPFault extends SOAPFault {
            public function __construct($code, $string) {
            parent::__construct($code, $string);
            error_log($this);
            }
            }
            ?>



            SOAP faults are automatically generated when you do something that generates an error, such as calling an undefined function.




            15.5.4. See Also


            Recipe 14.10 for catching SOAP faults in a SOAP client.













            Program 91: Stacked Wrong













            Program 91: Stacked Wrong

            In the following program we define an unsafe class, stack, and a safer version of it, safe_stack. Our test program creates an array of five stacks and pushes on some test data. It prints the size of the stack. But the results are not what we expect.




            1 /************************************************
            2 * stack_test -- Test the use of the classes *
            3 * stack and safe_stack. *
            4 ************************************************/
            5 #include <iostream>
            6
            7 // The largest stack we can use
            8 // (private to class stack and safe_stack)
            9 const int STACK_MAX = 100;
            10 /************************************************
            11 * stack -- Class to provide a classic stack. *
            12 * *
            13 * Member functions: *
            14 * push -- Push data on to the stack. *
            15 * pop -- Return the top item from the *
            16 * stack. *
            17 * *
            18 * Warning: There are no checks to make sure *
            19 * that stack limits are not exceeded. *
            20 ************************************************/
            21 class stack {
            22 protected:
            23 int count; // Number of items in the stack
            24 int *data; // The stack data
            25 public:
            26 // Initialize the stack
            27 stack(void): count(0)
            28 {
            29 data = new int[STACK_MAX];
            30 }
            31 // Destructor
            32 virtual ~stack(void) {
            33 delete data;
            34 data = NULL;
            35 }
            36 private:
            37 // No copy constructor
            38 stack(const stack &);
            39
            40 // No assignment operator
            41 stack & operator = (const stack &);
            42 public:
            43 // Push an item on the stack
            44 void push(
            45 const int item // Item to push
            46 ) {
            47 data[count] = item;
            48 ++count;
            49 }
            50 // Remove the an item from the stack
            51 int pop(void) {
            52 --count;
            53 return (data[count]);
            54 }
            55
            56 // Function to count things in
            57 // an array of stacks
            58 friend void stack_counter(
            59 stack stack_array[],
            60 const int n_stacks
            61 );
            62 };
            63
            64 /***********************************************
            65 * safe_stack -- Like stack, but checks for *
            66 * errors. *
            67 * *
            68 * Member functions: push and pop *
            69 * (just like stack) *
            70 ***********************************************/
            71 class safe_stack : public stack {
            72 public:
            73 const int max; // Limit of the stack
            74 public:
            75 safe_stack(void): max(STACK_MAX) {};
            76 // Destructor defaults
            77 private:
            78 // No copy constructor
            79 safe_stack(const safe_stack &);
            80
            81 // No assignment operator
            82 safe_stack & operator =
            83 (const safe_stack &);
            84 public:
            85 // Push an item on the stack
            86 void push(
            87 // Data to push on the stack
            88 const int data
            89 ) {
            90 if (count >= (STACK_MAX-1)) {
            91 std::cout << "Stack push error\n";
            92 exit (8);
            93 }
            94 stack::push(data);
            95 }
            96 // Pop an item off the stack
            97 int pop(void) {
            98 if (count <= o) {
            99 std::cout << "Stack pop error\n";
            100 exit (8);
            101 }
            102 return (stack::pop());
            103 }
            104 };
            105
            106
            107 /************************************************
            108 * stack_counter -- Display the count of the *
            109 * number of items in an array of stacks. *
            110 ************************************************/
            111 void stack_counter(
            112 // Array of stacks to check
            113 stack *stack_array,
            114
            115 // Number of stacks to check
            116 const int n_stacks
            117 )
            118 {
            119 int i;
            120
            121 for (i = 0; i < n_stacks; ++i)
            122 {
            123 std::cout << "Stack " << i << " has " <<
            124 stack_array[i].count << " elements\n";
            125 }
            126 }
            127
            128 // A set of very safe stacks for testing
            129 static safe_stack stack_array[5];
            130
            131 int main()
            132 {
            133
            134 stack_array[0].push(0);
            135
            136 stack_array[1].push(0);
            137 stack_array[1].push(1);
            138
            139 stack_array[2].push(0);
            140 stack_array[2].push(1);
            141 stack_array[2].push(2);
            142
            143 stack_array[3].push(0);
            144 stack_array[3].push(1);
            145 stack_array[3].push(2);
            146 stack_array[3].push(3);
            147
            148 stack_array[4].push(0);
            149 stack_array[4].push(1);
            150 stack_array[4].push(2);
            151 stack_array[4].push(3);
            152 stack_array[4].push(4);
            153
            154 stack_counter(stack_array, 5);
            155 return (0);
            156 }


            (Next Hint 296. Answer 72.)




















            Tablespace Container Management



            [ Team LiB ]





            Tablespace Container Management


            Although we as DBAs attempt to obtain accurate tablespace sizing information as part of the physical design process, oftentimes the data is not available and we have to take an educated guess. Sometimes our educated guess is incorrect or we may have been given erroneous data, or the data is just growing a lot faster than anticipated. In these cases we need the ability to add containers, resize, or drop containers to support the changing data requirements. For SMS Managed Space, the only change that can be made is through a redirected restore. During a redirected restore, additional directory containers can be added or removed.


            For DMS Managed Space, we have more options and flexibility with which to deal with space problems.


            NOTE



            DB2 v8 offers the ability to add DMS container(s) so that a rebalance does not occur. Using the command BEGIN NEW STRIPE SET we can add a new container above the high water mark so that a rebalance does not occur.






              [ Team LiB ]



              Chapter 10. Partitioning











               < Day Day Up > 









              Chapter 10. Partitioning







              Over the past 15 years,



              hard disk capacities have evolved

              from around 10 MB to over 100 GB, and capacities are still growing.

              Disk arrays are fast approaching the 100 terabyte range. No matter

              how much storage is available, however, there is always a way to

              exhaust it. As databases grow in size, day-to-day operations become

              more and more challenging. For example, finding the time and

              resources to rebuild an index containing 100 million entries can

              prove quite demanding. Prior to Oracle8, database administrators

              would meet this challenge by manually breaking a large table into

              several smaller tables. Although the pieces could be hidden behind a

              special type of view (called a partition view)

              during a query, all DML statements had to be performed against the

              individual tables, thereby exposing the partitioning scheme to the

              database developers and users.





              Starting with Version 8.0, Oracle provided a means for breaking a

              table into multiple pieces while preserving the look and feel of a

              single table. Each piece is called a partition,

              and, although every partition must share the same columns,

              constraints, indexes, and triggers, each partition can have its own

              unique storage parameters. While administrators generally deal with

              individual partitions when allocating storage and performing backups,

              developers may choose to deal with either the entire table or with

              individual partitions.



















                 < Day Day Up > 



                7.2 Project Management Process Areas



                [ Team LiB ]





                7.2 Project Management Process Areas


                The Project Management process areas cover the activities related to planning, monitoring, and controlling the project. The CMMI-SE/SW model includes six project management process areas:[3]

                [3] The ordering of these process areas in the continuous representation of the CMMI-SE/SW model is PP, PMC, SAM, IPM, RSKM, and QPM. In the CMMI-SE/SW/IPPD version the order is PP, PMC, SAM, IPM, RSKM, IT, and QPM. In the CMMI-SE/SW/IPPD/SS version the order is PP, PMC, SAM, IPM, RSKM, IT, ISM, and QPM. The order here is different to facilitate our explanation of relationships among the process areas.


                • Project Planning (PP)

                • Project Monitoring and Control (PMC)

                • Integrated Project Management (IPM)

                • Quantitative Project Management (QPM)

                • Supplier Agreement Management (SAM)

                • Risk Management (RSKM)


                The SE/SW/IPPD model includes one additional process area under Project Management and an expanded version of the Integrated Project Management process area:


                • Integrated Project Management for IPPD (IPM)

                • Integrated Teaming (IT)


                The SE/SW/IPPD/SS model includes one additional process area under Project Management:


                • Integrated Supplier Management (ISM)


                This section describes the Project Management process areas in the CMMI-SE/SW model. Section 7.5 covers the process area in the IPPD model extension and Section 7.6 covers the process areas in the Supplier Sourcing model extension.


                As shown in Figure 7-7, a close relationship exists between four of these process areas. IPM and QPM build on the capabilities of PP and PMC. This relationship is defined in the staged representation with PP and PMC at ML 2, IPM at ML 3, and QPM at ML 4. Likewise, Integrated Supplier Management (ISM) at ML 3 builds on Supplier Agreement Management at ML 2. When using the continuous representation for process improvement, you should understand this relationship and plan your improvement projects accordingly.


                Figure 7-7. Project Management process area relationships


                7.2.1 Project Planning


                The purpose of Project Planning is to establish and maintain plans that define project activities. PP (see Figure 7-8) has three specific goals: to establish estimates, to develop a project plan, and to obtain commitments. PP and PMC work together, in that the former involves the creation of the project plans, and the latter involves tracking progress against the plans, thereby ensuring that any corrective actions are managed to closure.


                Figure 7-8. Project Planning context diagram

                © 2002 by Carnegie Mellon University.


                In the first goal�establishing estimates for the project�the scope of the project is estimated based on a work breakdown structure, and project attributes for work products and tasks are estimated. To set the scope of the planning effort, a project life cycle is defined. Estimates of effort and cost can then be developed. These estimates are used as the basis for developing the project plans in the second goal, developing a project plan: Budgets and schedules are established, risks are identified, and plans are created for data management, resources, knowledge and skills needed, and stakeholder involvement.


                For the third goal�obtaining commitment to the plan�the project reviews all of the plans that affect the project to understand project commitments, reconciles the project plan to reflect available and projected resources, and obtains commitments from relevant stakeholders responsible for performing and supporting plan execution.


                7.2.2 Project Monitoring and Control


                The purpose of Project Monitoring and Control is to provide an understanding of the project's progress so that appropriate corrective actions can be taken when the project's performance deviates significantly from the plan. PMC (see Figure 7-9) has two specific goals: one on monitoring actual performance, and another on managing corrective actions.


                Figure 7-9. Project Monitoring and Control context diagram

                © 2002 by Carnegie Mellon University.


                The first goal�monitor the project against the plan�has five practices that identify what should be monitored and two practices that deal with reviews. The monitoring focuses on the following:


                • Project planning parameters

                • Commitments

                • Project risks

                • Data management

                • Stakeholder involvement


                These monitoring efforts are reviewed at both progress reviews and milestone reviews. Whenever these practices identify needed corrective actions, the second goal�managing corrective actions�provides specific practices to analyze the issues, take the necessary action, and manage the corrective action to closure. Note that other CMMI process areas (such as Verification, Supplier Agreement Management, and Configuration Management) refer to this PMC goal and its practices to obtain information about managing corrective actions.


                7.2.3 Integrated Project Management


                The purpose of Integrated Project Management is to establish and manage the project and the involvement of the relevant stakeholders according to an integrated and defined process that is tailored from the organization's set of standard processes. IPM (see Figure 7-10) has two specific goals in the CMMI-SE/SW model. Adding IPPD provides two more specific goals. The two basic specific goals relate to using a defined process for the project and coordinating activities with relevant stakeholders. These goals build on the planning covered in PP, by making sure that the appropriate organizations and people are involved in managing the project. The organization's standard processes, which were developed in the Organizational Process Definition process area, are the basis for the project's defined process.


                Figure 7-10. Integrated Project Management (without IPPD) context diagram

                © 2002 by Carnegie Mellon University.


                The first IPM goal�using a defined process for the project�has five practices. Establishing the project's defined process is the first step, with the organization's standard processes serving as a starting point. Next, the organizational process assets from the organizational process asset library are used for planning the project activities, integrating all plans to describe the defined process, and managing using the integrated plans. Finally, the project contributes its work products to the organization's process assets for use by future projects and process-improvement activities.


                The second basic goal�coordination and collaboration with relevant stakeholders�has three practices, which focus on managing the involvement of stakeholders to satisfy commitments and resolve misunderstandings, tracking critical project dependencies, and resolving outstanding issues.


                The addition of IPPD brings two more specific goals: using the project's shared vision and organizing integrated teams. The first goal (Figure 7-11), which is dubbed SG 3 in the IPPD version, defines a shared vision context that is used to establish a shared vision for the project and evaluates the use and effectiveness of that vision. The second goal, called SG 4 in the IPPD version, organizes integrated teams by determining team structure for a project, developing a plan for distributing requirements to the team, and establishing the teams.


                Figure 7-11. Integrated Project Management for IPPD context diagram

                © 2002 by Carnegie Mellon University.


                7.2.4 Quantitative Project Management


                The purpose of the Quantitative Project Management process area is to quantitatively manage the project's defined process to achieve the project's established quality and process-performance objectives. QPM (see Figure 7-12) has two specific goals that build on the goals of PP, PMC, and IPM: using performance objectives to quantitatively manage the project and statistically managing selected subprocesses. The first goal�using performance objectives to quantitatively manage the project�is achieved by specific practices that establish performance objectives, analyze and select candidate subprocesses, and monitor the project's performance objectives to determine whether they have been satisfied. The second goal�statistically managing selected subprocesses�is achieved by specific practices that select measures and analytical techniques, understand variation, monitor the selected subprocesses, and record the resulting data in a measurement repository for the organization. In this way, QPM builds on PMC by ensuring that the organization uses statistical management practices as well as historical data to determine objectives and select the subprocesses that will be quantitatively managed.


                Figure 7-12. Quantitative Project Management context diagram

                © 2002 by Carnegie Mellon University.


                7.2.5 Supplier Agreement Management


                The purpose of Supplier Agreement Management is to manage the acquisition of products from suppliers for which there exists a formal agreement. SAM (see Figure 7-13) has two specific goals: one for establishing supplier agreements and another for satisfying them. This process area works in cooperation with the Technical Solution process area, in which the organization decides whether to make or buy products. Once a decision to buy is made, SAM creates the agreement and then manages it from the purchaser's viewpoint. Product-component requirements are developed in the Requirements Development process area.


                Figure 7-13. Supplier Agreement Management context diagram

                © 2002 by Carnegie Mellon University.


                In the first goal�establishing supplier agreements�the project analyzes the acquisition options to see how well they meet the needs and requirements. Suppliers are then identified and selected, and an agreement is established. In the second goal�satisfying supplier agreements�the project reviews commercial off-the-shelf (COTS) products, performs the activities mandated in the supplier agreements, ensures that the supplier agreement is satisfied before accepting the acquired products, and transitions the acquired products to the project for the integration effort.


                7.2.6 Risk Management


                The purpose of Risk Management is to identify potential problems before they occur, so that risk-handling activities may be planned and invoked as needed across the life of the product or project to mitigate adverse impacts on achieving objectives. RSKM (see Figure 7-14) actually builds on part of the PP process area, as a specific practice in PP identifies and analyzes project risks, and the project plan should document those risks. However, PP is less systematic and less proactive than the requirements noted in RSKM. Furthermore, RSKM could be applied outside of the project context to manage organizational risks (if desired). Several other process areas reference RSKM.


                Figure 7-14. Risk Management context diagram

                © 2002 by Carnegie Mellon University.


                RSKM has three specific goals that involve preparation for risk management, identification and analysis of the risks, and handling and mitigation of risks as appropriate. The first goal�prepare for risk management�includes determining risk sources and the categories used for organizing risks by "bins," establishing the parameters used to analyze and categorize risks, and developing a risk strategy. The second goal�identification and analysis�focuses on determining the relative priority of the risks based on the analysis parameters. The third goal�handling and mitigation of the risks�encompasses developing and implementing risk mitigation plans.





                  [ Team LiB ]



                  Section 4.11. What's an Absolute Path?










                  4.11. What's an Absolute Path?


                  The last time we talked about paths we were writing HTML to make links with the <a> element. The path we're going to look at now is the absolute path
                  part of a URL, the last part that comes after the protocol (http) and the Web site name (www.starbuzzcoffee.com).


                  An absolute path tells the server how to get from your root folder to a particular page or file. Take Earl's Autos
                  site, for example. Say you want to look in Earl's inventory to see if your new Mini Cooper has come in. To do that, you'll need to figure out the absolute path to the file "inventory.html" that is in the "new" folder. All you have to do is trace through the folders, starting at the root, to get to the "new" folder where his "inventory.html" file is located. The path is made up of all the folders you go through to get there.


                  So, that looks like root (we represent root with a "/"), "cars", "new", and finally, the file itself, "inventory.html". Here's how you put that all together:



                  earls_autosEarl's Autos root folder.
                  "/"Always start at the root.
                  cars
                  /
                  carsAdd on each folder as you navigate to the file.
                  newIn between the folder names, put a "/" to keep them separate.
                  /
                  new
                  inventory.html
                  used
                  inventory.html
                  inventory.html
                  And then add on the filename.
                  /cars/new/inventory.html
                  Absolute path to "inventory.html".




                  4.11.1. there are no Dumb Questions


                  Q:

                  What is important about the absolute path?

                  A:

                  The absolute path is what a server needs to locate the file you are requesting. If the server didn't have an absolute path, it wouldn't know where to look.

                  Q:

                  I feel like I understood the pieces (protocols, servers, Web sites, and absolute paths), but I'm having trouble connecting them.

                  A:

                  If you add all those things together you have a URL, and with a URL you can ask a browser to retrieve a page (or other kinds of resources) from the Web. How? The protocol part tells the browser the method it should use to retrieve the resource (in most cases, this is HTTP). The Web site part (which consists of the server name and the domain name) tells the browser which computer on the Internet to get the resource from. And the absolute path tells the server what page you're after.

                  Q:

                  We learned to put relative paths in the href attribute of our <a> elements. How can the server find those links if they aren't absolute?

                  A:

                  Wow, great question. When you click on a link that is relative, behind the scenes the browser creates an absolute path out of that relative path and the path of the page that you click on. So, all the Web server ever sees are absolute paths, thanks to your browser.

                  Q:

                  Would it help the browser if I put absolute paths in my HTML?

                  A:

                  Ah, another good question, but hold that thought, we'll get back to that in a sec.



                  Sharpen your pencil


                  You've waited long enough. It's time to give your new URL a spin. Before you do, fill in the blanks below and then type in the URL (like you haven't already). If you're having any problems, this is the time to work with your hosting company to get things sorted out. If you haven't set up an hosting company, fill in the blanks for www.starbuzzcoffee.com, and type the URL into your browser anyway.


                  protocol Web site name absolute path




                  I'd like my visitors to be able to type "http://www.starbuzzcoffee.com" and not have to type the "index.html". Is there a way to do that?


                  Yes, there is. One thing we haven't talked about is what happens if a browser asks for a directory rather than a file from a Web server. For instance, a browser might ask for:



                  Remember, when we're talking about Web servers or FTP, we usually use the term "directory"
                  instead of "folder." But they're really the same thing.

                  http://www.starbuzzcoffee.com/images/
                  The images
                  directory in the root directory.

                  or
                  http://www.starbuzzcoffee.com/The root directory itself.
                  But, you need to find out what your hosting company wants you to name your default file,
                  because it depends on the type of server they use.




                  When a Web server receives a request like this, it tries to locate a default file in that directory. Typically a default file is called "index.html" or "default.htm" and if the server finds one of these files, it returns the file to the browser to display.


                  So, to return a file by default from your root directory (or any other directory), just name the file "index.html" or "default.htm".


                  But I asked about "http://www.starbuzzcoffee.com", which looks a little different. It doesn't have the ending "/".


                  Oops, you sure did. When a server receives a request like yours without the trailing "/" and there is a directory with that name, then the server will add a trailing slash for you. So if the server gets a request for:



                  http://www.starbuzzcoffee.com/
                  it will change it to:
                  http://www.starbuzzcoffee.com
                  which will cause the server to look for a default file, and in
                  the end it will return the file as if you'd originally typed:

                  http://www.starbuzzcoffee.com/index.html














                  Introductory Notes



                  [ Team LiB ]









                  Introductory Notes


                  Risk management is a continuous, forward-looking process that is an important part of the business and technical management processes. Risk management should address issues that could endanger achievement of critical objectives. A continuous risk management approach is applied to effectively anticipate and mitigate the risks that may have a critical impact on the project.


                  Effective risk management includes early and aggressive risk identification through the collaboration and involvement of relevant stakeholders, as described in the stakeholder involvement plan addressed in the Project Planning process area. Strong leadership across all relevant stakeholders is needed to establish an environment for the free and open disclosure and discussion of risk.


                  While technical issues are a primary concern both early on and throughout all project phases, risk management must consider both internal and external sources for cost, schedule, and technical risk. Early and aggressive detection of risk is important because it is typically easier, less costly, and less disruptive to make changes and correct work efforts during the earlier, rather than the later, phases of the project.


                  Risk management can be divided into three parts: defining a risk management strategy; identifying and analyzing risks; and handling identified risks, including the implementation of risk mitigation plans when needed.


                  As represented in the Project Planning and Project Monitoring and Control process areas, organizations may initially focus simply on risk identification for awareness, and react to the realization of these risks as they occur. The Risk Management process area describes an evolution of these specific practices to systematically plan, anticipate, and mitigate risks to proactively minimize their impact on the project.


                  Although the primary emphasis of the Risk Management process area is on the project, the concepts can also be applied to manage organizational risks.







                    [ Team LiB ]



                    Verifying Implementation



                    [ Team LiB ]









                    Verifying Implementation


                    GP 2.9 Objectively Evaluate Adherence


                    Objectively evaluate adherence of the process and product quality assurance process against its process description, standards, and procedures, and address noncompliance.


                    Elaboration


                    Examples of activities reviewed include the following:



                    • Objectively evaluating processes and work products


                    • Tracking and communicating noncompliance issues





                    Examples of work products reviewed include the following:



                    • Noncompliance reports


                    • Evaluation logs and reports






                    GP 2.10 Review Status with Higher Level Management


                    Review the activities, status, and results of the process and product quality assurance process with higher level management and resolve issues.



                    AUTHORS' NOTE:
                    GG3 and its practices do not apply for a maturity level 2 rating, but do apply for a maturity level 3 rating and above.




                    GG 3 Institutionalize a Defined Process


                    The process is institutionalized as a defined process.








                      [ Team LiB ]



                      SOME REALLY BAD REASONS ORGANIZATIONS ACQUIRE PROCESS EXPERTISE OR TOOLS













                      SOME REALLY BAD REASONS ORGANIZATIONS ACQUIRE PROCESS EXPERTISE OR TOOLS

                      Consultancy is very big business. Natural SPI’s clients have spent anywhere from 5 to 20 percent of their entire budget allocated to CMMI-based process improvement and I’m sure they got every penny’s worth! Chances are pretty good that someone in your organization will also have the idea to buy some outside expertise or tool to help with the CMMI effort. There are some really good and really bad reasons for outsourcing some aspects of the organization’s process improvement work; let’s start with the bad reasons.




                      Bad Process Acquisition Reason 1: They Had a Cool Booth at the SEPGSM Conference


                      Well, okay, so they had a cool booth and they gave away some cool prizes or they engineered a very impressive product demo. Their full-color brochure is slick, their Web site incorporates all the latest Web technology, and they wear nice suits. Maybe everyone recognizes the company name or logo. And all of that has what to do with CMMI-based process improvement?


                      I remember attending a presentation at SEPG 2003 delivered by a vice president from one of the biggest names in management consulting. They were one of the conference anchors and had provided a keynote speaker. In the presentation, she boasted about how people in her organization worked nights and weekends to achieve their CMMI Level 3 target. Now wait a minute, let me get this straight, an accolade about process improvement being achieved through the heroics of individuals? Does anyone other than me see something wrong there?


                      If you choose a consulting firm or a tool vendor, just make sure your decision is based on actual performance data or experiential information, not solely on name or reputation.





                      Bad Process Acquisition Reason 2: They Guarantee Your Organization Will Be Certified at CMM/CMMI Level in X Months


                      There are lots of problems here. Let’s start with the simple, provable fact that there’s no such thing as maturity level certification. (Read Chapter 8 — Process Improvement Myths and Methodologies.) If someone is promising that, how well do they really know this business? Let’s go a little deeper. Even if the consulting services or tool could ensure your organization achieves a CMM or CMMI maturity level within a certain time frame, is that the same as a guarantee that your organization will actually improve its overall systems engineering and delivery performance? You don’t have to choose between getting a maturity level and achieving measurable improvement, but you do need to realize that the two are not always the same thing. Read the fine print or the lack thereof.





                      Bad Process Acquisition Reason 3: They’re Great Golfing Partners


                      Or bowling buddies, or drinking pals, or whatever. There is a certain segment of the population for whom relationships are everything and facts such as actual performance don’t even figure into decisions. I once had a boss who would come to my cube and, with great exuberance, announce to me a new member to the group. The conversations went something like this:


                      BOSS: Hey, Michael, I just hired so-and-so to help out with your process improvement project!


                      ME: That’s great! What does he do?


                      BOSS: Oh, he’s a really great guy; you’ll like him.


                      ME: Okay, good. What kind of experience does he have?


                      BOSS: He’s really good … gets along with everybody.


                      ME: What are his skills?


                      BOSS: Okay, so teach him what you need him to do; he’ll be great.


                      ME: Sigh!


                      Deals, sometimes big deals such as consulting agreements or the purchase of a several hundred thousand dollar tool, will be made almost solely on the basis of a personal relationship. Sometimes, through pure dumb luck, such deals work out. Most of the time they don’t because they’re not based on the factual needs of the organization or on the vendor’s historically demonstrated ability to deliver.





                      Bad Process Acquisition Reason 4: They’re Cheap


                      Cost is always a factor in acquisition or procurement decisions; it should be. However, if cost is the only vendor or consultant selection criteria, then by the definition of goal and requirements traceability, the organization does not have any goals for quality, schedule, or approach.





                      Bad Process Acquisition Reason 5: They Used to Work at ___________


                      You fill in the blank: SEI, IBM, Hill Air Force Base, Loral, the Software Productivity Consortium, Space Shuttle software, etc. Yes, there are organizations in the world that have been centers for brilliance, excellence, and innovation in process improvement and CMM and CMMI implementation. But as the stories grow older, they grow bolder, and now the legends are larger than the current-day reality.


                      The lesson is that good consultants can come from anywhere. They don’t have to come from a place you recognize from the urban myths of process improvement to have good ideas and good experience which can help your organization. Just because a consultant or a tool vendor does come from a place of process legend doesn’t mean that your organization will get what it needs and wants. Make sure the people in your organization who are responsible for making decisions about process consulting or tools can distinguish between reputation and demonstrable performance.