Wednesday, October 21, 2009

11.2 General-Purpose Actions








 

 










11.2 General-Purpose Actions



JSTL provides a handful of general-purpose actions for manipulating scoped variables, beans and maps, and handling exceptions. Those actions are listed in Table 11.9.





















































Table 11.9. General-Purpose Actions


Action





Description





<c:out>





Evaluates an expression (either an EL expression for <c:out> or a JSP expression for <c_rt:out>) and sends the result of that evaluation to the current JspWriter.





<c:set>





Sets the value of a scoped variable, a property of a bean, or an entry in a Java map.





<c:remove>





Deletes a scoped variable.





<c:catch>





Catches any exceptions of type java.lang.Throwable thrown in the body of the action and optionally stores that exception in a page-scoped variable.





<c:out>



Evaluates an expression and sends the result of that expression to the current JspWriter.





Syntax:[1]



[1] Items in brackets are optional.



Syntax #1: Without a body





<c:out value [escapeXml] [default]/>



Syntax #2: With a body that specifies the default value





<c:out value [escapeXml]>

default

</c:out>



Description:



The <c:out> action evaluates an expression�either an EL expression (<c:out>) or a JSP expression (<c_rt:out>)�and sends the result of that evaluation, coerced to a string, to the current JspWriter.



Attributes:























































Attribute[a]





Type





Description





value





Object





The expression that is either an EL expression for <c:out> or a JSP expression for <c_rt:out>.





escapeXml





boolean





A value that specifies whether the following characters are converted to their corresponding character entity codes: < > & ' ". The default value is true.





default





Object





A default value that is used instead of the supplied expression if that expression is null or invalid.





[a] static | dynamic





Constraints and Error Handling:





  • If you specify an invalid value attribute such as null, <c:out> uses the default value instead.



  • If the expression specified by the value attribute is null or invalid and no default value is specified, <c:out> emits an empty string.





In a Nutshell:



The <c:out> action replaces the syntax for JSP expressions�<%= expr %>�and is JSTL's most heavily used action; it's used in nearly every code example throughout this book. You can use <c:out> for JSTL Expression Language (EL) expressions and <c_rt:out> for JSP expressions. You specify those expressions with the value attribute.



You can optionally specify a default value that <c:out> sends to the current JspWriter if the specified value is null or is not a valid expression. You can specify the default value with the default attribute or in the body of the <c:out> action.



The escapeXml attribute specifies whether certain characters are converted to HTML character entity codes. Those characters and their corresponding entity codes are listed in Table 11.10. By default, the escapeXml attribute is true, meaning <c:out> converts the characters listed in Table 11.10 to their corresponding character entity codes. If you specify false for the escapeXml attribute, <c:out> will not convert those characters.





























































Table 11.10. <c:out> Default Character Conversions


Character





Character Entity Code





<





&lt;





>





&gt;





&





&amp;





'





&#039





"





&#034





<c:set>



Stores a value in a scoped variable or a property of a target object





Syntax:[2]



[2] Items in brackets are optional.



Syntax #1: Without a body, sets the value of a scoped variable





<c:set value var [scope]/>



Syntax #2: With a body that specifies the value of a scoped variable





<c:set var [scope]>

value

</c:set>



Syntax #3: Without a body, sets the value of a bean property or a key/value pair in a map





<c:set value target property/>



Syntax #4: With a body that specifies the value of a bean property or the value of a key/value pair in a map





<c:set target property>

value

</c:set>



Description:



The <c:set> action lets you store a value in a scoped variable or a bean property. You can also use <c:set> to add, modify, or remove a key/value pair in a map.



Attributes:











































































Attribute[a]





Type





Description





value





Object





The expression that is either an EL expression for <c:out> or a JSP expression for <c_rt:out>. That value represents a bean property value or the value of a map entry.





target





Object





An object whose property, specified with the property attribute, is set to the value specified with the value attribute. That object must be either a bean or an instance of java.util.Map.





property





String





The name of a bean property or the name of a key for a map entry.





var





String





The name of a scoped variable that contains the value specified by the value attribute. That scoped variable's type is whatever type the value evaluates to.





scope





String





The scope of the scoped variable whose name is specified by the var attribute; default is page scope.





[a] static | dynamic





Constraints and Error Handling:





  • For syntaxes 1 and 2, if the value attribute evaluates to null, <c:set> removes the scoped variable identified by the var and scope attributes.



  • For syntaxes 3 and 4, if the value attribute evaluates to null and the target is a bean, <c:set> sets that bean's property to null.



  • For syntaxes 3 and 4, if the value attribute evaluates to null and the target is an instance of java.util.Map, <c:set> removes the entry whose key corresponds to the property attribute.



  • For syntaxes 3 and 4, <c:set> throws an exception if the value of the target attribute evaluates to null or if the value of the target attribute is not a bean or an instance of java.util.Map.





In a Nutshell:



For syntaxes 1 and 2, <c:set> sets the value of a scoped variable that you specify with the var attribute and, optionally, the scope attribute.



For syntaxes 3 and 4, <c:set> sets a property of a target object. If the target object is a bean, <c:set> sets that bean's property�which you specify with the property attribute�with the value that you specify with the value attribute.



If the target object is a Java map and that map has an entry whose key corresponds to the property attribute, <c:set> sets the value of that entry to the value you specify with the value attribute. If the map does not have an entry corresponding to the property attribute, <c:set> creates an entry, adds it to the map, and sets its value to the value that you specify with the value attribute.



<c:remove>



Removes a scoped variable





Syntax:[3]



[3] Items in brackets are optional.





<c:remove var [scope]/>



Description:



The <c:remove> action removes a scoped variable that you specify with the var attribute and, optionally, the scope attribute.



Attributes:













































Attribute[a]





Type





Description





var





String





The name of the scoped variable that <c:remove> removes.





scope





String





The scope of the scoped variable whose name is specified by the var attribute; default is page scope.





[a] static | dynamic



In a Nutshell:



If you don't specify the scope attribute, <c:remove> removes the scoped variable by calling PageContext.removeAttribute(var). That method searches the page, request, session, and application scopes�in that order�and removes the first scoped variable that it finds with the name that you specified with the var attribute. If you do specify the scope attribute, <c:remove> removes the scoped variable by calling PageContext.removeAttribute(var, scope), which removes the specified variable from the specified scope.



<c:catch>



Catches an exception and optionally stores it in a page-scoped variable





Syntax:[4]



[4] Items in brackets are optional.





<c:catch [var]>

body content

</c:catch>



Description:



The <c:catch> action catches the first exception thrown from its body content. If you specify the optional var attribute, <c:catch> stores the exception in a scoped variable with a name corresponding to the var attribute's value.



Attributes:



































Attribute[a]





Type





Description





var





String





The name of a page-scoped variable that references the exception thrown from the body of the <c:set> action.





[a] static | dynamic



In a Nutshell:



Most of the time, you will probably specify the var attribute for the <c:catch> action so that <c:catch> will store the exception that it catches in a scoped variable. If you don't specify that attribute, <c:catch> will catch the exception but it won't save it; essentially, that approach lets you ignore exceptions and is not recommended.














     

     


    Section 4.2. Operator Concepts










    4.2. Operator Concepts


    PHP has many types of operators. The categories
    are:


    • Arithmetic operators

    • Array operators

    • Assignment operators

    • Bitwise operators

    • Comparison operators

    • Execution operators

    • Incrementing/decrementing operators

    • Logical operators

    • String operators


    The operators are listed as found on http://www.zend.com/manual/language.operators.php. There are some operators we're not going to discuss in order for you to get up and running with PHP as quickly as possible. These include some of the casting operators that we'll just skim the surface of, for now. When working with operators, there are four aspects that are critical:


    • Number of operands

    • Type of operands

    • Order of precedence

    • Operator associativity


    The easiest place to start is by talking about the operands.



    4.2.1. Number of Operands






    Depending on which operator you are using, it may take different numbers of operands. Many operators are used to combine two expressions into a more complex single expression; these are called binary
    operators
    .
    Binary operators include addition, subtraction, multiplication, and division.


    Other operators take only one operand; these are called unary
    operators
    . Think of the negation operator (-) that multiplies a numeric value by -1. The auto-increment and -decrement operators described in Chapter 3 are also unary operators.


    A ternary
    operator
    takes three operands. The shorthand for an if statement, which we'll talk about later when discussing conditionals, takes three operands.




    4.2.2. Types of Operands




    You need to be mindful of the type of operand an operator is meant to work on, because certain operators expect their operands to be particular data types. PHP attempts to make your life as easy as possible by automatically converting operands to the data type that an operator is expecting. But there are times that an automatic conversion isn't possible.


    Mathematical operators are an example of where you need to be careful with your types. They take only numbers as operands. For example, when you try to multiply two strings, PHP can convert the strings to numbers. While "Becker" * "Furniture" is not a valid expression, it returns zero. Because the strings don't contain simple numbers, an expression that is converted without an error is "70" * "80". This outputs to 5600. Although 70 and 80 are strings, PHP is able to convert them to the number type required by the mathematical operator.


    There will be times when you want to explicitly set or convert a variable's type. There are two ways to do this in PHPfirst, by using settype to actually change the data type, or second, by casting, which temporarily converts the value. PHP uses casting to convert data types. When PHP does the casting for you automatically, it's called implicit casting.
    You can also specify data types explicitly, but it's not something that you'll likely need to do.



    PHP uses implicit casting to the type that the operator requires.




    The cast types allowed are:




    (int), (integer)


    Cast to integer




    (bool), (boolean)


    Cast to Boolean




    (float), (double), (real)


    Cast to float




    (string)


    Cast to string




    (array)


    Cast to array




    (object)


    Cast to object



    To use a cast, place it before the variable to cast, as in Example 4-2. The $test_string variable contains the string "1234".


    Example 4-2. Casting a variable




    $test=1234;
    $test_string=(string)$test;




    Keep in mind that it may not always be obvious what will happen when casting between certain types. You might run into problems if you don't watch yourself when manipulating variable types.


    Some binary operators such as the assignment
    operators

    have further restrictions on the lefthand operand. Because the assignment operator is assigning a value to the lefthand operator, it must be something that can take a value such as a variable. Example 4-3 demonstrates good and bad lefthand expressions.


    Example 4-3. Lefthand expressions




    3 = $locations; // bad - a value can not be assign to the literal 3
    $a + $b = $c; //bad - the expression on the left isn't one variable
    $c = $a + $b; //OK
    $stores = "Becker"." "."Furniture"; // OK





    There is a simpler way to remember this. The lefthand expression in assignment operations is known as an L-value. L-values in PHP are variables, elements of an array, and object properties. Don't worry about object properties.





    4.2.2.1. Order of precedence




    The order of precedence
    of an operator determines which operator processes first in an expression. For instance, the multiplication and division process before addition and subtraction. You can see a simplified table at http://www.zend.com/manual/language.operators.php#language.operators.precedence.


    If the operators have the same precedence, they are processed in the order they appear in the expression. For example, multiplication and division process in the order they appear in an expression, because they have the same precedence. Operators with the same precedence can occur in any order without affecting the result.


    Most expressions do not have more than one operator of the same precedence level, or the order in which they process doesn't change the result. As shown in Example 4-4, when adding and subtracting, it doesn't matter whether you add or subtract firstthe result is still 1.


    Example 4-4. Order of precedence




    2 + 4 - 5 == 1;
    4 - 5 + 2 == 1;

    4 * 5 / 2 == 10;
    5 / 2 * 4 == 10;

    2 + 4 - 5 == 1;
    4 - 5 + 2 == 1;

    4 * 5 / 2 == 10;
    5 / 2 * 4 == 10;




    When using expressions that contain operators of different precedence levels, the order can change the value of the expression. You can use parentheses, ( and ), to override the precedence levels or just to make the expression easier to read. Example 4-5 shows how to change the default precedence.


    Example 4-5. The multiplication is done last because of the override




    echo 2 * 3 + 4 + 1;
    11
    echo 2 * (3 + 4 + 1);
    16




    PHP has several levels of precedence, enough so that it's difficult to keep track of them without checking a reference. Table 4-2 is a list of operators in PHP sorted by order of precedence from highest to lowest. Operators with the same level number are all of the same precedence.



    The Association column lists operators that are right to left instead of left to right. We'll discuss associativity next.




    Table 4-2. List of PHP operators

    Operator

    Description

    Operands

    Association

    Level

    NEW

    Create new object

    Constructor call

    Right to left

    1

    .

    Property access (dot notation)

    Objects

     

    2

    [ ]

    Array index

    Array, integer, or string

     

    2

    ()

    Function call

    Function or argument

     

    2

    !

    Logical NOT

    Unary

    Right to left

    3

    ~

    Bitwise NOT

    Unary

    Right to left

    3

    ++, --

    Increment and decrement operators

    1value

    Right to left

    3

    +, -

    Unary plus, negation

    Number

    Right to left

    3

    (int)

    Cast operators

    Unary

    Right to left

    3

    (double)

    Cast operators

    Unary

    Right to left

    3

    (string)

    Cast operators

    Unary

    Right to left

    3

    (array)

    Cast operators

    Unary

    Right to left

    3

    (object)

    Cast operators

    Unary

    Right to left

    3

    @

    Inhibit errors

    Unary

    Right to left

    3

    *, /, %

    Multiplication, division

    Numbers

     

    4

    +, -

    Addition, subtraction

    Numbers

     

    5

    .

    Concatenation

    Strings

     

    5

    <<, >>

    Bitwise shift left, bitwise shift right

    Binary

     

    6

    <, <=, >, >=

    Comparison operators

    Numbers, strings

     

    7

    ==, !=

    Equality, inequality

    Any

     

    8

    ===, !==

    Identity, non-identity

    Any

     

    8

    &

    Bitwise AND

    Binary

     

    9

    ^

    Bitwise NOR

    Binary

     

    10

    |

    Bitwise OR

    Binary

     

    11

    &&

    Logical AND

    Boolean

     

    12

    ||

    Logical OR

    Boolean

     

    13

    ? :

    Conditional

    Boolean

    Right to left

    14

    =

    Assignment

    1value=any

    Right to left

    15

    AND

    Logical AND

    Boolean

     

    16

    OR

    Logical OR

    Boolean

     

    17

    XOR

    Logical XOR

    Boolean

     

    18





    4.2.2.2. Associativity





    All operators process their operators in a certain direction. This direction is called associativity,
    and it depends on the type of operator. Most operators are processed from left to right, which is called left associativity. For example, in the expression 3 + 5 - 2, 3 and 5 are added together, and then 2 is subtracted from the addition, resulting in 8. Left associativity means that the expression is evaluated from left to right. Right associativity means the opposite.


    Since it has right associativity, the assignment operator is one of the exceptions, since it has right associativity. The expression $a=$b=$c processes by $b being assigned the value of $c, and then $a being assigned the value of $b. This assigns the same value to all of the variables. If the assignment operator is right associative, the variables might not have the same value.


    If you're thinking that this is incredibly complicated, don't worry. These rules are only enforced if you fail to be explicit about your instructions. Keep in mind that you should always use brackets in your expressions to make your actual meaning very clear. This helps both PHP and also other people who may need to read your code.





    4.2.3. Relational Operators


    In Chapter 3, we discussed assignment and math operators. Relational operators provide the ability to compare two operands and return either trUE or FALSE regarding the comparison. An expression that returns only TRUE or FALSE is called a Boolean expression, which we discussed earlier in this chapter. These comparisons include tests for equality
    and less than or greater than. These comparison operators allow you to tell PHP when to do something based on a comparison being true so decisions can be made in your code.



    4.2.3.1. Equality

    The equality operator,
    a double equals sign (==), is used frequently. Using the single = in its place is a common logical error in programs, since it assigns values rather than tests equality.


    If the two operands are equal, TRUE is returned; otherwise, FALSE is returned. If you're echoing your results, TRUE is printed as 1 in your browser. FALSE is 0, which won't display in your browser.


    It's a simple construct but it also allows you to test for conditions. If the operands are of different types, PHP attempts to convert them before comparing.


    For example, '1' == 1 is true. Also, $a == 1 is true if the variable $a is assigned to 1.


    If you don't want the equals operator to automatically convert types, you can use the identity operator, a triple equals sign ===, which checks that the values and types are the same. For example, '1' === 1 is false because they're different types, since a string doesn't equal an integer.


    Sometimes you might want to check to see whether two things are different. The inequality operator, an exclamation mark before the equals sign (!=), checks for the opposite of equality, which means not equal to.



    '1' != 'A' // true
    '1' != '1' // false





    4.2.3.2. Comparison operators




    You may need to check for more than just equality. Comparison operators test the relationship between two values. You may be familiar with these from high school math. They include less than (<), less than or equal to (<=), greater than (>), and greater than or equal to (>=).


    For example, 3<4 is TRUE, while 3<3 is FALSE but 3<=3 is TRUE.


    Comparison operators are often used to check for something happening up until a set point. For example, a web store might offer free shipping if you purchase five or more items. So the code must compare the number of items to the number five before changing the shipping cost.




    4.2.3.3. Logical operators

    Logical operators work with the Boolean results of relational operators to build more complex logical
    expressions; there are four logical operators
    shown in Table 4-3.


    Table 4-3. Logical operators

    Logical operator

    Meaning

    AND

    TRUE if both operands must be TRUE

    OR

    TRUE if at least one operand is trUE

    XOR

    trUE if only one operand is trUE

    NOT

    TRUE if FALSE, FALSE if trUE



    To test whether both operands are true, use the AND operator, also represented as double ampersands (&&). trUE is returned only if both operands are trUE; otherwise, FALSE is returned. See Table 4-3 for more information.


    To test whether one operand is trUE, use the OR operator, which is also represented as double vertical bars (||). trUE is returned only if either or both operands are trUE.



    Using the OR operator can create tricky program logic problems. If PHP finds that the first operand is TRUE, it won't evaluate the second operand. While this saves execution time, you need to be careful that the second operator doesn't contain code that needs to be executed for your program to work properly.




    To test whether either operand is trUE but not both, use XOR. XOR returns trUE if one and only one operand is TRUE.


    To negate a Boolean value, use the NOT operator represented as an exclamation point (!). It returns trUE if the operand has a value of FALSE. It returns FALSE if the operand is trUE.



    If you accidentally use & instead of && or | instead of ||, you'll end up getting the wrong operator. They compare binary data bit by bit. PHP converts your operands into binary data and applies the binary operators.




    Because they have different precedence levels, AND and OR have two representations. Table 4-4 displays logical statements and their results.


    Table 4-4. Logical statements and their results

    Example logical statement

    Result

    TRUE AND TRUE

    TRUE

    FALSE AND TRUE

    FALSE

    TRUE OR FALSE

    TRUE

    FALSE OR FALSE

    FALSE

    TRUE XOR TRUE

    FALSE

    !TRUE

    FALSE















    Section 7.4.&nbsp; Boot-Time Initialization Routines










    7.4. Boot-Time Initialization Routines


    Most initialization routines have two interesting properties:


    • They need to be executed at boot time, when all the kernel components get initialized.

    • They are not needed once they are executed.


    The next section, "xxx_initcall Macros," describes the mechanism used to run initialization routines at boot time, taking into consideration these properties as well as priorities among modules. The later section "Memory Optimizations" shows how routines and data structures that are no longer needed can be freed at link time or runtime by using smart tagging.



    7.4.1. xxx_initcall Macros







    The early phase of the kernel boot consists of two main blocks of initializations:


    • The initialization of various critical and mandatory subsystems that need to be done in a specific order. For instance, the kernel cannot initialize a PCI device driver before the PCI layer has been initialized. See the later section "Example of dependency between initialization routines" for another example.

    • The initialization of other kernel components that do not need a strict order: routines in the same priority level can be run in any order.


    The first part is taken care of by the code that comes before do_initcalls in Figure 5-1 in Chapter 5. The second part is taken care of by the invocation of do_initcalls shown close to the end of do_basic_setup in the same figure. The initialization routines of this second part are classified based on their role and priority. The kernel executes those initialization routines one by one, starting from the ones placed in the highest-priority class (core_initcall). The addresses of those routines, which are needed to invoke them, are placed in the .initcallN.init memory sections of Figure 7-3 by tagging them with one of the xxx_initcall macros in Table 7-1.


    The area used to store the addresses of the routines tagged with the xxx_initcall macros is delimited by a starting address (_ _initcall_start) and an ending address (_ _initcall_end). In the excerpt of the do_initcalls function that follows, you can see that it simply takes the function addresses one by one from that area and executes the functions they point to:



    static void _ _init do_initcalls(void)
    {
    initcall_t *call;
    int count = preempt_count( );

    for (call = _ _initcall_start; call < _ _initcall_end; call++) {
    ... ... ...
    (*call)( );
    ... ... ...
    }
    flush_scheduled_work( );
    }



    The routines invoked by do_initcalls are not supposed to change the preemption status or disable IRQs. Because of that, after each routine execution, do_initcalls checks whether the routine has made any changes, and adjusts the preemption and IRQ status if necessary (not shown in the previous snapshot).


    It is possible for the xxx_initcall routines to schedule some work that takes place later. This means that the tasks handled by those routines may terminate asynchronously, at unknown times. The call to flush_scheduled_work is used to make do_initcalls wait for those asynchronous tasks to complete before returning.


    Note that do_initcalls itself is marked with _ _init: because it is used only once within do_basic_setup during the booting phase, the kernel can discard it once the latter is done.


    _ _exitcall is the counterpart of _ _initcall. It is not used much directly, but rather via other macros defined as aliases to it, such as module_exit, which we introduced in the section "Module Initialization Code."



    7.4.1.1. Example of _ _initcall and _ _exitcall routines: modules





    I said in the section "Module Initialization Code" that the module_init and module_exit macros, respectively, are used to tag routines to be executed when the module is initialized (either at boot time if built into the kernel or at runtime if loaded separately) and unloaded.


    This makes a module the perfect candidate for our _ _initcall and _ _exitcall macros: in light of what I just said, the following definition from include/linux/init.h of the macros module_init and module_exit should not come as a surprise:



    #ifndef MODULE
    ... ... ...
    #define module_init(x) _ _initcall(x);
    #define module_exit(x) _ _exitcall(x);

    #else
    ... ... ...
    #endif



    module_init is defined as an alias to _ _initcall for code statically linked to the kernel: its input function is classified as a boot-time initialization routine.


    module_exit follows the same scheme: when the code is built into the kernel, module_exit becomes a shutdown routine. At the moment, shutdown routines are not called when the system goes down, but the code is in place to allow it.[*]

    [*] User-Mode Linux is the only architecture that actually makes use of shutdown routines. It does not use _ _exitcall macros, but defines its own macro, _ _uml_exitcall. The home page of the User-Mode Linux project is http://user-mode-linux.sourceforge.net.




    7.4.1.2. Example of dependency between initialization routines

    net_dev_init was introduced in Chapter 5. Device drivers register with the kernel with their module_init routine, which, as described in the section "The Big Picture" in Chapter 6, registers its devices with the networking code. Both net_dev_init and the various module_init functions for built-in drivers are invoked at boot time by do_initcalls. Because of that, the kernel needs to make sure no device registrations take place before net_dev_init has been executed. This is enforced transparently thanks to the marking of device driver initialization routines with the macro device_initcall (or its alias, _ _initcall), while net_dev_init is marked with subsys_initcall. In Figure 7-3, you can see that subsys_initcall routines are executed earlier than device_initcall routines (the memory sections are sorted in priority order).




    7.4.1.3. Legacy code








    Before the introduction of the set of xxx_initcall macros, there was only one macro to mark initialization functions: _ _initcall. The use of only a single macro created a heavy limitation: no execution order could be enforced by simply marking routines with the macro. In many cases, this limitation is not acceptable due to intermodule dependencies, and other considerations. Therefore, the use of _ _initcall could not be extended to all the initialization functions.


    _ _initcall used to be employed mostly by device drivers. For backward compatibility with pieces of code not yet updated to the new model, it still exists and is simply defined as an alias to device_initcall.


    Another limitation, which is still present in the current model, is that no parameters can be provided to the initialization routines. However, this does not seem to be an important limitation.














    Section 24.119. Math.pow( ): compute xy










    24.119. Math.pow( ): compute xy


    ECMAScript v1



    24.119.1. Synopsis


    Math.pow(x, y)



    24.119.1.1. Arguments



    x


    The number to be raised to a power.




    y


    The power that x is to be raised to.





    24.119.1.2. Returns

    x to the power of y, xy





    24.119.2. Description


    Math.pow( ) computes x to the power of y. Any values of x and y may be passed to Math.pow( ). However, if the result is an imaginary or complex number, Math.pow( ) returns NaN. In practice, this means that if x is negative, y should be a positive or negative integer. Also, bear in mind that large exponents can easily cause floating-point overflow and return a value of Infinity.













    New variables in the Samba configuration file











     < Day Day Up > 











    New variables in the Samba configuration file


    As with the current version of Samba, the behavior of Samba 3.0 and Linux depends on the configuration as defined in the main Samba configuration file. In Red Hat Linux 9, that file is located in /etc/samba/smb.conf. Samba 3.0 includes a number of new defaults as well as newly configurable variables.


    The following highlights will give you more of a feel of what you can do with Samba 3.0. The behavior of some of the variables that you've seen in this book changes for Samba 3.0.





    • encrypt passwords: Passwords are now encrypted by default. If you want to accommodate those older Windows operating systems that can't handle encrypted passwords, you'll have to add the following line to smb.conf:




      encrypt passwords = no





    • winbind uid, winbind gid: These variables have been replaced by idmap uid and idmap gid. The new variables support mapping to NT user and group SIDs.






    • add user script: This command is replaced by add machine script; the default version of this command no longer assigns the computer account to any specific group.




    Naturally, there are a number of new variables that you might find useful when you incorporate Samba 3.0 into your network. Some of the more interesting variables related to user names and passwords include the following:





    • add group script: Supports creation of Windows Domain groups on the local Linux computer. Closely related to delete group script.





    • add user to group script: Supports adding a Samba-enabled user to a Windows Domain group on the local Linux computer. Closely related to delete user from group script.





    • auth methods: If you have multiple user name/password authentication databases, this variable allows you to set the search order.





    • passdb backend: Allows you to switch between password databases. The default uses the smbpasswd command. You can also set up this variable to look at the passwd.tdb database for a stand-alone server, or a database that conforms to LDAP.





    • realm: Lets you specify the Kerberos 5 server to use for authentication with an associated LDAP database.





    • set primary group script: Allows administrators to set a primary group for a new user.




    You can also use several new Samba configuration variables to manage the files that are shared with clients on the network. Some of these variables include the following:





    • hide special files: Linux includes a number of special files that you may not want to share, such as devices.





    • hide unwritable files: You can minimize the frustration of some users by hiding readonly files from browse lists. Naturally, this is not a good idea if you've shared a directory that is supposed to be read-only.





    • map acl inherit: Supports mapping from a Microsoft Windows ACL.





















     < Day Day Up > 



    5.6. Applied Resource-Oriented Architecture



    5.6. Applied Resource-Oriented
    Architecture


    Recently, I built a
    resource-oriented system on the rearchitecture work my company did for the
    Persistent URL (PURL) system. The original PURL[27] implementation was done close to 15 years ago. It was a
    forked version of Apache 1.0, written in C and reflecting the state of the art
    at the time.[28] It
    has been a steady piece of Internet infrastructure since then, but it was
    showing its age and needed modernization, particularly to support the W3C TAG's
    303 recommendation and higher volumes of use. Most of the data was accessible
    through web pages or ad hoc CGI-bin scripts because at the time, the browser
    seemed like the only real client to serve. As we started to realize the
    applicability of persistent, unambiguous identifiers for use in the Semantic
    Web, life sciences, publication, and similar communities, we knew that it was
    time to rethink the architecture to be more useful for both people and
    software.



    [27] http://purl.org



    [28] This codebase formed the basis of the very successful
    TinyURL (http://tinyurl.com) service.


    The PURL system was designed to
    mediate the tension between good names and resolvable names. Anyone who has been
    publishing content on the Web over time knows that links break when content gets
    moved around. The notion of a Persistent URL is one that has a good, logical
    name that maps to a resolvable location. For example, a PURL could be defined
    that points from http://purl.org/people/briansletten to http://bosatsu.net/foaf/brian.rdf and
    returns a 303 to indicate a "see also" response. I am not a network-addressable
    resource, but my Friend-of-a-Friend (FOAF) file[29] is a place to find more information about me. I could pass
    that PURL around to anyone who wants to link to my FOAF file. If I ever move to
    some other company, I could update the PURL to point to a new location for my
    FOAF file. All existing links will remain valid; they will just 303 to the new
    location. This process is described in Figure 5-6. The PURL Server implements the W3C Technical
    Architecture Group (TAG) guidance that 303 response codes can be used to provide
    more information about non-network addressable resources.



    [29] http://foaf-project.org



    Figure 5-6. PURL "See Also" redirect




    In addition to supporting the PURL
    redirection, we wanted to treat each major piece of data in the PURL system as
    an addressable information resource. Not only does this simplify the interaction
    with the user interface, it allows for unintended potential reuse of the data
    beyond what we originally planned. Manipulation of the resource requires
    ownership credentials, but anyone is allowed to fetch the definition of a PURL.
    There is the direct resolution process of hitting a PURL such as http://purl.org/employee/briansletten (which will result in the 303 redirect), as well as the
    indirect RESTful address of the PURL resource http://purl.org/admin/purl/employee/briansletten, which will return a definition of the PURL that currently
    looks something like the following:

    <purl status="1">
    <id>/employee/briansletten</id>
    <type>303</type>
    <maintainers>
    <uid>brian</uid>
    </maintainers>
    <seealso>
    <url>http://bosatsu.net/foaf/brian.rdf</url>
    </seealso>
    </purl>


    Clients of the PURL server can "surf" to
    the data definition as a means of finding information about a PURL resource
    without actually resolving it. No code needs to be written to retrieve this
    information. We can view it in a browser or capture it on the command line with
    curl. As such, we can imagine writing shell scripts that use data from our
    information resources to check whether a PURL points to something valid and is
    returning reasonable results. If not, we could find the owner of the PURL and
    fire off a message to the email address associated with the account.
    Addressable, accessible data finds its way into all manner of unintended
    orchestrations, scripts, applications, and desktop widgets because it is so easy
    and useful to do so.


    In the interest of full disclosure,
    we failed to support JSON as a request format in the initial release, which
    complicated the AJAX user interface. JavaScript XML handling leaves a lot to be
    desired. Even though we use the XML form internally, we should have gone to the
    trouble of exposing the JSON form for parsing in the browser. You can be sure we
    are fixing this oversight soon, but I thought it was important to highlight the
    benefits we could have taken advantage of if we had gotten it right in the first
    place. You do not need to support all data formats up front, but these days
    supporting both XML and JSON is a good start.


    As an interesting side note, we could
    have chosen several containers and tools to expose this architecture as
    expressed so far. Anything that responds to HTTP requests could have acted as
    our PURL server. This represents a shallow but useful notion of RESTful
    interfaces and resource-oriented architecture, as demonstrated in Figure 5-7. Any web server or application server can act as a shallow
    resource-oriented engine. The logical HTTP requests are interpreted as requests
    into servlets, Restlets, and similar addressable functionality.



    Figure 5-7. Shallow resource-oriented
    architectures




    We chose to use NetKernel as the foundation for this architecture because
    it is the embodiment of resource-oriented architectures and has a dual license,
    allowing its use with both open source and commercial projects. The idea of a
    logical coupling between layers with different representations is baked into the
    software architecture and offers similar benefits of flexibility, scalability,
    and simplicity. The linkage between the layers is through asynchronously
    resolved, logical names. This deeper notion of resource-oriented architectures
    looks something like Figure 5-8.
    NetKernel is an interesting software infrastructure because it takes the idea of
    logically connected resources inside so that HTTP logical requests can be turned
    into other logical requests. This architecture reflects the properties of the
    Web in a runtime software environment.



    Figure 5-8. Deep resource-oriented architectures




    The external URL http://purl.org/employee/briansletten gets mapped through a rewrite to a piece of
    functionality called an accessor.[30]
    Accessors live in modules that export public URI definitions representing an
    address space they will respond to. The convenience here is that it is possible
    to radically change the implementation technologies in a newer version of a
    module and simply update the rewrite rules to point to the new implementation.
    The client needs to be none the wiser as long as we return compatible responses.
    We can approximate this flexibility in modern object-oriented languages through
    the use of interfaces, but that still constrains us to a "physical" coupling to
    the interface definition. With the logical-only binding, we still need to
    support expectations from existing clients, but beyond that we are not coupled
    to any particular implementation detail. This is the same value we see
    communicating through URIs on the Web, but in locally running software!



    [30] http://docs.1060.org/docs/3.3.0/book/gettingstarted/doc_intro_code_accessor.html


    Internally, we use the Command
    Pattern[31]
    associated with the method type of the request to implement the accessor. An
    HTTP GET method is mapped to a GetResourceCommand that maintains no state. When the request comes in, we
    pull the command out of a map and issue the request to it. The REST stateless
    style ensures that all information needed to answer the request is contained in
    the request, so we do not need to maintain state in the command instance. We can
    access that request state through the context instance in the following code.
    This code looks relatively straightforward to Java developers. We are calling
    methods on Java objects, catching exceptions, the works. An important thing to
    note is the use of the IURAspect interface. We are essentially saying that we do
    not care what form the resource is in. It could be a DOM instance, a JDOM
    instance, a string, or a byte array; for our purposes it does not matter. The
    infrastructure will convert it into a bytestream tagged with metadata before
    responding to the request. If we had wanted it in a particular form supported by
    the infrastructure, we could have simply asked for it in that form. This
    declarative, resource-oriented approach helps radically reduce the amount of
    code that is necessary to manipulate data and allows us to use the right tool
    for the right job:



    [31] http://en.wikipedia.org/wiki/Command_pattern

    if(resStorage.resourceExists(context, uriResolver)) {
    IURAspect asp = resStorage.getResource(context, uriResolver);

    // Filter the response if we have a filter
    if (filter!=null) {
    asp = filter.filter(context, asp);
    }

    // Default response code of 200 is fine
    IURRepresentation rep = NKHelper.setResponseCode(context, asp, 200);
    rep = NKHelper.attachGoldenThread(context, "gt:" + path , rep);
    retValue = context.createResponseFrom(rep);
    retValue.setCacheable();
    retValue.setMimeType(NKHelper.MIME_XML);
    } else {
    IURRepresentation rep = NKHelper.setResponseCode(context,
    new StringAspect("No such resource: "
    + uriResolver.getDisplayName(path)), 404);
    retValue = context.createResponseFrom(rep);
    retValue.setMimeType(NKHelper.MIME_TEXT);
    }


    Most of the information resources will
    return a 200 when a GET request is issued. Obviously, PURLs override that
    behavior to return 302, 303, 307, 404, etc. The interesting resource-oriented
    tidbit is revealed when we inspect the PURL-oriented implementation of the
    resStorage.getResource() method:


     


    INKFRequest req = context.createSubRequest("active:purl-storage-query-purl");
    req.addArgument("uri", uri);
    IURRepresentation res = context.issueSubRequest(req);
    return context.transrept(res, IAspectXDA.class);




    In essence, we are issuing a logical request
    through the active:purl-storage-query-purl URI
    with an argument of ffcpl:/purl/employee/briansletten. Ignore the unusual URI scheme; it is simply used to
    represent an internal request in NetKernel. We do not know what code is actually
    going to be invoked to retrieve the PURL in the requested form, nor do we
    actually care. In a resource-oriented environment, we simply are saying, "The
    thing that responds to this URI will generate a response for me." We are now
    free to get things going quickly by serving static files to clients of the
    module while we design and build something like a Hibernate-based mapping to our
    relational database. We can make this transition by rewriting what responds to
    the active:purl-storage-query-purl URI. The
    client code never needs to know the difference. If we change the PURL resolution
    away from a local persistence layer to a remote fetch, the client code can still
    not care. These are the benefits we have discussed in the larger notion of
    resource-oriented Enterprise computing made concrete in a powerful software
    environment.


    Not only are our layers loosely coupled
    like this, but we get the benefit of an idempotent, stateless request in this
    environment as well. The earlier code snippet that fetches the PURL definition
    gets flattened internally to an asynchronously scheduled request to the URI
    active:purl-storage-query-purl+uri@ffcpl:/purl/employee/briansletten. As we discussed earlier, this becomes a compound
    hash key representing the result of querying our persistence layer for the
    generated result. Even though we know nothing about the code that gets invoked,
    NetKernel is able to cache the result nonetheless. This is the architectural
    memoization that I mentioned before. The
    actual process is slightly more nuanced, but in spirit, this is what is going
    on. If someone else tries to resolve the same PURL either internally or through
    the HTTP RESTful interface, we could pull the result from the cache. Though this
    may not impress anyone who has built caching into their web pages, it is
    actually a far more compelling result when you dig deeper. Any potential URI
    request is cacheable in this way, whether we are reading files in from disk,
    fetching them via HTTP, transforming an XML document through an XSLT file, or
    calculating pi to 10,000 digits. Each of these invocations is done through a
    logical, stateless, asynchronous result, and each has the potential to be
    cached. This resource-oriented architectural style gives us software that
    scales, is efficient, is cacheable, and works through uniform, logical
    interfaces. This results in substantially less brittle, more flexible
    architectures that scale, just like the Web and for the same reasons.


     


     


    What Is MySQL?
























































    Chapter 2 -

    What is MySQL?
    byGareth Downes-Powellet al.

    Wrox Press 2003





















































    What Is MySQL?


    MySQL is an SQL Database Server. Let's analyze each of these terms to help us define what exactly MySQL is.




    Server


    A server is a piece of software that runs in the background on a computer. It is built to keep running and executing specific tasks. All the way through this book, you will deal with two different servers: HTTP servers and MySQL servers.







    Database


    A database is a structured collection of data. It may be anything from the task list you use everyday, to information about the global population. A database is structured in a way that allows you to retrieve information easily and quickly depending on the kind of data it stores. You would not store a list of recipes the same way a big company will store its customer information. But the point these two databases have in common is that the information is easy to find and use.


    MySQL is a relational database management system. An RDBMS defines relations between data structures. A relation between two data structures is a way to construct new virtual structures in a way that will enforce some constraints or conditions. This will help the user to construct a robust application. Most of the operations we will describe in this book are relational operations.






    SQL


    SQL stands for "Structured Query Language". The SQL language, which is commonly used on database software, will let you talk in a human-friendly way to the server to retrieve information from your database and manipulate the data in it. You may find many other flavors of SQL database server, for example Oracle, IBM DB2, Microsoft SQL Server, but they will all speak the same basic language: SQL.






    Advantages of MySQL


    MySQL has some advantages and disadvantages when compared to other databases. Let's take a look at some of them:




    • MySQL is fast, very reliable, and easy to use. Other SQL servers are often fast and very reliable, but not very easy to use or configure. Some others are very easy to use, but neither fast nor reliable. MySQL has all these three qualities. It is also lightweight. The binary package of MySQL for Windows is only 12 MB. For comparison, Microsoft SQL Server weighs in at around 300 MB.




    • MySQL is the server of choice when used with the PHP language. PHP provides a very strong support for MySQL, and due to its huge user base has been widely and thoroughly tested. Many web-hosting companies provide MySQL and PHP as a standard package.




    • MySQL is open source. This means that you can have the sourcecode of MySQL and you are free to change it according to your needs. Hopefully, you won't need to, but the power of having MySQL open source is that if you did need to, it is very helpful to have the sourcecode to fit the server to your specific needs.




    • There is a very large user base for MySQL and there are a lot of online communities focused on development and help. This means that if you have problems, there are plenty of people to ask for advice. This community has also created a number of third-party tools to help you get the job done. You will find some links to these tools at the end of this chapter.




    • The biggest advantage of MySQL is that it is free. There are some cases where MySQL is not free, but for our goal, which is web application development, it is. For a free program, MySQL has a lot of advanced features like replication and a transactional system. It also runs on many platforms; you can run MySQL on Windows, Linux, FreeBSD, Solaris, and many others.









    Disadvantages of MySQL


    MySQL is not perfect. Its main disadvantage is that it lacks some of the more advanced features found on commercial database systems, which are also found on some of the other free database systems, like PostgreSQL. However, we won't need those features for the type of application that we're considering in this book.






    Where To Get MySQL


    MySQL can be obtained from many web sites and FTP servers. However, the official homepage for MySQL is http://www.mysql.com. Here you will be able to choose your operating system, choose the closest mirror to you, and choose between an HTTP or FTP transfer when you download.


    On MySQL.com you will find a number of files available for download:




    • MySQL is the most commonly used version of MySQL. It has no transaction system. All others features are included.




    • MySQL Max is almost the same as the MySQL package, except that this one supports transactions.




    • MySQL 4.0 is a development version of MySQL. It is not intended for a production environment, but is at your disposal for testing the new features.




    • MySQL GUI and MyCC are graphical clients for administering a MySQL server.




    There are many good products available to download for use with MySQL, we will review some of them at the end of the chapter.