Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7019 Articles
article-image-joomla-flash-flashy-templates-headers-banners-and-tickers-part-2
Packt
18 Nov 2009
4 min read
Save for later

Joomla! with Flash: Flashy Templates, Headers, Banners, and Tickers: Part 2

Packt
18 Nov 2009
4 min read
Using Flash headers We have seen that one of the uses of Flash in Joomla! templates is as a header. By using a Flash animation in a site's header you can create some stunning effects. As we have already seen, while designing the template, we may embed Flash animation in the header region and control the layout using an appropriate CSS stylesheet. To embed such Flash animations like these, you can use the <object> </object> XHTML tag. We have seen its use in the previous section. An alternative to this is showing the Flash header at some module position. There are several extensions that can be used for showing Flash objects at a module position. We will be looking at some of them next. Using Flexheader3 Flexheader3 is a Joomla! 1.5-compatible extension for using Flash as headers in Joomla! sites. This is available for download for free at http://flexheader2.andrehotzler.de/en/download/folder/208-flexheader3.html. After downloading the package, install it from the Extensions | Install/Uninstall screen in Joomla! administration. Then click on Extensions | Module Manager. In the Module Manager screen, you will find the module named Flexheader3. Click on it and that shows the Module: [Edit] screen for the Flexheader3 module, as shown in the following screenshot: The Details section is similar to other modules from where you enable the module, select the module position to display this, select the order of display, and assign menus for which this module will be displayed. The module-specific settings are in the Parameters section. As you see, selecting the module position is crucial for this module. Most of the templates don't have a position to display the header using a module. Therefore, you may need to create a module position for displaying a Flash header. The following section shows you how to create a module position displaying a header. Creating a module position To create a module position in your template you need to edit at least two files. Browse to the /templates directory, and click on the name of the template that you want to modify. You need to edit two files in the template folder: index.php and templateDetails.xml. First, open the templateDetails.xml file in your text editor and find the <positions> tag. Under this, type the line highlighted in the following code so that the file looks like the following: <positions> <position>flexheader</position> <position>left</position> <position>user1</position> ... <position>right</position> <position>debug</position> </positions> Remember to type <position>flexheader</position> before ending </positions> tag. Placing it outside the <positions> </positions> block will make the template unusable. After modifying the templateDetails.xml file, open the index.php file in your text editor. Find out the code for including a header image in that template. Generally, this is done by inserting an image using the <img src=... /> tag. If you don't find such a tag, then look for <div id="header" ... > or something like that. In such cases, CSS is used to display the background image to the div element. Once you have found the code for showing the header image, replace it with the following code: <jdoc:include type="modules" name="flexheader" style="RAW" /> This line of code means that you are instructing to include modules designated for the flexheader position. When we assign the Flexheader3 module to this position, the contents of that module will be displayed in this position. Generally, this module will produce a code like the following in this position: <img src="/images/header.png" title="My header image" alt="Header image" style="width: 528px; height: 70px;" /> When changes to index.php are made, save those changes. We will be configuring the module to display a Flash header in this module position.
Read more
  • 0
  • 0
  • 5859

article-image-keeping-extensions-secure-joomla-15-part-2
Packt
18 Nov 2009
15 min read
Save for later

Keeping Extensions Secure with Joomla! 1.5: Part 2

Packt
18 Nov 2009
15 min read
Making a directory path safe When we poke around in the server filesystem, we want to make sure that we know what we are doing. If we are dealing with directories, Joomla! provides us with some easy ways to make sure that those directories are being safely referenced. Failure to properly sanitize directory paths can lead to major security vulnerabilities. For example, if we were attempting to remove a directory, a security vulnerability could allow the deletion of the completely wrong resource! For more information about external control of paths, refer to CWE-73. A directory path is a URL to a directory. A directory path does not include a file. To safely manage a path to a file, refer to the next recipe, Making a path safe. How to do it... The static JFolder class, which is a part of the joomla.filesystem library, provides us with all sorts of useful methods for working with folders. To use the class, we must import it. jimport('joomla.filesystem.folder'); This bit is nice and easy. We use the JFolder::makeSafe() method and pass the name of the folder we want to sanitize. This method returns a string that can be used to interact safely with a folder. // make the directory path safe$safeDirPath = JFolder::makeSafe($unsafeDirPath); The one downside of JFolder::makeSafe() is that it assumes that the directory separators are correctly defined in the original string. For example, while running on a *nix system, if the string contained Windows-style backslashes instead of *nix style forward slashes, those slashes would be stripped. We can use the static JPath class to overcome this, as follows: // import JPath and JFolderjimport('joomla.filesystem.path');jimport('joomla.filesystem.folder');// clean the path$cleanDirPath = JPath::clean($unsafeDirPath);// make the directory path safe$safeDirPath = JFolder::makeSafe($cleanDirPath); This time we have included the JPath::clean() method prior to making the path safe. For more information about JPath, refer to the next recipe, Making a path safe. Directory separators The correct way to add directory separators in Joomla! is to use the DS constant. For example, the path to bar from foo is expressed as 'foo' . DS . 'bar'. How it works... What exactly does the JFolder::makeSafe() method do to guarantee that the directory path is safe? It strips out any characters or character sequences that are seen as posing potential security risks. The following list describes the characters that are considered safe: Alphanumeric (a-z, A-Z, and 0-9) Colon Dash Directory separators—the exact character sequence will depend on the environment Space Underscore The following table shows some examples of input and output strings from the JFolder::makeSafe() and JPath::clean() methods running on a Windows system (DS == ''). This is intended to show why using the two together can be preferable. If we choose to use the two together, order of usage is important. We should always use the JPath::clean() method first and the JFolder::makeSafe() method next. Although, as the fourth example shows, sometimes it can be worth cleaning a second time, which means clean, make safe, and clean.   Original   Clean   Safe   Clean and safe   foobar   foobar   foobar   foobar   //foo/bar   foobar   foobar   foobar   foo bar   foo bar   foo20bar   foo20bar   foo bar/..   foo bar..   foo bar   foo bar   /foo"   foo"   foodel   foodel   del *.*   del *.*       See also For information about safely dealing with files, refer to the previous recipe, Making a filename safe. For information about dealing with paths, please refer to the next recipe, Making a path safe. Making a path safe This recipe is similar to the previous two recipes, Making a filename safe and Making a directory path safe. This recipe differs in that it is for a complete path, normally to a file. There is a whole raft of security issues associated with processing paths. The following list identifies some of the more common issues we need to be aware of: CWE-22: Path traversal CWE-73: External control of filename or path CWE-98: Insufficient control of filename for include/require statement in PHP program (aka 'PHP file inclusion') CWE-434: Unrestricted file upload All of these vulnerabilities can have serious consequences, which should not be overlooked. For example, a malicious user could upload a destructively tailored script file and then execute it. Luckily, Joomla! provides us with some easy ways to reduce the risks associated with these potential weaknesses. Getting ready Before we delve into some of the complex ways of safely dealing with paths, let's start small. If we browse a basic installation of Joomla!, we will discover a large number of empty index.html files. These files prevent directory listings. Most web servers automatically generate directory listings if we visit a directory in which there are no index files. We should always add a copy of the empty index.html file to every directory in our extension. The use of empty index.html files provides a form of security through obscurity. This is only intended to be a very basic safeguard and should never be relied on for complete protection. For more information, refer to CWE-656. The second thing we should do is ensure that all of our PHP files can only be executed if the _JEXEC constant has been defined. This is used to make sure that the file has been executed from within Joomla!, that is, make sure it is not being used as a standalone script or is included from a script other than Joomla! // Check file executed from within Joomla!defined('_JEXEC') or die('Restricted access'); How to do it... If we are retrieving a path value from a request variable, we can use the PATH type. This type is not entirely what it seems, as a PATH type cannot be an absolute path and cannot reference hidden files and folders. This means it cannot start with any form of directory separator, as it would in a *nix environment, or a drive identifier, as it would in a Windows environment. It also means that none of the folder names or the optional filename can start with a period (a *nix hidden file/folder). If a value does not reach these criteria, the return value will be null. Therefore, it is very important to consider the suitability of the PATH type before opting to use it. // get the value of myPath from the request$myPath = JRequest::getVar('myPath', 'default', 'REQUEST', 'PATH'); On its own, the PATH type does not really constitute a security measure. For example, it does not protect against the path traversal CWE-22. Once we have our path variable, it is time to clean it. Cleaning is done in Joomla! using the static JPath class. Cleaning resolves any issues with directory separators. The exact process depends on the filesystem directory separator, for example a back or forward slash. The point is that if the directory separators in the string are incorrect, they are corrected as necessary. // import the JPath classjimport('joomla.filesystem.path');// clean $myPath$myPath = JPath::clean($myPath); Like the PATH type, a cleaned path does not really constitute a security measure. For example, it too does not protect against path traversal CWE-22. OK, we've heard enough about not constituting a security measure. Now it's time to overcome that problem. The static JPath class includes the JPath::check() method, which checks for path traversal and also that the path is within the Joomla! installation. The only constraint is that the method can only deal with absolute paths. Remember the PATH type used in JRequest can only cope with relative paths. Therefore, if we use the PATH type, we must convert it to an absolute path before using the JPath::check() method. // check for path traversal and snoopingJPath::check($myPath); The odd thing about this method is that we don't really do anything with the result! There is a very good reason for this. If the check fails, Joomla! will exit and display a suitable error message. In some instances, this may not be appropriate. Unfortunately, there is nothing we can do to prevent this. Therefore, if we want to avoid this we will have to check the path ourselves. Generally speaking, if a path fails the check, it is likely that an attack has been attempted. For that reason, exiting Joomla! is probably the most suitable response. However, the JPath::check() method does have one serious limitation. It only checks for snooping outside of the Joomla! root directory. We can manually check that we are only looking in a specified area in the Joomla! installation. // create path which must be the root of the directory$safePath = JPATH_COMPONENT . DS . 'safeFolder' . DS;// check for snooping outside of $safePathif (strpos($myPath, $safePath) !== 0) { JError::raiseError(20, 'Snooping out of bounds'); jexit();}// check for file traversaljimport('joomla.filesystem.path');JPath::check($directory); Essentially, this only ensures that the start of the $myPath string is equivalent to $safePath. We deal with failures in the same way as the JPath::check() method. Notice that we still use the JPath::check() method because we can still effectively use this method to check for file traversal. See also The previous two recipes, Making a filename safe and Making a directory path safe, discuss how to work safely with filenames and paths. We can also use filesystem permissions to secure files and folders. Safely retrieving request data Almost 99% of the time, security vulnerabilities in PHP applications such as Joomla! are caused by inadequate input parsing and validation CWE-20. We access request data in Joomla! using the static JRequest class. Built into this class is the ability to cast values to specific types and to mask data. We cannot rely solely on JRequest to ensure that incoming data is safe. This is where validation comes into play. Input data always has definable constraints. For example, we might define an entity identifier as a positive integer no less than 1 and no greater than 4294967295 (the maximum value for an unsigned MySQL INT). If we can define the constraints, we can also check that the input adheres to the constraints. Validating strings tend to be more complex. This is because strings are highly versatile and can contain many different characters. One thing we should always bear in mind when dealing with string validation is the effect of different character encodings. Joomla! 1.5 is UTF-8 compliant. UTF-8 is a Unicode variable-size multibyte character encoding that enables the encoding of many different alphabets and symbols that would otherwise be unavailable. As PHP is not UTF-8 aware, we should always use the static JString methods instead of the PHP string functions when dealing with UTF-8 strings. Getting ready Prior to doing anything, it is worth defining and documenting the boundaries of all the input that we use in our extension. This may include value ranges and formats. This can be a lengthy task, but it will help to ensure that our extension is secure. How to do it... The most important thing we must do when accessing request data is to use JRequest. Even if we just want the raw values, JRequest forms an important part of the Joomla! framework. Even before we get a chance to execute any code in our extension, JRequest will have already performed vital security work in an attempt to prevent global variable injection, CWE-471. So where do we begin? We start with the simple JRequest::getVar() method. This method is used to safely get at the request data. There are five parameters, of which only the first is required. The following example shows how we use the first three of these parameters: // gets the value of name$value = JRequest::getVar('nameOfVar');// gets the value of name,// if name is not specified returns defaultValue$value = JRequest::getVar('nameOfVar', 'defaultValue');// gets the value of name,// if name is not specified returns defaultValue// name is retrieved from the GET request data$value = JRequest::getVar('nameOfVar', 'defaultValue', 'GET'); The third parameter can be any of the following values:   Value Description COOKIE HTTP Cookies ENV Environment variables FILES Uploaded file details GET HTTP GET variables POST HTTP POST variables REQUEST Combination of GET, POST, and COOKIE; this is the default SERVER Server and environment variables In most instances, REQUEST (the default) should be sufficient. The only time we need to use GET and POST explicitly is when we are expecting a request to use a specific HTTP method. For added security, we can restrict a request to a certain HTTP method using the static JRequest::getMethod() method, as shown in the following example: if (JRequest::getMethod() != 'GET') { jexit('UNEXPECTED REQUEST METHOD');} There's more... The following two subsections discuss the last two parameters, $type and $mask. It is in the last two parameters where the security benefits of JRequest become very apparent. Casting Strictly speaking, casting is not an accurate description of the fourth JRequest::getVar() parameter. The types that we can cast to are not the types that we would use to describe a variable. For example, WORD is not a PHP or Joomla! type, but it is an available option. The following example extracts an integer representation of the GET request value, nameOfVar: // gets the value of nameOfVar,// if nameOfVar is not specified returns 0// name is retrieved from the GET request data// casts the return value as an integer$int = JRequest::getVar('nameOfVar', 0, 'GET', 'INT'); Hey presto! We have a safe value that we know is an integer. Had we not included the parameter to cast the value, we would not have been able to guarantee that $int was in fact an integer. Of course, we could have used the PHP intval() function or cast the value ourselves using (int). Not all of the types we can cast to are as simple as an integer; for example, ALNUM is used to strip non-alphanumeric characters from a string value. JRequest also provides alias methods that allow us to achieve the same thing, but with less code. For example, we can quickly extract an integer. The following example is the same as the previous example: $int = JRequest::getInt('nameOfVar', 0); The following table describes all of the types we can cast to using JRequest. Note that only the most commonly used types have alias methods. Type   Description   Alias   DEFAULT   Aggressive cleaning occurs to remove all detected code elements     ALNUM   Alphanumeric string; strips all non-ASCII letters and numbers     ARRAY   Force array cast     BASE64   Base64 string; strips all non Base64 characters, which is useful for passing encoded data in a URL, for example a return URL     BOOL or BOOLEAN   Force Boolean cast   getBool()   CMD   Command; strips all non-alphanumeric, underscore, period, and dash characters, which is ideal for values such as task   getCmd()   FLOAT or DOUBLE   Floating point number   getFloat()   INT or INTEGER   Whole number   getInt()   PATH   Filesystem path; used to identify a resource in a filesystem, for example the path to an image to use as a logo (relative paths only)     STRING   String; often used with a mask to clean the data   getString()   USERNAME   Username; strips characters unsuitable for use in a username, including non-printing characters (for example a backspace), angled brackets, double and single quotation marks, percent signs, and ampersands     WORD   Word; strips all non-alpha and underscore characters   getWord()     By default, the most aggressive mask is applied. This will remove code, such as HTML and JavaScript, from the data. The next section describes how we use masks. Masking strings The fifth JRequest::getVar() parameter defines a mask. Masks are used in JRequest to define what is and isn't allowed in a string value. By default no masking is applied, which means that very aggressive security measures are taken to ensure that the incoming data is as safe as possible. While this is useful, it is not always appropriate. For example, the core component com_content allows users to enter HTML data in an article. Without a mask, this information would be stripped from the request data. There are three constants we can use to easily define the mask we want to apply. These are JREQUEST_NOTRIM, JREQUEST_ALLOWRAW, and JREQUEST_ALLOWHTML. The following example shows how we can use these: // using getVar$string = JRequest::getVar('nameOfVar', 'default', 'REQUEST', 'STRING', JREQUEST_ALLOWRAW);// using getString alias$string = JRequest::getString('nameOfVar', 'default', 'REQUEST', JREQUEST_ALLOWRAW); The following examples show how the output varies depending on the mask that we apply: # Original input value 1 <p>Paragraph <a onClick="alert('foobar');">link</a></p> 2 CSS <link type="text/css", href="http://somewhere/nasty.css" /> 3 space at front of input 4 &ltp&gtPara&lt/p&gt # Output value (No mask) 1 Paragraph link 2 CSS 3 space at front of input 4 &ltp&gtPara&lt/p&gt    
Read more
  • 0
  • 0
  • 1174

article-image-plotting-geographical-data-using-basemap
Packt
18 Nov 2009
3 min read
Save for later

Plotting Geographical Data using Basemap

Packt
18 Nov 2009
3 min read
Basemap is a Matplotlib toolkit, a collection of application-specific functions that extends Matplotlib functionalities, and its complete documentation is available at http://matplotlib.sourceforge.net/basemap/doc/html/index.html. Toolkits are not present in the default Matplotlib installation (in fact, they also have a different namespace, mpl_toolkits), so we have to install Basemap separately. We can download it from http://sourceforge.net/projects/matplotlib/, under the matplotlib-toolkits menu of the download section, and then install it following the instructions in the documentation link mentioned previously. Basemap is useful for scientists such as oceanographers and meteorologists, but other users may also find it interesting. For example, we could parse the Apache log and draw a point on a map using GeoIP localization for each connection. We use the 0.99.3 version of Basemap for our examples. First example Let's start playing with the library. It contains a lot of things that are very specific, so we're going to just give an introduction to the basic functions of Basemap. # pyplot module importimport matplotlib.pyplot as plt# basemap importfrom mpl_toolkits.basemap import Basemap# Numpy importimport numpy as np These are the usual imports along with the basemap module. # Lambert Conformal map of USA lower 48 statesm = Basemap(llcrnrlon=-119, llcrnrlat=22, urcrnrlon=-64, urcrnrlat=49, projection='lcc', lat_1=33, lat_2=45, lon_0=-95, resolution='h', area_thresh=10000) Here, we initialize a Basemap object, and we can see it has several parameters depending upon the projection chosen. Let's see what a projection is: In order to represent the curved surface of the Earth on a two-dimensional map, a map projection is needed. This conversion cannot be done without distortion. Therefore, there are many map projections available in Basemap, each with its own advantages and disadvantages. Specifically, a projection can be: equal-area (the area of features is preserved) conformal (the shape of features is preserved) No projection can be both (equal-area and conformal) at the same time. In this example, we have used a Lambert Conformal map. This projection requires additional parameters to work with. In this case, they are lat_1, lat_2, and lon_0. Along with the projection, we have to provide the information about the portion of the Earth surface that the map projection will describe. This is done with the help of the following arguments: Argument Description llcrnrlon Longitude of lower-left corner of the desired map domain llcrnrlat Latitude of lower-left corner of the desired map domain urcrnrlon Longitude of upper-right corner of the desired map domain urcrnrlat Latitude of upper-right corner of the desired map domain     The last two arguments are:   Argument Description resolution Specifies what the resolution is of the features added to the map (such as coast lines, borders, and so on), here we have chosen high resolution (h), but crude, low, and intermediate are also available. area_thresh Specifies what the minimum size is for a feature to be plotted. In this case, only features bigger than 10,000 square kilometer
Read more
  • 0
  • 0
  • 6072

article-image-ground-sql-azure-migration-using-ms-sql-server-integration-services
Packt
18 Nov 2009
5 min read
Save for later

Ground to SQL Azure migration using MS SQL Server Integration Services

Packt
18 Nov 2009
5 min read
Enterprise data can be of very different kinds ranging from flat files to data stored in relational databases with the recent trend of storing data in XML data sources. The extraordinary number of database related products, and their historic evolution, makes this task exacting. The entry of cloud computing has turned this into one of the hottest areas as SSIS has been one of the methods indicated for bringing ground based data to cloud storage in SQL Azure, the next milestone in Microsoft Data Management. The reader may review my book on this site, "Beginners Guide to Microsoft SQL Server Integration Services" to get a jump start on learning this important product from Microsoft. SQL Azure SQL Azure is one of the three pillars of Microsoft's Azure cloud computing platform. It is a relational database built on SQL Server Technologies maintained on Microsoft's physical site where subscribers like you and me can rent out storage of data. Since the access is over the internet it is deemed to be in the cloud and Microsoft would provide all data maintenance. Some of the key benefits of this 'Database usage as a service' are: Manageability High Availability Scalability Which in other words means taking away a lot headache from you like worrying about hardware and software (SQL Azure Provisioning takes care of this), replication, DBAs with attitudes etc. Preparation for this tutorial You need some preparation to work with this tutorial. You must have a SQL Server 2008 installed to start with. You also need to register yourself with Microsoft to get an invitation to use SQL Azure by registering for the SQL Azure CTP. Getting permission is not immediate and may take days. After you register agreeing to the license terms, you get the permission (You become a subscriber to the service) to use the Azure Platform components (SQL Azure is one of them). After subscribing you can create a database on the SQL Azure instance. You will be the administrator of your instance (Your login will be known as the server level principal equivalent to the landbased sa login), and you can web access the server with a specific connection string provided to you and a strong password which you create. When you access the Azure URL, you provide the authentication to get connected to your instance of the server by signing in. Therein, you can create a database or delete an existing database. You have couple of tools available to work with this product. Read the blog post mentioned in the summary. Overview of this tutorial In this tutorial you will be using MS SQL Server Integration Services to create a package that can transfer a table from SQL Server 2008 to SQL Azure for which you have established your credentials. In my case the credentials are: Server: tcp:XXXXXX.ctp.database.windows.net User ID: YYYYY Password: ZZZZZ Database: PPPPPP Trusted_Connection=False; Here XXXXXX, YYYY,ZZZZZ, and PPPPPP are all the author's personal authentication values and you would get yours when you register as previously mentioned. Table to be migrated on SQL Server 2008 The table to be migrated on the SQL Server 2008 (Enterprise server, evaluation edition is shown in the next figure). PrincetonTemp is a simple table in the TestNorthwind database on the default instance of the local server on a Windows XP machine, with a few columns and no primary key. Create a SQL Server Integration Services Package Open BIDS (a Visual Studio add-in extending support to build database applications with SQL Server) and create a new SQL Server Integration Services project[Use File |New |Project...in the IDE]. Herein the Visual Studio 2008 with SP1 is used. You need to provide a name which for this project is GroundToCloud. The program creates the project for you which you can see in the Solution Explorer. By default it creates a package for you, Package.dtsx. You may rename the package (herein ToAzure.dtsx)and the project folders and file appear as shown. Add an ADO.NET Source component Drag and drop a Data Flow Task to the tabbed page Control Flow in the package designer. Into the Data flow tabbed page drag and drop an ADO.NET Source component from the Toolbox. Double click the component you just added, from the pop-up menu choose Edit... The ADO.NET Source editor gets displayed. If there are previously configured connections one of them may show up in this window. We will be creating a new connection and therefore click the New... button to display an empty Configure ADO.NET Connection Manager as shown (again, if there are existing connections they all will show up in this window). A connection is needed in connecting to a source outside the IDE. Double click the New... button to display the Connection Manager window which is all but empty. Fill in the details for your instance of ground based server as shown (the ones shown are for this article at the author's site). You may test the connection by hitting the Test Connection button. Clicking the OK buttons on the Connection Manager and the Configure ADO.NET Connection Manager will bring you back to the ADO.NET Source Editor displaying the connection you have just made as shown. A connection string also gets added to the bottom pane of the package designer as well as to the Configure ADO.NET Connection Manager. Click on the drop-down and pick the table (PrincetonTemp) that needs to be migrated to the cloud based server, SQL Azure. Click OK. The Columns navigation on the left would reveal all the columns in the table if it were to be clicked. The Preview button would return the data returned by a SELECT query on the columns as shown.
Read more
  • 0
  • 0
  • 4000

article-image-quality-assurance-asterisk-16
Packt
18 Nov 2009
10 min read
Save for later

Quality Assurance in Asterisk 1.6

Packt
18 Nov 2009
10 min read
The world has changed quite a bit in the last 150 years. Over this time, the telephone system has been invented, improved, and automated. Telephone switches no longer refer to people sitting in a large room connecting wires between the appropriate jacks. Flexible and powerful telephone service has moved from a dream to an expectation in large businesses, and for most of us it is a necessity. Today, telephone systems are the lifeblood of business. They are how we take orders, acquire supplies, and even call for emergency assistance. With the increase in prominence of telephones, the expectations of telephone users have increased proportionally. Not only have the technological expectations for telephone systems increased dramatically, but consumers are expecting more and more out of the businesses they call. Customers expect to be helped quickly and professionally. They want to know everything in a matter of minutes. Roads do not hold the only rage our society is facing today. As a business we have a variety of questions relating to our telephone system such as: How are our personnel handling angry callers? Are our employees answering the calls in a reasonable amount of time? Do we have any workers using the phone system for personal calls when they should be doing their job? We will never be able to make sure everybody does what they are supposed to do all of the time. What we will be able to do at the end of this article is perform spot-checks on how we are doing on customer service, and make sure our phone service isn't being used for unauthorized purposes. Ultimately, it comes down to a matter of trust; however, some people do not know better because they haven't been fully trained. Most will always act honorably; however, some just cannot and should not be trusted. We will try to find out who is who. Call Detail Records When we talk about security, what images come to mind? May be a big, burly guard? Perhaps a bunch of guys in green, carrying machine guns? Do we imagine a person with a metal-detecting wand? Or do we think of thick glass window panes? All of these are security features. It is just that some are a little more intrusive than others. Each time we increase security, we become a little bit less friendly. We all have to decide how far we are willing (and able) to go. In the continuum of security, Call Detail Records are the least intrusive. No special usernames or passwords have to be remembered. No fear of big brother breathing down your customers' and users' necks need be felt. We are simply doing the same thing telephone companies do—tracking what calls were made, when they were made, how long they lasted, where they came from, and a few other bits of information. This information is then available for us to review at our leisure. Asterisk gives us a few options on how we track this information. The two major choices are flat-file logging and database logging. Flat-file CDR logging By default, Asterisk includes a module called cdr_csv. Right out of the box, Asterisk logs all calls coming in and going out. The information for these calls is placed in a Comma Separated Value (CSV) file. This CSV file is located in var/log/asterisk/cdr-csv. All information is available in Master.csv, and some channels can be configured to send some information to other files as well. The benefit of using a CSV file is the simplicity. Right after compiling and installing Asterisk, this method will work. No additional configuration is required. Also, no additional network traffic is generated, and no additional services have to be installed on our server. When using the CSV form of CDR, we will see lists and lists of values. They are not very easy to parse, so here is the format, in the order in which they appear: account code: As determined by the channel (for DAHDI) or the user (for IAX and SIP) source: The source of the call destination: The destination of the call destination context caller ID channel: The channel of the source destination channel: If applicable last application: The last application run on the channel last application argument: The last argument to the last application on the channel start time: The time the call commenced answer time: The time the call was answered end time: The time the call ended duration: The difference between start time and end time billable seconds: The difference between answer time and end time, which must be less than the duration disposition: Either ANSWERED, NO ANSWER, or BUSY amaflags: As set for the channel or user, like account code uniqueid: A unique call identifier userfield: A user field set by the SetCDRUserField command We see that there are many items of information logged for each and every call. We can compare the billable seconds with our phone bill at the end of the month to make sure they're close. We can look at the destination and figure out if the calls were authorized. This gives us enough information to answer most questions we may have about a phone call. While we have enough information to answer questions, finding that answer is not very easy. We would have to scan through the entire file to try to find anything. If we are going to use an accounting package or reporting software, CSV may be exactly what we need. However, if we wish to use it in a more ad hoc sort of way, it is not very readable. Database CDR logging If we wish to read our CDR logs, it is most easily accomplished when the records are sortable. The easiest way to do this is to store our CDR records in a database. Even in this, Asterisk gives us choices. Included with Asterisk is support for PostgreSQL databases. In order to be able to install this, we must first have the postgresql-devel package installed on our system. If you have to install this package, you'll need to reinstall Asterisk. The automake system will automatically detect that we have the capability to use PostgreSQL and compile that module for us. Aside from the development packages we have installed, we will also need a PostgreSQL server somewhere in our network. It can be the same machine as the Asterisk server, but it doesn't necessarily need to be. In fact, it probably makes sense to have only one such database server on our network, and we don't want to tie up too much of our PBX's resources with database maintenance and storage. There is a script in /usr/src/asterisk/contrib/scripts/ called postgres_cdr.sql, which creates the correct table structure for us. This script should be run from the database server. If we get an error message while rebuilding that says something like "cannot find-lz", then we need to install zlib-devel. Now that we have set up our database and installed the CDR module, we must configure Asterisk to use the correct database. In order to do this, we need to edit /etc/asterisk/cdr_pgsql.conf. All of the configuration variables are in the global section. Our file should look like the following: [global]hostname=dbserver.mydomain.tldport=5432dbname=asteriskpassword=supersecretuser=asteriskuser Once we have these variables set, the next time we restart Asterisk, all CDR records will be logged in the database. If PostgreSQL is not our database of choice, we can use MySQL. This is not a part of the normal distribution of Asterisk. But as we have already installed asterisk-addons, we should already have the ability to use MySQL for CDR logging. Before we compile, we need to make sure that we have mysql-devel installed. First, we need to decide which version we're going to use. Because of some license quibbles, MySQL version 4.0 and later is not in the automatic package distribution chain. Instead, if we do need to download it, we will have to get it directly from www.mysql.com. However, the older version (3.x) will work with Asterisk and hence, you may wish to take a look at the differences between what version 3 offered and what later versions give us. Other than the development package mentioned, we will also need a MySQL server somewhere in our network. Just as with PostgreSQL, we can choose to have it on the same server as Asterisk, but for the same reasons, we probably shouldn't. Next, on the database server, we need to create the database with a user and a table for the CDR data. We do this by running the following code: # mysqladmin create database asteriskcdrdb # mysqlmysql> GRANT ALL PRIVILEGES   -> ON asteriskcdrdb.*   -> TO asteriskcdruser   -> IDENTIFIED BY 'changethis2yourpassword';mysql> USE asteriskcdrdb;mysql> CREATE TABLE cdr (   -> uniqueid varchar(32) NOT NULL default '',   -> userfield varchar(255) NOT NULL default '',   -> accountcode varchar(20) NOT NULL default '',   -> src varchar(80) NOT NULL default '',   -> dst varchar(80) NOT NULL default '',   -> dcontext varchar(80) NOT NULL default '',   -> clid varchar(80) NOT NULL default '',   -> channel varchar(80) NOT NULL default '',   -> dstchannel varchar(80) NOT NULL default '',   -> lastapp varchar(80) NOT NULL default '',   -> lastdata varchar(80) NOT NULL default '',   -> calldate datetime NOT NULL default '0000-00-00 00:00:00',   -> duration int(11) NOT NULL default '0',   -> billsec int(11) NOT NULL default '0',   -> disposition varchar(45) NOT NULL default '',   -> amaflags int(11) NOT NULL default '0'-> ); That's all there is to it! We only have to do this once, so it's really not so bad. Next, we have to modify the /etc/asterisk/cdr_mysql.conf file to correctly reflect our choices. [global]hostname=ourdbserver.ourdomain.tlddbname=asteriskcdrdbpassword=changethis2yourpassworduser=asteriskcdruserport=3306userfield=1 The next time we restart Asterisk, our CDR information will be stored in the MySQL database. What does that give us? We now have the ability to use a number of very powerful tools to search our CDR records to find trends and patterns.
Read more
  • 0
  • 0
  • 1680

article-image-microsoft-chart-xml-data
Packt
18 Nov 2009
4 min read
Save for later

Microsoft Chart with XML Data

Packt
18 Nov 2009
4 min read
Introduction SQL 2000 Server provided T-SQL language extensions to operate bi-directionally with relational and XML sources. It also provided two system stored procedures, sp_XML_preparedocument and sp_XML_removedocument, that assist the XML to Relational transformation. This support for returning XML data from relational data using the For XML clause is continued in SQL Server 2005 and SQL Server 2008 although the support for XML is lot more extensive. The shape of the data returned by the For XML clause is further modified by choosing the following modes, raw, auto, explicit, or path. As a preparation for this article we will be creating an XML document starting from the PrincetonTemp table used in a previous article, Binding MS Chart Control to LINQ Data Source Control, on this site. Creating an XML document from an SQL Table Open the SQL Server Management and create a new query [SELECT * from PrincetonTemp for XML auto]. You can use the For XML Auto clause to create a XML document (actually what you create is a fragment - a root-less XML without a processing directive) as shown in Figure 01. Figure 01: For XML Auto clause of a SELECT statement The result shown in a table has essentially two columns with the second column containing the document fragment shown in the next listing. Listing 01: <PrincetonTemp Id="1" Month="Jan " Temperature="4.000000000000000e+001" RecordHigh="6.000000000000000e+001"/> <PrincetonTemp Id="2" Month="Feb " Temperature="3.200000000000000e+001" RecordHigh="5.000000000000000e+001"/> <PrincetonTemp Id="3"Month="Mar " Temperature="4.300000000000000e+001" RecordHigh="6.500000000000000e+001"/> <PrincetonTemp Id="4" Month="Apr " Temperature="5.000000000000000e+001" RecordHigh="7.000000000000000e+001"/> <PrincetonTemp Id="5" Month="May " Temperature="5.300000000000000e+001" RecordHigh="7.400000000000000e+001"/> <PrincetonTemp Id="6" Month="Jun " Temperature="6.000000000000000e+001" RecordHigh="7.800000000000000e+001"/> <PrincetonTemp Id="7" Month="Jul " Temperature="6.800000000000000e+001" RecordHigh="7.000000000000000e+001"/> <PrincetonTemp Id="8" Month="Aug " Temperature="7.100000000000000e+001" RecordHigh="7.000000000000000e+001"/> <PrincetonTemp Id="9" Month="Sep " Temperature="6.000000000000000e+001" RecordHigh="8.200000000000000e+001"/> <PrincetonTemp Id="10" Month="Oct " Temperature="5.500000000000000e+001" RecordHigh="6.700000000000000e+001"/> <PrincetonTemp Id="11" Month="Nov " Temperature="4.500000000000000e+001" RecordHigh="5.500000000000000e+001"/> <PrincetonTemp Id="12" Month="Dec " Temperature="4.000000000000000e+001" RecordHigh="6.200000000000000e+001"/> This result is attribute-centric as each row of data corresponds to a row in the relational table with each column represented as an XML attribute. The same data can be extracted in an element centric manner by using the directive elements in the SELECT statement as shown in the next figure. Figure 02: For XML auto, Elements clause of a Select statement This would still give us an XML fragment but now it is displayed with element nodes as shown in the next listing (only two nodes 1 and 12 are shown). Listing 02: <PrincetonTemp><Id>1</Id><Month>Jan </Month><Temperature>4.000000000000000e+001</Temperature> <RecordHigh>6.000000000000000e+001</RecordHigh> </PrincetonTemp> ... <PrincetonTemp><Id>12</Id><Month>Dec </Month><Temperature>4.000000000000000e+001</Temperature> <RecordHigh>6.200000000000000e+001 </RecordHigh></PrincetonTemp> To make a clear distinction between the results returned by the two select statements the first row of data is shown in blue. This has returned elements and not attributes. As you can see the returned XML still lacks a root element as well as the XML processing directive. To continue with displaying this data in MS Chart Save Listing 2 as PrincetonXMLDOC.xml to a location of your choice. Create a Framework 3.5 Web Site project Let us create a web site project and display the chart on the Default.aspx page. Open Visual Studio 2008 from its shortcut on the desktop. Click File  New | Web Site...|(or Shift+Alt+N) to open the New Web Site window. Change the default name of the site to a name of your choice (herein Chart_XMLWeb) as shown. Make sure you are creating a .NET Framework 3.5 web site as shown here. Figure 03: New Framework 3.5 Web Site Project Click on APP_Data folder in the solution explorer as shown in the next figure and click on Add Existing Item… menu item. Figure 04: Add an existing item to the web site folder In the interactive window that gets displayed browse to the location where you saved the PrincetonXMLDOC.xml file and click Add button. This will add the XML file to the ADD_Data folder of the web site project. Double click PrincetonXMLDOC.xml in the web site project folder to display and verify its contents as shown in the next figure. Only nodes 1 and 12 are shown expanded. As mentioned previously this is an XML fragment. Figure 05: Imported PrincetonXMLDOC.xml Modify this document by adding the <root/> as well as the XML processing instruction as shown in the next figure. Build the project. Figure 06: Modified PrincetonXMLDOX.xml (valid XML document)
Read more
  • 0
  • 0
  • 14701
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-unity-game-development-interactions-part-2
Packt
18 Nov 2009
14 min read
Save for later

Unity Game Development: Interactions (Part 2)

Packt
18 Nov 2009
14 min read
Opening the outpost In this section, we will look at the two differing approaches for triggering the animation giving you an overview of the two techniques that will both become useful in many other game development situations. In the first approach, we'll use collision detection—a crucial concept to get to grips with as you begin to work on games in Unity. In the second approach, we'll implement a simple ray cast forward from the player. Approach 1—Collision detection To begin writing the script that will trigger the door-opening animation and thereby grant access to the outpost, we need to consider which object to write a script for. In game development, it is often more efficient to write a single script for an object that will interact with many other objects, rather than writing many individual scripts that check for a single object. With this in mind, when writing scripts for a game such as this, we will write a script to be applied to the player character in order to check for collisions with many objects in our environment, rather than a script made for each object the player may interact with, which checks for the player. Creating new assets Before we introduce any new kind of asset into our project, it is good practice to create a folder in which we will keep assets of that type. In the Project panel, click on the Create button, and choose Folder from the drop-down menu that appears. Rename this folder Scripts by selecting it and pressing Return (Mac) or by pressing F2 (PC). Next, create a new JavaScript file within this folder simply by leaving the Scripts folder selected and clicking on the Project panel's Create button again, this time choosing JavaScript. By selecting the folder, you want a newly created asset to be in before you create them, you will not have to create and then relocate your asset, as the new asset will be made within the selected folder. Rename the newly created script from the default—NewBehaviourScript—to PlayerCollisions. JavaScript files have the file extension of .js but the Unity Project panel hides file extensions, so there is no need to attempt to add it when renaming your assets. You can also spot the file type of a script by looking at its icon in the Project panel. JavaScript files have a 'JS' written on them, C# files simply have 'C#' and Boo files have an image of a Pacman ghost, a nice little informative pun from the guys at Unity Technologies! Scripting for character collision detection To start editing the script, double-click on its icon in the Project panel to launch it in the script editor for your platform—Unitron on Mac, or Uniscite on PC. Working with OnControllerColliderHit By default, all new JavaScripts include the Update() function, and this is why you'll find it present when you open the script for the first time. Let's kick off by declaring variables we can utilise throughout the script. Our script begins with the definition of four variables, public member variables and two private variables. Their purposes are as follows: doorIsOpen: a private true/false (boolean) type variable acting as a switch for the script to check if the door is currently open. doorTimer: a private floating-point (decimal-placed) number variable, which is used as a timer so that once our door is open, the script can count a defined amount of time before self-closing the door. currentDoor: a private GameObject storing variable used to store the specific currently opened door. Should you wish to add more than one outpost to the game at a later date, then this will ensure that opening one of the doors does not open them all, which it does by remembering the most recent door hit. doorOpenTime: a floating-point (potentially decimal) numeric public member variable, which will be used to allow us to set the amount of time we wish the door to stay open in the Inspector. doorOpenSound/doorShutSound: Two public member variables of data type AudioClip, for allowing sound clip drag-and-drop assignment in the Inspector panel. Define the variables above by writing the following at the top of the PlayerCollisions script you are editing: private var doorIsOpen : boolean = false;private var doorTimer : float = 0.0;private var currentDoor : GameObject;var doorOpenTime : float = 3.0;var doorOpenSound : AudioClip;var doorShutSound : AudioClip; Next, we'll leave the Update() function briefly while we establish the collision detection function itself. Move down two lines from: function Update(){} And write in the following function: function OnControllerColliderHit(hit : ControllerColliderHit){} This establishes a new function called OnControllerColliderHit. This collision detection function is specifically for use with player characters such as ours, which use the CharacterController component. Its only parameter hit is a variable that stores information on any collision that occurs. By addressing the hit variable, we can query information on the collision, including—for starters—the specific game object our player has collided with. We will do this by adding an if statement to our function. So within the function's braces, add the following if statement: function OnControllerColliderHit(hit: ControllerColliderHit){ if(hit.gameObject.tag == "outpostDoor" && doorIsOpen == false){ }} In this if statement, we are checking two conditions, firstly that the object we hit is tagged with the tag outpostDoor and secondly that the variable doorOpen is currently set to false. Remember here that two equals symbols (==) are used as a comparative, and the two ampersand symbols (&&) simply say 'and also'. The end result means that if we hit the door's collider that we have tagged and if we have not already opened the door, then it may carry out a set of instructions. We have utilized the dot syntax to address the object we are checking for collisions with by narrowing down from hit (our variable storing information on collisions) to gameObject (the object hit) to the tag on that object. If this if statement is valid, then we need to carry out a set of instructions to open the door. This will involve playing a sound, playing one of the animation clips on the model, and setting our boolean variable doorOpen to true. As we are to call multiple instructions—and may need to call these instructions as a result of a different condition later when we implement the ray casting approach—we will place them into our own custom function called OpenDoor. We will write this function shortly, but first, we'll call the function in the if statement we have, by adding: OpenDoor(); So your full collision function should now look like this: function OnControllerColliderHit(hit: ControllerColliderHit){ if(hit.gameObject.tag == "outpostDoor" && doorIsOpen == false){ OpenDoor(); }} Writing custom functions Storing sets of instructions you may wish to call at any time should be done by writing your own functions. Instead of having to write out a set of instructions or "commands" many times within a script, writing your own functions containing the instructions means that you can simply call that function at any time to run that set of instructions again. This also makes tracking mistakes in code—known as Debugging—a lot simpler, as there are fewer places to check for errors. In our collision detection function, we have written a call to a function named OpenDoor. The brackets after OpenDoor are used to store parameters we may wish to send to the function—using a function's brackets, you may set additional behavior to pass to the instructions inside the function. We'll take a look at this in more depth later in this article under the heading Function Efficiency. Our brackets are empty here, as we do not wish to pass any behavior to the function yet. Declaring the function To write the function we need to call, we simply begin by writing: function OpenDoor(){} In between the braces of the function, much in the same way as the instructions of an if statement, we place any instructions to be carried out when this function is called. Playing audio Our first instruction is to play the audio clip assigned to the variable called doorOpenSound. To do this, add the following line to your function by placing it within the curly braces after { "and before" }: audio.PlayOneShot(doorOpenSound); To be certain, it should look like this: function OpenDoor(){ audio.PlayOneShot(doorOpenSound);} Here we are addressing the Audio Source component attached to the game object this script is applied to (our player character object, First Person Controller), and as such, we'll need to ensure later that we have this component attached; otherwise, this command will cause an error. Addressing the audio source using the term audio gives us access to four functions, Play(), Stop(), Pause(), and PlayOneShot(). We are using PlayOneShot because it is the best way to play a single instance of a sound, as opposed to playing a sound and then switching clips, which would be more appropriate for continuous music than sound effects. In the brackets of the PlayOneShot command, we pass the variable doorOpenSound, which will cause whatever sound file is assigned to that variable in the Inspector to play. We will download and assign this and the clip for closing the door after writing the script. Checking door status One condition of our if statement within our collision detection function was that our boolean variable doorIsOpen must be set to false. As a result, the second command inside our OpenDoor() function is to set this variable to true. This is because the player character may collide with the door several times when bumping into it, and without this boolean, they could potentially trigger the OpenDoor() function many times, causing sound and animation to recur and restart with each collision. By adding in a variable that when false allows the OpenDoor() function to run and then disallows it by setting the doorIsOpen variable to true immediately, any further collisions will not re-trigger the OpenDoor() function. Add the line: doorOpen = true; to your OpenDoor() function now by placing it between the curly braces after the previous command you just added. Playing animation We have already imported the outpost asset package and looked at various settings on the asset before introducing it to the game in this article. One of the tasks performed in the import process was the setting up of animation clips using the Inspector. By selecting the asset in the Project panel, we specified in the Inspector that it would feature three clips: idle (a 'do nothing' state) dooropen doorshut In our openDoor() function, we'll call upon a named clip using a String of text to refer to it. However, first we'll need to state which object in our scene contains the animation we wish to play. Because the script we are writing is to be attached to the player, we must refer to another object before referring to the animation component. We do this by stating the line: var myOutpost : GameObject = GameObject.Find("outpost"); Here we are declaring a new variable called myOutpost by setting its type to be a GameObject and then selecting a game object with the name outpost by using GameObject.Find. The Find command selects an object in the current scene by its name in the Hierarchy and can be used as an alternative to using tags. Now that we have a variable representing our outpost game object, we can use this variable with dot syntax to call animation attached to it by stating: myOutpost.animation.Play("dooropen"); This simply finds the animation component attached to the outpost object and plays the animation called dooropen. The play() command can be passed any string of text characters, but this will only work if the animation clips have been set up on the object in question. Your finished OpenDoor() custom function should now look like this: function OpenDoor(){ audio.PlayOneShot(doorOpenSound); doorIsOpen = true; var myOutpost : GameObject = GameObject.Find("outpost"); myOutpost.animation.Play("dooropen");} Reversing the procedure Now that we have created a set of instructions that will open the door, how will we close it once it is open? To aid playability, we will not force the player to actively close the door but instead establish some code that will cause it to shut after a defined time period. This is where our doorTimer variable comes into play. We will begin counting as soon as the door becomes open by adding a value of time to this variable, and then check when this variable has reached a particular value by using an if statement. Because we will be dealing with time, we need to utilize a function that will constantly update such as the Update() function we had awaiting us when we created the script earlier. Create some empty lines inside the Update() function by moving its closing curly brace } a few lines down. Firstly, we should check if the door has been opened, as there is no point in incrementing our timer variable if the door is not currently open. Write in the following if statement to increment the timer variable with time if the doorIsOpen variable is set to true: if(doorIsOpen){ doorTimer += Time.deltaTime;} Here we check if the door is open — this is a variable that by default is set to false, and will only become true as a result of a collision between the player object and the door. If the doorIsOpen variable is true, then we add the value of Time.deltaTime to the doorTimer variable. Bear in mind that simply writing the variable name as we have done in our if statement's condition is the same as writing doorIsOpen == true. Time.deltaTime is a Time class that will run independent of the game's frame rate. This is important because your game may be run on varying hardware when deployed, and it would be odd if time slowed down on slower computers and was faster when better computers ran it. As a result, when adding time, we can use Time.deltaTime to calculate the time taken to complete the last frame and with this information, we can automatically correct real-time counting. Next, we need to check whether our timer variable, doorTimer, has reached a certain value, which means that a certain amount of time has passed. We will do this by nesting an if statement inside the one we just added—this will mean that the if statement we are about to add will only be checked if the doorIsOpen if condition is valid. Add the following code below the time incrementing line inside the existing if statement: if(doorTimer > doorOpenTime){shutDoor();doorTimer = 0.0;} This addition to our code will be constantly checked as soon as the doorIsOpen variable becomes true and waits until the value of doorTimer exceeds the value of the doorOpenTime variable, which, because we are using Time.deltaTime as an incremental value, will mean three real-time seconds have passed. This is of course unless you change the value of this variable from its default of 3 in the Inspector. Once the doorTimer has exceeded a value of 3, a function called shutDoor() is called, and the doorTimer variable is reset to zero so that it can be used again the next time the door is triggered. If this is not included, then the doorTimer will get stuck above a value of 3, and as soon as the door was opened it would close as a result. Your completed Update() function should now look like this: function Update(){ if(doorIsOpen){ doorTimer += Time.deltaTime; if(doorTimer > 3){ shutDoor(); doorTimer = 0.0; } }} Now, add the following function called shutDoor() to the bottom of your script. Because it performs largely the same function as openDoor(), we will not discuss it in depth. Simply observe that a different animation is called on the outpost and that our doorIsOpen variable gets reset to false so that the entire procedure may start over: function shutDoor(){audio.PlayOneShot(doorShutSound);doorIsOpen = false;var myOutpost : GameObject = GameObject.Find("outpost");myOutpost.animation.Play("doorshut");}
Read more
  • 0
  • 0
  • 3019

article-image-joomla-15-blogging-and-rss-feeds
Packt
18 Nov 2009
7 min read
Save for later

Joomla! 1.5 Blogging and RSS Feeds

Packt
18 Nov 2009
7 min read
  Blogging is a great way to get more traffic to your site and communicate with the community interested in the same topics as you. Search engines such as Yahoo! and Google love blogs because of the fact that articles written in blogs are mostly up-to-date and they get the information about the update of a blog really fast using RSS Feeds and Pings. Articles posted on a blog with these two options in place can get into the search engine indexes within hours, sometimes even minutes. How is blogging good for SEO? Using a blog has some advantages that fair really well if you want to have more visibility in the search engines. We will be looking at some of those advantages and how they can affect your search engine rankings. I am not saying blogging is easy, but it is very rewarding. Creating fresh content Creating short articles about your favorite topic and publishing them on a regular basis is the best way to get into the search engine results pages faster. The number one thing about blogging is that you can write long articles or short articles. The combination of the two different formats won't break the flow of your site, unlike a normal web site, where you mostly write articles that are built with a certain length. You can also state an opinion about things that are going on in your community and write news items. All that in one web site without worrying too much about how to structure all the information. A structure is needed for SEO and Joomla! will force you to use the structure you have chosen for your site. Using Joomla! as a blog will make it easier for you as you will be using the categories created in advance to hold that information for you. Google and blog indexing If you set up a blog and start using the sites and services we will be looking at, like FeedBurner and Technorati, you will notice that the major search engines also use these services to index blog sites and find new posts really fast. Now Google even owns FeedBurner! You will not only syndicate your articles using options such as RSS Feeds, but you will also push your articles through Technorati, the number one site to show your blog to bloggers. Google has a special tool with some basic categorization in place for searching blogs; you can find it at http://blogsearch.google.com. One good thing about this blog search tools is that it will show you how "old" a blog post is. For example, under the title you will see a statement such as 10 hours ago just to prove how fast you can get an article indexed from a blog. Setting up Joomla! as a blog Joomla! was not built to be a blog in its basic form, unlike WordPress. However, Joomla! has a built-in layout function called Blog layout that can be used for sections and categories. RSS Feeds are also built in, but we need to put an extra component in place to get a commenting system. First things first, let's set up the basic structure of your Joomla! based blog. How to structure your blog section The first thing you need to do is to come up with a section name for your blog. You already have an extended keywords list, so it should not be difficult to set up a blog. In my example site I have set up a Section called Garden Pools Blog and the Alias I want to use is garden-pools. This alias is going to be included in the SEF URL and contains some of the keywords I want to target with the blog. Once that is ready, you need to create the main categories, which of course will be the main topics of your blog section. Choosing your blog categories Again you need to find the right keywords to put into your category names. The best thing you can do now is to focus on the topic you want to blog about. It is really essential that you think about these categories and name them the right way, or you will get into trouble later on. Once you know about the SEF URLs, you might find yourself in trouble if you have the same category names as in the main site. In my category for this blog I have used the category name Water Gardens, depending on my choice of URL construction in the sh404SEF component. It is possible that I may not use the same category name for the main topics of my site. If I were to use the same category name they both would get the URL http://www.cblandscapegardening/water-gardens/, leaving one of the categories not reachable. One workaround would be to change the alias of one of the categories, but that would still leave a duplicate title on your site which you would need to change. Google would show it as a possible duplicate title in its webmaster content analysis. You can prevent this by choosing your categories wisely. Therefore, it is important to think about these URL structures, when you start naming and creating the blog categories. Stay focused and limit yourself If you start naming the categories make sure you stay on the same blog topic and keep the terms as relevant as possible. Don't create too many categories as you are going to create a separate menu for the blog. Too many categories will fill your menu with a long list of topics, and the visitors will not be able to choose from this long list. It is also not a pretty sight to have such a long list in your sidebar. Limiting yourself to a smaller section of categories, which you want to connect your articles to, will help you to stay more relevant to the topic of your choice. Creating a blog menu Once you have set up your categories, it's time to create your blog menu. Start with creating a new menu and call it whatever you want to, give it a title like The Garden Blog as in my example site. To set this feature go to your administrator panel and choose Menus | Main Menu from the menu bar at the top. After that choose New. Make it short and to the point so that it is really easy to find it on your site. Go to the Extensions menu, choose Module Manager, and Publish the module in the location you want it to show on your site. The first thing you should do is create a link to the section in which you are going to put your blog posts, and change the Parameters(Basic) to match the layout you want:   #Leading is set to 1, which means one full length article to start with   #Intro is set the 6, so you have the introduction text (that is the text before the "read more" link) from six articles, getting a total of seven on the blog page   Columns is set to 1 to get a complete overview of the articles in a listing that is not broken into two columns after the first Intro article   #Links this is the number of links with the title of older articles that don't show on the blog page anymore After setting the Parameters(Basic) you need to set the Parameters(Advanced) as well:   Change the Category Order to Order and the Primary Order to Most recent first.   Make sure you have the Show a Feed Link set to Yes—only for this menu item. This option is set so that we can get a full RSS Feed over all the blog categories For a blog, you need to change some of the settings in the Parameters(Component):     For a blog you need to Show the Author Name, the Created Date and Time, the Show Navigation, and the Read more... Link   The Article Rating/Voting depends on you, for me its set to off, as I don't like the dotted rating icons. The commenting system will give your visitors the ability to share their thoughts about your article, rather than just rate them, unlike the rating system. You will learn more about such a commenting system later in this article.
Read more
  • 0
  • 0
  • 1869

article-image-build-advanced-contact-manager-using-jboss-richfaces-33-part-3
Packt
18 Nov 2009
11 min read
Save for later

Build an Advanced Contact Manager using JBoss RichFaces 3.3: Part 3

Packt
18 Nov 2009
11 min read
  The ajaxSingle and the process attributes The ajaxSingle property is very useful to control the form submission when ajaxSingle is set to true—the form is not submitted and, just the Ajax component data is sent. This attribute is available in every Ajax action component and we can use it to call an action from a button, skipping the form validation (like the JSF immediate property does), or to send the value of just an input into a form without validation and submitting the other ones. The second use case can be used, for example, when we need an input menu that dynamically changes the value of other inputs without submitting the entire form: <h:form> <!-- other input controls --> <h:selectOneMenu id="country" value="#{myBean.selectedCountry}"> <f:selectItems value="#{myBean.myCountries}"> <a:support event="onchange" ajaxSingle="true" reRender="city" /> </h:selectOneMenu> <h:selectOneMenu id="city" value="#{myBean.selectedCity}"> <f:selectItems value="#{myBean.myCities}"> </h:selectOneMenu> <!-- other input controls --></h:form> In this example, every time the user selects a new country, the value is submitted to the bean that recalculates the myCities property for the new country, after that the city menu will be re-rendered to show the new cities. All that without submitting the form or blocking the changes because of some validation problem. What if you would like to send more than one value, but still not the entire form? We can use Ajax regions (we will see in the next sections), or we can use the process attribute. It contains a list of components to process while submitting the Ajax action: <h:form> <!-- other input controls --> <h:inputText id="input1" ... /> <h:selectOneMenu id="country" value="#{myBean.selectedCountry}"> <f:selectItems value="#{myBean.myCountries}"> <a:support event="onchange" ajaxSingle="true" process="input2, input3" reRender="city" /> </h:selectOneMenu> <h:inputText id="input2" ... /> <h:inputText id="input3" ... /> <h:selectOneMenu id="city" value="#{myBean.selectedCity}"> <f:selectItems value="#{myBean.myCities}"> </h:selectOneMenu> <!-- other input controls --></h:form> In this example, we also wanted to submit the input2 and the input3 values together with the new country, because they are useful for retrieving the new cities list—just by setting the process attribute with the id list and during the submission, they will be processed. Thus input1 will not be sent. Also, for action components such as buttons, you can decide what to send using the ajaxSingle and process attributes. Form submission and processingWe speak about form "submission" to simplify the concept and make things more understandable. In reality, for every request, all of the form is submitted, but only the selected components (using ajaxSingle and/or process attributes) will be "processed". By "processed" we mean "pass through" the JSF phases (decoding, conversion, validation, and model updating). More Ajax! For every contact, we would like to add more customizable fields, so let's use the ContactField entity connected to every Contact instance. First of all, let's create a support bean called HomeSelectedContactOtherFieldsHelper inside the book.richfaces.advcm.modules.main package. It might look like this: @Name("homeSelectedContactOtherFieldsHelper")@Scope(ScopeType.CONVERSATION)public class HomeSelectedContactOtherFieldsHelper { @In(create = true) EntityManager entityManager; @In(required = true) Contact loggedUser; @In FacesMessages facesMessages; @In(required = true) HomeSelectedContactHelper homeSelectedContactHelper; // my code} A notable thing is highlighted—we injected the homeSelectedContactHelper component, because to get the list of the customized fields from the database, we need the contact owner. We also set the required attribute to true, because this bean can't live without the existence of homeSelectedContactHelper in the context. Now, let's add the property containing the list of personalized fields for the selected contact: private List<ContactField> contactFieldsList;public List<ContactField> getContactFieldsList() { if (contactFieldsList == null) { // Getting the list of all the contact fields String query = "from ContactField cf where cf.contact.id=:idContactOwner order by cf.id"; contactFieldsList = (List<ContactField>) entityManager.createQuery(query) .setParameter("idContactOwner", homeSelectedContactHelper.getSelectedContact() .getId()).getResultList(); } return contactFieldsList;}public void setContactFieldsList(List<ContactField> contactFieldsList) { this.contactFieldsList = contactFieldsList;} As you can see, it is a normal property lazy initialized using the getter. This queries the database to retrieve the list of customized fields for the selected contact. We have to put into the bean some other method useful to manage the customized field (adding and deleting field to and from the database), let's add those methods: public void createNewContactFieldInstance() { // Adding the new instance as last field (for inserting a new field) getContactFieldsList().add(new ContactField());}public void persistNewContactField(ContactField field) { // Attaching the owner of the contact field.setContact(homeSelectedContactHelper.getSelectedContact()); entityManager.persist(field);}public void deleteContactField(ContactField field) { // If it is in the database, delete it if (isContactFieldManaged(field)) { entityManager.remove(field); } // Removing the field from the list getContactFieldsList().remove(field);}public boolean isContactFieldManaged(ContactField field) { return field != null && entityManager.contains(field);} The createNewContactFieldInstance() method will just add a new (not yet persisted), empty instance of the ContactField class into the list. After the user has filled the values in, he/she will press a button that calls the persistNewContactField() method to save the new data into the database. In order to delete it, we are going to use the deleteContactField() method, and to determine if an instance is persisted into the database or not, we are going to use the isContactFieldManaged() method. Now, let's open the /view/main/contactView.xhtml file and add the code to show the personalized fields after h:panelGrid— i shows the standard ones: <a:repeat value="#{homeSelectedContactOtherFieldsHelper.contactFieldsList}" var="field"> <h:panelGrid columns="2" rowClasses="prop" columnClasses="name,value"> <h:outputText value="#{field.type} (#{field.label}):"/> <h:outputText value="#{field.value}"/> </h:panelGrid></a:repeat> We are using a new RichFaces data iteration component that permits us to iterate over a collection and put the data we want (the rich:dataTable component would instead create a table for the elements list). In our case, the h:panelGrid block will be repeated for every element of the collection (so for every customized field). Now, let's open the /view/main/contactEdit.xhtml file and add the code for editing the customized fields into the list: <a:region> <a:outputPanel id="otherFieldsList"> <a:repeat value="#{homeSelectedContactOtherFieldsHelper. contactFieldsList}" var="field"> <h:panelGrid columns="3" rowClasses="prop" columnClasses="name,value,validatormsg"> <h:panelGroup> <h:inputText id="scOtherFieldType" value="#{field.type}" required="true" size="5"> <a:support event="onblur" ajaxSingle="true"/> </h:inputText> <h:outputText value=" ("/> <h:inputText id="scOtherFieldLabel" value="#{field.label}" size="5"> <a:support event="onblur" ajaxSingle="true"/> </h:inputText> <h:outputText value=")"/><br/> <rich:message for="scOtherFieldType" styleClass="messagesingle" errorClass="errormsg" infoClass="infomsg" warnClass="warnmsg"/> </h:panelGroup> <h:panelGroup> <h:inputText id="scOtherFieldValue" value="#{field.value}" required="true"> <a:support event="onblur" ajaxSingle="true"/> </h:inputText><br/> <rich:message for="scOtherFieldValue" styleClass="messagesingle" errorClass="errormsg" infoClass="infomsg" warnClass="warnmsg"/> </h:panelGroup> <h:panelGroup> <a:commandButton image="/img/add.png" reRender="otherFieldsList" action="#{homeSelectedContactOtherFieldsHelper. persistNewContactField(field)}" rendered="#{!homeSelectedContactOtherFieldsHelper. isContactFieldManaged(field)}"> </a:commandButton> <a:commandButton image="/img/remove.png" reRender="otherFieldsList" ajaxSingle="true" action="#{homeSelectedContactOtherFieldsHelper. deleteContactField(field)}"> </a:commandButton> </h:panelGroup> </h:panelGrid> </a:repeat> <a:commandLink reRender="otherFieldsList" ajaxSingle="true" action="#{homeSelectedContactOtherFieldsHelper. createNewContactFieldInstance}" rendered="#{homeSelectedContactHelper. selectedContactManaged}" styleClass="image-command-link"> <h:graphicImage value="/img/add.png"/> <h:outputText value="#{messages['addNewField']}"/> </a:commandLink> </a:outputPanel></a:region> The code looks very similar to the one in the view box, except for the action buttons (to add a new instance, persist, save, or delete) and, for the presence of the surrounding tag a:region (highlighted). This is very important in order to make sure the form works correctly; we will see why in the next section. Also, notice that every input component has the a:support tag as a child that will update the bean with the edited value at the onblur event (which means that every time you switch the focus to another component, the value of the last one is submitted). So, if you delete or add a field, you will now loose the edited values for other fields. It is also used for Ajax validation, as the user is informed that the value is not valid when it moves the cursor to another input. Here is a screenshot with the new feature in the edit box: Using a:support only for Ajax validation If you want to use the a:support tag only for validation purpose, remember to set its bypassUpdates attribute to true, so the process would be faster as the JSF Update Model and Invoke Application phases will not be invoked. Ajax containers While developing a web application with RichFaces, it's very useful to know how to use Ajax containers (such as the a:region component) in order to optimize Ajax requests. In this section, we'll discuss about the a:region component. It is a very important component of the framework—it can define Ajax areas to limit the part of the component tree to be processed during an Ajax request. Regions can be nested during an Ajax request and the closest one will be used. By setting to true the a:region attribute called regionRenderOnly, you can use this component to limit the elements' update—In this way, in fact, only the components inside the region can be updated. Another important attribute is selfRendered; setting this to true tells the framework to render the response basing on component tree without referring to the page code—it is faster, but all of the transient elements that are not saved in the tree (such as f:verbatim or HTML code written directly without using JSF components) will be lost at the first refresh, so you can't use them in this case. To summarize, it is very useful to control the rendering process and optimize it, in order to limit the elements of a form to send during an Ajax request without validation problems, to show different indicators for Ajax status. Example of using a:region: <h:form> <a:region> <h:inputText id="it1" value="#{aBean.text1}"> <a:support event="onkeyup" reRender="text1" /> </h:inputText> <h:inputText id="it2" value="#{aBean.text2}" /> </a:region> <h:inputText id="it3" value="#{aBean.text3}" /> <a:commandButton action="#{aBean.saveTexts}" reRender="text1,text2" /></h:form><h:outputText id="text1" value="#{aBean.text1}" /><h:outputText id="text2" value="#{aBean.text2}" /> In this example, while the user is typing in the text1 value of inputText, a:support sends an Ajax request containing only the it1 and it2 values of inputText. In this case, in fact, a:region limits the components sent by every Ajax request originated from inside the region. So, the Ajax request will only update aBean.text1 and aBean.text2. Wrapping only a component inside an Ajax region is the equivalent of using the ajaxSingle property set to true. If the user clicks on the a:commandButton aBean.text1, the aBean.text2 and aBean.text3 values will be updated by the Ajax request. Coming back to our application, as all the customized fields are inside the same form component, we surround each one with the a:region tag. In this way, the single field is submitted regardless of the other ones. For example, without using a:region, if the user empties the name input value and then tries to insert a new customized field, the process will fail because the name input is not validated. If we use the a:region component, the name field will not be processed and a new field will be inserted. Now that we know how to use the a:region tag, we can combine it with ajaxSingle and process in order to decide what to send at every request, and to better optimize Ajax interactions into the application.
Read more
  • 0
  • 0
  • 1402

article-image-event-delivery-network-oracle-soa-suite-11g-r1
Packt
18 Nov 2009
2 min read
Save for later

Event Delivery Network with Oracle SOA Suite 11g R1

Packt
18 Nov 2009
2 min read
Creating truly decoupled composite SOA applications requires a complete separation of the service consumer and the service provider.This is typically achieved through the use of asynchronous messaging.In an asynchronous messaging pattern, applications can perform in a"fire and forget" mode. This removes the need of an application to know details of the application on the other side. Additionally, it also improves resource utilization as applications are not holding onto resources until the interaction is complete. On the other hand, this introduces complexities of creating and managing message queues and topics. It requires that both the publisher of the message and the consumer use the same messaging technology. Each messaging system also has its own constraints on the types of programming languages and environments that can use the service. In a service-oriented world, this tight coupling to the implementation of the underlying messaging system is at odds with the fundamental requirement of implementation independence. What's needed is a level of abstraction that allows applications to generate an event using business terms and associate a business object in an implementation‑independent form. Oracle SOA Suite 11g addresses this with the introduction of anew feature in the form of the Event Delivery Network. Introducing events The Event Delivery Network (EDN) in Oracle SOA Suite 11g provides a declarative way to use a publish/subscribe model to generate and consume business events without worrying about the underlying message infrastructure. Developers only need to produce or consume events without having to deal with any particular messaging API like JMS, AQ, and MQ, and so on. Consuming an event means expressing an interest in the occurrence of a specific situation,while producing an event means advertising this occurrence. Using the same concepts that are used in Web Service Definition Language (WSDL), EDN uses an XML-based Event Definition Language, which allows you to define the event and its associated,strongly typed data. This definition is then registered with the SOA Infrastructure and is available to all composites to publish or subscribe.   SERVICES MESSAGING EDN WSDL:Standard service interface model JMS API:Application Programming Interface EDL:Event Definition Language XSD:Strong typing Handful of raw types XSD Business-oriented Developer-oriented Business-oriented Wealth of tools Mostly coding tools Fully declarative  
Read more
  • 0
  • 0
  • 2804
article-image-integrating-websphere-extreme-scale-data-grid-relational-database-part-1
Packt
18 Nov 2009
10 min read
Save for later

Integrating Websphere eXtreme Scale Data Grid with Relational Database: Part 1

Packt
18 Nov 2009
10 min read
As stated above there are three compelling reasons to integrate with a database backend. First, reporting tools do not have good data grid integration. Using CrystalReports and other reporting tools, don't work with data grids right now. Loading data from a data grid into a data warehouse with existing tools isn't possible either. The second reason we want to use a database with a data grid is when we have an extremely large data set. A data grid stores data in memory. Though much cheaper than in the past, system memory is still much more expensive than a typical magnetic hard disk. When dealing with extremely large data sets, we want to structure our data so that the most frequently used data is in the cache and less frequently used data is on the disk. The third compelling reason to use a database with a data grid is that our application may need to work with legacy applications that have been using relational databases for years. Our application may need to provide more data to them, or operate on data already in the legacy database in order to stay ahead of a processing load.In this article, we will explore some of the good and not-so-good uses of an in-memory data grid. We'll also look at integrating Websphere eXtreme Scale with relational databases. You're going where? Somewhere along the way, we all learned that software consists of algorithms and data. CPUs load instructions from our compiled algorithms, and those instructions operate on bits representing our data. The closer our data lives to the CPU, the faster our algorithm can use it. On the x86 CPU, the registers are the closest we can store data to the instructions executed by the CPU. CPU registers are also the smallest and most expensive data storage location. The amount of data storable in registers is fixed because the number and size of CPU registers is fixed. Typically, we don't directly interact with registers because their correct usage is important to our application performance. We let the compiler writers handle translating our algorithms into machine code. The machine code knows better than we do, and will use register storage far more effectively than we will most of the time. Less expensive, and about an order of magnitude slower, we have the Level 1 cache on a CPU (see below). The Level 1 cache holds significantly more data than the combined storage capacity of the CPU registers. Reading data from the Level 1 cache, and copying it to a register, is still very fast. The Level 1 cache on my laptop has two 32K instruction caches, and two 32K data caches. Still less expensive, and another order of magnitude slower, is the Level 2 cache. The Level 2 cache is typically much larger than Level 1 cache. I have 4MB of the Level 2 cache on my laptop. It still won't fit the contents of the Library of Congress into that 4MB, but that 4MB isn't a bad amount of data to keep near the CPU. Up another level, we come to the main system memory. Consumer level PCs come with 4GB RAM. A low-end server won't have any less than 8GB. At this point, we can safely store a large chunk of data, if not all of the data, used by an application. Once the application exits, its data is unloaded from the main memory, and all of the data is lost. In fact, once our data is evicted from any storage at or below this level, it is lost. Our data is ephemeral unless it is put onto some secondary storage. The unit of measurement for accessing data in a register, either Level 1 or 2 cache and main memory, is a nanosecond. Getting to secondary storage, we jump up an SI-prefix to a microsecond. Accessing data in the secondary storage cache is on the order of microseconds. If the data is not in cache, the access time is on the order of milliseconds. Accessing data on a hard drive platter is one million times slower than accessing that same data in main memory, and one billion times slower than accessing that data in a register. However, secondary storage is very cheap and holds millions of times more than primary storage. Data stored in secondary storage is durable. It doesn't disappear when the computer is reset after a crash. Our operation teams comfortably build secondary storage silos to store petabytes of data. We typically build our applications so the application server interacts with some relational database management system that sits in front of that storage silo. The network hop to communicate with the RDBMS is in the order of microseconds on a fast network, and milliseconds otherwise. Sharing data between applications has been done with the disk + network + database approach for a long time. It's become the traditional way to build applications. Load balancer in front, application servers or batch processes constantly communicating with a database to store data for the next process that needs it. As we see with computer architecture, we insert data where it fits. We squeeze it as close to the CPU as possible for better performance. If a data segment doesn't fit in one level, keep squeezing what fits into each higher storage level. That leaves us with a lot of unused memory and disk space in an application deployment. Storing data in the memory is preferable to storing it on a hard drive. Memory segmentation in a deployment has made it difficult to store useful amounts of data at a few milliseconds distance. We just use a massive, but slow, database instead. Where does an IMDG fit? We've used ObjectGrid to store all of our data so far. This diagram should look pretty familiar by now: Because we're only using the ObjectGrid APIs, our data is stored in-memory. It is not persisted to disk. If our ObjectGrid servers crash, then our data is in jeopardy (we haven't covered replication yet). One way to get our data into a persistent store is to mark up our classes with some ORM framework like JPA. We can use the JPA API to persist, update, and remove our objects from a database after we perform the same operations on them using the ObjectMap or Entity APIs. The onus is on the application developer to keep both cache and database in sync: If you take this approach, then all of the effort would be for naught. Websphere eXtreme Scale provides functionality to integrate with an ORM framework, or any data store, through Loaders. A Loader is a BackingMap plugin that tells ObjectGrid how to transform an object into the desired output form. Typically, we'll use a Loader with an ORM specification like JPA. Websphere eXtreme Scale comes with a few different Loaders out of the box, but we can always write our own. A Loader works in the background, transforming operations on objects into some output, whether it's file output or SQL queries. A Loader plugs into a BackingMap in an ObjectGrid server instance, or in a local ObjectGrid instance. A Loader does not plug into a client-side BackingMap, though we can override Loader settings on a client-side BackingMap. While the Loader runs in the background, we interact with an ObjectGrid instance. We use the ObjectMap API for objects with zero or simple relationships, and the Entity API for objects with more complex relationships. The Loader handles all of the details in transforming an object into something that can integrate with external data stores: Why is storing our data in a database so important? Haven't we seen how much faster Websphere eXtreme Scale is than an RDBMS? Shouldn't all of our data be stored in in-memory? An in-memory data grid is good for certain things. There are plenty of things that a traditional RDBMS is good at that any IMDG just doesn't support. An obvious issue is that memory is significantly more expensive than hard drives. 8GB of server grade memory costs thousands of dollars. 8GB of server grade disk space costs pennies. Even though the disk is slower than memory, we can store a lot more data on it. An IMDG shines where a sizeable portion of frequently-changing data can be cached so that all clients see the same data. The IMDG provides orders of magnitude with better latency, read, and write speeds than any RDBMS. But we need to be aware that, for large data sets, an entire data set may not fit in a typical IMDG. If we focus on the frequently-changing data that must be available to all clients, then using the IMDG makes sense. Imagine a deployment with 10 servers, each with 64GB of memory. Let's say that of the 64GB, we can use 50GB for ObjectGrid. For a 1TB data set, we can store 50% of it in cache. That's great! As the data set grows to 5TB, we can fit 10% in cache. That's not as good as 50%, but if it is the 10% of the data that is accessed most frequently, then we come out ahead. If that 10% of data has a lot of writes to it, then we come out ahead. Websphere eXtreme Scale gives us predictable, dynamic, and linear scalability. When our data set grows to 100TB, and the IMDG holds only 0.5% of the total data set, we can add more nodes to the IMDG and increase the total percentage of cacheable data (see below). It's important to note that this predictable scalability is immensely valuable. Predictable scalability makes capacity planning easier. It makes hardware procurement easier because you know what you need. Linear scalability provides a graceful way to grow a deployment as usage and data grow. You can rest easy knowing the limits of your application when it's using an IMDG. The IMDG also acts as a shock absorber in front of a database. We're going to explore some of the reasons why an IMDG makes a good shock absorber with the Loader functionality. There are plenty of other situations, some that we have already covered, where an IMDG is the correct tool for the job. There are also plenty of situations where an IMDG just doesn't fit. A traditional RDBMS has thousands of man-years of research, implementation tuning, and bug fixing already put into it. An RDBMS is well-understood and is easy to use in application development. There are standard APIs for interacting with them in almost any language: In-memory data grids don't have the supporting tools built around them that RDBMSs have. We can't plug CrystalReports into an ObjectGrid instance to get daily reports out of the data in the grid. Querying the grid is useful when we run simple queries, but fails when we need to run the query over the entire data set, or run a complex query. The query engine in Websphere eXtreme Scale is not as sophisticated as the query engine in an RDBMS. This also means the data we get from ad hoc queries is limited. Running ad hoc queries in the first place is more difficult. Even building an ad hoc query runner that interacts with an IMDG is of limited usefulness. An RDBMS is a wonderful cross-platform data store. Websphere eXtreme Scale is written in Java and only deals with Java objects. A simple way for an organization to share data between applications is in a plaintext database. We have standard APIs for database access in nearly every programming language. As long as we use the supported database driver and API, we will get the results as we expect, including ORM frameworks from other platforms like .NET and Rails. We could go on and on about why an RDBMS needs to be in place, but I think the point is clear. It's something we still need to make our software as useful as possible.
Read more
  • 0
  • 0
  • 2157

article-image-papervision3d-external-models-part-1
Packt
18 Nov 2009
22 min read
Save for later

Papervision3D External Models: Part 1

Packt
18 Nov 2009
22 min read
This article covers the following: Modeling for Papervision3D Preparing for loading models Creating and loading models using Autodesk 3ds Max Loading an animation from Autodesk 3ds Max Creating and loading models using SketchUp Creating and loading models using Blender Controlling loaded materials Let's start off by having a look at some general practices to keep in mind when modeling for Papervision3D. Modeling for Papervision3D In this section, we will discuss several techniques that relate to modeling for Papervision3D. As Papervision3D is commonly used for web-based projects, modeling requires a different mindset than modeling for an animated movie, visualization, or game. Most of the techniques discussed relate to improving performance. This section is especially useful for modelers who need to create models for Papervision3D. Papervision3D PreviewerPapervision3D Previewer is a small program that should be part of every modeller's toolbox. This tool comes in handy for testing purposes. It allows a modeler to render an exported model in Papervision3D, and it displays some statistics that show how the model performs. At the time of writing, this tool was not compatible with Papervision3D 2.1, which could result in small problems when loading external models.Papervision3D Previewer can be downloaded from http://code.google.com/p/mrdoob/wiki/pv3dpreviewer Keep your polygon count low Papervision3D is a cutting edge technology that brings 3D to the Flash Player. It does this at an amazing speed relative to the capabilities of the Flash player. However, performance of Papervision3D is just a fraction of the performance that can be achieved with hardware-accelerated engines such as used by console games. Even with hardware-accelerated games there is a limit to the number of polygons that can be rendered, meaning there is always a compromise between detail and performance. This counts even more for Papervision3D, so always try to model using as few polygons as possible. Papervision3D users often wonder what the maximum number of triangles is that the Flash player can handle. There is no generic answer to this question, as performance depends on more factors than just the number of triangles. On average, the total triangle count should be no more than 3000, which equals 1500 polygons (remember that one polygon is made of two triangles). Unlike most 3D modeling programs, Papervision3D is triangle based and not polygon based. Add polygons to resolve artifacts Although this seems to contradict the previous suggestion to keep your polygon count low, sometimes you need more polygons to get rid of texture distortion or to reduce z-sorting artifacts. z-sorting artifacts will often occur in areas where objects intersect or closely intersect each other. Subdividing polygons in those areas can make z-sorting more accurate. Often this needs to be done by creating new polygons for the intersecting triangles of approximately the same size. There are several approaches to prevent z-sorting problems. Depending on the object you're using, it can be very time consuming to tweak and find the optimal amount and location of polygons. The amount of polygons you add in order to solve the problem should still be kept as low as possible. Finding the optimal values for your model will often result in switching a lot between Papervision3D and the 3D modeling program. Keep your textures small Textures used in the 3D modeling tool can be exported along with the model to a format that is readable for Papervision3D. This is a valuable feature as the texture will automatically be loaded by Papervision3D. However, the image, which was defined in the 3D authoring tool, will be used exactly as provided by Papervision3D. If you choose a 1024 by 1024 pixels image as the texture, for example the wheels of a car, Papervision3D loads the entire image and draws it on the wheel of a car that appears on screen at a size of 50 by 50 pixels for example. There are several problems related to this: It's a waste of bandwidth to load such a large image. Loading any image takes time, which should be kept as short as possible. It's a waste of capacity. Papervision3D needs to resize the image from 1024 by 1024 pixels to an image, which will be, for example, maximal 50 by 50 pixels on screen. Always choose texture dimensions that make sense for the application using it, and keep in mind that they have to be power of two. This will enable mipmapping and smoothing, which come without extra performance costs. Use textures that Flash can read 3D modeling programs usually read a variety of image sources. Some even support reading Adobe Photoshop's native file-format PSD. Flash can load only GIF, JPG, or PNG files at run time. Therefore, stick to these formats in your model so that you do not have to convert the textures when the model needs to be exported to Papervision3D. Use UV maps If your model is made up of several objects and textures, it's a good idea to use UV mapping, which is the process of unwrapping the model and defining all its textures into one single image. This way we can speed up initial loading of an application by making one request from Flash to load this image instead of loading dozens of images. UV mapping can also be used to tile or reuse parts of the image. The more parts of the UV-mapped image you can reuse, the more bandwidth you'll save. Always try to keep your UV-mapped image as small as possible, just as with keeping your normal textures small. In case you have a lot of objects sharing the same UV map and you need a large canvas to unwrap the UV map, be aware of the fact that the maximum image size supported by Flash Player 9 is 2880x2880 pixels. With the benefits of power of two textures in mind, the maximum width and height is 2048x2048 pixels. Baking textures Baking textures is the process of integrating shadows, lighting, reflection, or entire 3D objects into a single image. Most 3D modeling tools support this. This contradicts what has been said about tiling images in UV maps, as baking results in images that usually can only be used once because of the baked information on the texture. However, it can increase the level of realism of your application, just like shading does, but without the loss of performance caused by calculating shading in real time. Never use them in combination with a tiling image, as repeated shading, for instance, will result in unnatural looking renders. Therefore, each texture needs to be unique, which will cause longer loading times before you can show a scene. Use recognizable names for objects and materials It is always a good convention to use recognizable names for all your objects. This counts for the classes, methods, and properties in your code, and also for the names of the 3D objects in your modeling tool. Always think twice before renaming an object that is used by an application. The application might use the name of an object as the identifier to do something with it—for example, making it clickable. When working in a team of modelers and programmers, you really need to make this clear to the modelers as changing the name of an object can easily break your application. Size and positioning Maintaining the same relative size for your modeled objects, as you would use for instantiating primitives in your scene, is a good convention. Although you could always adjust the scale property of a loaded 3D model, it is very convenient when both Papervision3D and your modeling tool use the same scale. Remember that Papervision3D doesn't have a metric system defining units of a certain value such as meters, yards, pixels, and so on. It just uses units. Another convention is to position your object or objects at the origin of the 3D space in the modeling tool. Especially when exporting a single object from a 3D modeling tool, it is really helpful if it is located at a position of 0 on all axes. This way you can position the 3D object in Papervision3D by using absolute values, without needing to take the offset into account. You can compare this with adding movie clips to your library in Flash. In most cases, it is pretty useful when the elements of a movie clip are centered on their registration point. Finding the balance between quality and performance For each project you should try to find the balance between lightweight modeling and quality. Because each project is different in requirements, scale, and quality, there is no rule that applies for all. Keep the tips mentioned in the previous sections in mind and try to be creative with them. If you see a way to optimize your model, then do not hesitate to use it. Before we have a look at how to create and export models for Papervision3D, we will create a basic application for this purpose. Creating a template class to load models In order to show an imported 3D model using Papervision3D, we will create a basic application. Based on the orbit example (code bundle-chapter 6, click the following link to download: http://www.packtpub.com/files/code/5722_Code.zip) we create the following class. Each time we load a new model we just have to alter the init() method. First, have a look at the following base code for this example: package { import flash.events.Event; import org.papervision3d.materials.WireframeMaterial; import org.papervision3d.materials.utils.MaterialsList; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.Cube; import org.papervision3d.view.BasicView; public class ExternalModelsExample extends BasicView { private var model:DisplayObject3D; private var rotX:Number = 0.1; private var rotY:Number = 0.1; private var camPitch:Number = 90; private var camYaw:Number = 270; private var easeOut:Number = 0.1; public function ExternalModelsExample() { stage.frameRate = 40; init(); startRendering(); } private function init():void { model = new Plane(); scene.addChild(model); } private function modelLoaded(e:FileLoadEvent):void { //To be added } override protected function onRenderTick(e:Event=null):void { var xDist:Number = mouseX - stage.stageWidth * 0.5; var yDist:Number = mouseY - stage.stageHeight * 0.5; camPitch += ((yDist * rotX) - camPitch + 90) * easeOut; camYaw += ((xDist * rotY) - camYaw + 270) * easeOut; camera.orbit(camPitch, camYaw); super.onRenderTick(); } }} We have created a new plane using a wireframe as its material. The plane is assigned to a class property named model, which is of the DisplayObject3D type. In fact, any external model is a do3D. No matter what type of model we load in the following examples, we can always assign it to the model property. The classes that we'll use for loading 3D models all inherit from DisplayObject3D. Now that we have created a default application, we are ready to create our first model in 3D Studio Max, export it, and then import it into Papervison3D. Creating models in Autodesk 3ds Max and loading them into Papervision3D Autodesk 3ds Max (also known as 3D Studio Max or 3ds Max) is one of the widely-known commercial 3D modeling and animation programs. This is a good authoring tool to start with, as it can save to two of the file formats Papervision3D can handle. These are: COLLADA (extension *.dae): An open source 3D file type, which is supported by Papervision3D. This is the most advanced format and has been supported since Papervision3D's first release. It also supports animations and is actually just a plain text XML file. 3D Studio (extension *.3ds): As the name suggests, this is one of the formats that 3ds Max natively supports. Generally speaking it is also one of the most common formats to save 3D models in. As of 3ds Max version 9, there is a built-in exporter plugin available that supports exporting to COLLADA. However, you should avoid using this, as at the time of writing, the models it exports are not suitable for Papervision3D. Don't have a license of 3ds Max and want to get along with the following examples? Go to www.autodesk.com to download a 30-day trial. Installing COLLADA Max An exporter that does support COLLADA files suitable for Papervision3D is called COLLADA Max. This is a free and open source exporter that works with all versions of 3ds Max 7 and higher. Installing this exporter is easy. Just follow the steps mentioned below: Make sure you have installed 3ds Max version 7 or higher. Go to http://sourceforge.net/projects/colladamaya/. Click on View all files and select the latest COLLADA Max version. (At the time of writing this is COLLADA Max NextGen 0.9.5, which is still in beta, but is the only version that works with 3ds Max 2010). Save the download somewhere on your computer. Run the installer. Click Next, until the installer confirms that the exporter is installed. Start 3ds Max and double check if we can export using the COLLADA or COLLADA NextGen filetype, as shown in the following screenshot: If the only COLLADA export option is Autodesk Collada, then something went wrong during the installation of COLLADA Max, as this is not the exporter that works with Papervision3D. Now that 3ds Max is configured correctly for exporting a file format that can be read by Papervision3D, we will have a look at how to create a basic textured model in 3ds Max and export it to Papervision3D. Creating the Utah teapot and export it for Papervision3D If you already know how to work with 3ds Max, this step is quite easy. All we need to do is create the Utah teapot, add UV mapping, add a material to it, and export it as COLLADA. However, if you are new to 3ds Max, the following steps needs to be clarified. First, we start 3ds Max and create a new scene. The creation of a new scene happens by default on startup. The Utah teapot is one of the objects that comes as a standard primitive in 3ds Max. This means you can select it from the default primitives menu and draw it in one of the viewports. Draw it in the top viewport so that the teapot will not appear rotated over one of its axes. Give it a Radius of 250 in the properties panel on the right, in order to make it match with the units that we'll use in Papervision3D. Position the teapot at the origin of the scene. You can do this by selecting it and changing the x, y, and z properties at the bottom of your screen. You would expect that you need to set all axes to 0, although this is not the case. In this respect, the teapot differs from other primitives in 3ds Max, as the pivot point is located at the bottom of the teapot. Therefore, we need to define a different value for the teapot on the z-axis. Setting it to approximately -175 is a good value. To map a material to the teapot, we need to define a UV map first. UV mapping is also known as UVW mapping. Some call it UV mapping and others call it UVW mapping. 3ds Max uses the term UVW mapping. While having the teapot still selected, go to modify and then select UVW Mapping from the modifier list. Select Shrink Wrap and click Fit in the Alignment section. This will create a UVW map for us. Open the material editor using keyboard shortcut m. Here we define the materials that we use in 3ds Max. Give the new material a name. Replace 01 – Default with a material name of your choice—for example, teapotMaterial. Provide a bitmap as the diffuse material. You can do this by clicking on the square button, at the right of the Diffuse value within Blinn Basic Parameters section. A new window called Material/Map Browser will open. Double-click Bitmap to load an external image. Select an image of your choice. We will use teapotMaterial.jpg The material editor will now update and show the selected material on an illustrative sphere. This is your newly-created material, which you need to drag on the created teapot. The teapot model can now be exported. Depending on the version of the installed COLLADA exporter, select COLLADA or COLLADA NextGen. Note that you should not export using Autodesk Collada, as this exporter doesn't work properly for Papervision3D. Give it a filename of your choice, for example teapot, and hit Save. The exporter window will pop up. The default settings are fine for exporting to Papervision3D, so click OK to save the file. Save the model in the default 3ds Max file format (.max) somewhere on your local disk, so we can use it later when discussing other ways to export this model to Papervision3D. The model that we have created and exported is now ready to be imported by Papervision3D. Let's take a look at how this works. Importing the Utah teapot into Papervision3D To work with the exported Utah teapot, we will use the ExternalModelsExample project that we created previously in this article. Browse to the folder inside your project where you have saved your document class. Create a new folder called assets and copy to this folder, the created COLLADA file along with the image used as the material of the teapot. The class used to load an external COLLADA file is called DAE, so let's import it. import org.papervision3d.objects.parsers.DAE; This type of class is also known as a parser, as it parses the model from a loaded file. When you have a closer look at the source files of Papervision3D and its model parsers, you will probably find out about the Collada class. This might be a little confusing as we use the DAE parser to load a COLLADA file and we do not use the Collada parser. Although you could use either, this article uses the DAE parser exclusively, as it is a more recent class, supporting more features such as animation. There is no feature that is supported by the Collada parser, and is not supported by the DAE parser. Replace all code inside the init() method with the following code that loads a COLLADA file: model = new DAE();model.addEventListener(FileLoadEvent.LOAD_COMPLETE,modelLoaded);DAE(model).load("assets/teapot.DAE"); Because model is defined as a DisplayObject3D class type, we need to cast it to DAE to make use of its methods so that we can call the load() method. An event listener is defined, waiting for the model to be completely loaded and parsed. Once it is loaded, the modelLoaded() method will be triggered. It is a good convention to add models only to the scene once the model is completely loaded. Add the following line of code to the modelLoaded() method: scene.addChild(model); COLLADA Utah Teapot Example Publishing this code will result in the teapot with the texture as created in 3ds Max. In real-world applications it is good practice to keep your models in one folder and your textures in another. You might want to organize the files similar to the following structure: Models in /assets/models/ Textures in /assets/textures/ By default, textures are loaded from the same folder as the model is loaded from, or optionally from the location as specified in the COLLADA file. To include the /assets/textures/ folder we can add a file search path, which defines to have a look in the specified folder, to see if the file is located there, in case none can be found on the default paths. This can be defined as follows: daeModel.addFileSearchPath("assets/textures"); You can call this method multiple times, in order to have multiple folders defined. Internally, in Papervision3D, it will loop through an array of file paths. Exporting and importing the Utah teapot in 3ds format Now that we have seen how to get an object from 3ds Max into a Papervision3D project, we have a look at another format that is supported by both 3ds Max and Papervision3D. This format is called 3D Studio, using a 3ds extension. It is one of the established 3D file formats that are supported by most 3D modeling tools. Exporting and importing is very similar to COLLADA. Let's first export the file to the 3D Studio format. Open the Utah teapot, which we've modeled earlier in this article. Leave the model as it is, and go straight to export. This time we select 3D Studio (*.3DS) as the file type. Save it into your project folder and name it teapot. Click OK when asked whether to preserve Max's texture coordinates. If your model uses teapotMaterial.jpg, or an image with more than eight characters in its filename, the exporter will output a warning. You can close this warning, but you need to be aware of the output message. It says that the bitmap filename is a non-8.3 filename, that is, a maximum amount of 8 characters for the filename and a 3-character extension. The 3D Studio file is an old format, released at the time when there was a DOS version of 3ds Max. Back then it was an OS naming convention to use short filenames, known as 8.3 filenames. This convention still applies to the 3D Studio format, for the sake of backward compatibility. Therefore, the reference to the bitmap has been renamed inside the exported 3D Studio file. Because the exported 3D Studio file changed only the reference to the bitmap filename internally and it did not affect the file it refers to, we need to create a file using this renamed file reference. Otherwise, it won't be able to find the image. In this case we need to create a version of the image called teapotMa.jpg. Save this file in the same folder as the exported 3D Studio file. As you can see, it is very easy to export a model from 3ds Max to a format Papervision3D can read. Modeling the 3D object is definitely the hardest and most time consuming part, simply because creating models takes a lot of time. Loading the model into Papervision3D is just as easy as exporting it. First, copy the 3D Studio file plus the renamed image to the assets folder of your project. We can then alter the document class in order to load the 3ds file. The class that is used to parse a 3D Studio file is called Max3DS and needs to be imported. import org.papervision3d.objects.parsers.Max3DS; In the init() method you should replace or comment the code that loads the COLLADA model from our previous example, with the following: model = new Max3DS();model.addEventListener(FileLoadEvent.LOAD_COMPLETE,modelLoaded);Max3DS(model).load("assets/teapot.3ds", null, "./assets/"); As the first parameter of the load method, we pass a file reference to the model we want to load. The second parameter defines a materials list, which we will not use for this example. The third and final parameter defines the texture folder. This folder is relative to the location of the published SWF. Note that this works slightly different than the DAE parser, which loads referenced images from the path relative to the folder in which the COLLADA file is located or loads images as specified by the addFileSearchPath() method. ExternalModelsExample Publish the code and you'll see the same teapot. However, this time it's using the 3D Studio file format as its source. Importing animated models The teapot is a static model that we exported from a 3D program and loaded into Papervision3D. It is also possible to load animated models, which contain one or multiple animations. 3ds Max is one of the programs in which you can create an animation for use in Papervision3D. Animating doesn't require any additional steps. You can just create the animation and export it. This also goes for other modeling tools that support exporting animations to COLLADA. For the sake of simplicity, this example will make use of a model that is already animated in 3ds Max. The model contains two animations, which together make up one long animation on a shared timeline. We will export this model and its animation to COLLADA, load it into Papervision3D, and play the two animations. Open animatedMill.max in 3ds Max. This file can be found in the zip file that can be downloaded from: http://www.packtpub.com/files/code/5722_Code.zip. You can see the animation of the model directly in 3ds Max by clicking the play button in the menu at the bottom right corner, which will animate the blades of the mill. The first 180 frames animate the blades from left to right. Frames 181 to 360 animate the blades from right to left. As the model is already animated, we can go ahead with exporting, without making any changes to the model. Export it using the COLLADA filetype and save it somewhere on your computer. When the COLLADA Max exporter settings window pops up, we need to check the Sample animation checkbox. By default Start and End are set to the length of the timeline as it is defined in 3ds Max. In case you just want to export a part of it, you can define the start and end frames you want to export. For this example we leave them as they are: 0 and 360. By completing these steps you have successfully exported an animation in the COLLADA format for Papervision3D. Now, have a look at how we can load the animated model into Papervision3D. First, you need to copy the exported COLLADA and the applied material—Blades.jpg, House.jpg, and Stand.jpg—to the assets folder of your project. To load an animated COLLADA, we can use the DAE class again. We only need to define some parameters at instantiation, so the animation will loop. model = new DAE(true,null,true);model.addEventListener(FileLoadEvent.LOAD_COMPLETE,modelLoaded);DAE(model).load("assets/animatedMill.dae"); Take a look at what these parameters stand for.
Read more
  • 0
  • 0
  • 3013

article-image-most-wanted-apache-myfaces-trinidad-12-tags-and-tag-attributes
Packt
18 Nov 2009
6 min read
Save for later

Most Wanted Apache MyFaces Trinidad 1.2 Tags and Tag Attributes

Packt
18 Nov 2009
6 min read
Component library structure Trinidad's approach to web technology is comprehensive: Aimed at full control of all the bits and pieces that make up a web application, little should be left that needs to be added. So based on such a closed world, Trinidad presents itself with a wealth of components and tags that even include very basic XHTML tags as replacements for the real XHTML originals. This is no radical replacement approach, rather it enables Trinidad to remain in full control of mechanisms such as partial-page rendering (PPR, also generally known as Ajax) that otherwise would need to deal with potentially incompatible libraries externally. The following image provides an outline of Trinidad's structural package design: Trinidad is divided into the following two namespaces: tr: It is the usual tag library id that references Trinidad's core library tags. It's a large library of over 100 components ranging from layout components and navigational components, to special viewer components that all implicitly support skinning, partial-page rendering, popup dialogs, error or info messaging, and so on. trh: It is the usual tag library id that references Trinidad's XHTML support library tags, a small companion that offers alternatives for those XHTML tags that are usually applied to build XHTML structures, for example, XHTML tables. Let us take a closer look at both namespaces. The upcoming image shows the core API's hierarchical structure. The tags are backed by two types of Trinidad classes—UIX* classes that deal with the JSF component requirements to implement specific JSF lifecycle processing methods, and Core* classes that deal with the specific properties (getters or setters). Trinidad’s XHTML tag library namespace (trh) Two groups can be distinguished from the trh namespace. The first one deals with the definition of an XHTML page and provides the developer with the following tags: <trh:html>: It is used to define the whole XHTML page, analogous to <html> <trh:head>: It is used to define the header, analogous to <head> <trh:body>: It is used to define the main contents, analogous to <body> <trh:script>: It is used to define a JavaScript to be executed, analogous to <script> <trh:tableLayout>: It is used to define an XHTML table. <trh:rowLayout>: It is used to define an XHTML table line, analogous to <tr>; note that it can also be used to display an arbitrary line, particularly when elements need to be kept in one and the same line. Alternatively, it is particularly interesting to look at the tr namespace as it provides some less heavy structures free from table constructions, for instance panelGroupLayout with a layout set to vertical or a panelBorderLayout, both generating div structures instead. <trh:cellFormat>: It is used to define an XHTML table cell as part of an XHTML table. The attributes of each tag are defined in a most consistent, and thus recognizable way. By the way, there are also tags for the construction of framesets such as trh:frame in case anyone still wants to make use of framesets. However, before we deal with the attributes let us conclude this structural overview by a look at the organization of the functionality of the core tag library. Trinidad’s core tag library namespace (tr) The following groups can be functionally distinguished which is also reflected in the packages structure of Trinidad's API (all beginning with org.apache.myfaces.trinidad.component; which has been left out here to avoid repetition). Note that, for completeness, we will also include information on the pure Java side as well as information on the few components that stem from the trh namespace: Basic document composition tags from the core API: document, stylesheet, form, subform. poll also appears here although it is not a composition tag. Form input and display tags, components from the core.input API: inputText, inputDate, inputListOfValues, and so on. Command or navigation tags from core.nav that includes two tag types: One that is focused on command tags that assumes a given form, presupposing the use of form and display tags from the foregoing group—commandButton, commandLink, goButton, goLink, and so on. The other deals exclusively with navigation: navigationTree, navigationPane, breadCrumbs, and so on. Large input and output component tags from core.data, for example, table, tree, and treeTable components. Layout component tags from core.layout, for example, all the swing-like panel tags, such as panelBorderLayout, panelHorizontalLayout, panelAccordion, showDetail, showDetailItem, and so on. Basic output components from core.output that are almost always used in a web application, for example, messages, outputText, outputLabel, spacer, statusIndicator, and so on. Model objects from core.model devised for various tags ; they provide the corresponding view models for their tag viewer counterparts, for example, SortableModel, CollectionModel and RowKeySet for tr:table, ChildPropertyTreeModel for tr:tree and ChartModel for tr:chart. A couple of converter components from trinidad.convert equip JSF and Trinidad input components with powerful JSF conversion, that is, convertNumber and convertDateTime. Validator components from trinidad.validator equip JSF and Trinidad input components with powerful JSF validation such as range validation (validateDateTimeRange) and validation by regular expression match (validateRegExp). Events and event listeners from trinidad.event add new event types and listeners specific for Trinidad components such as those that support Trinidad's dialog framework, for example, commandButton to launch a popup dialogue using LaunchEvent, ReturnEvent, and ReturnListener. It provides only a few tags, but these can be very utile, for example, fileDownloadActionListener, resetActionListener, returnActionListener, and setActionListener. There is a lot more to be found on the pure Java API side that either surfaces indirectly on the tag library as attributes, or is used implicitly by the tags themselves. Furthermore, there are utility classes and context support classes—RequestContext being probably the most prominent one because it offers a lot of functionality, for example, PPR from the server side. The following figure illustrates the Java side of things (it shows what the structure of some of the classes behind core.input look like): The preceding figure is an outline of the core.input API hierarchy. Again, we can see the typical UIX* and Core* structure. Finally, let us take a closer look at the tag attributes.
Read more
  • 0
  • 0
  • 1913
article-image-restful-web-service-implementation-resteasy
Packt
18 Nov 2009
2 min read
Save for later

RESTful Web Service Implementation with RESTEasy

Packt
18 Nov 2009
2 min read
Getting the tools If you have already downloaded and installed Java's JDK and the Tomcat web server, you only need to download the JBoss's RESTEasy framework. Nevertheless, the complete list of the software needed for this article is as follows: Software Web Location Java JDK http://java.sun.com/ Apache Tomcat http://tomcat.apache.org/download-60.cgi Db4o http://developer.db4o.com/files/default.aspx RESTEasy Framework http://www.jboss.org/resteasy/ Install the latest Java JDK along with the latest version of Tomcat, if you haven't done so. Download and install Db4o and RESTEasy. Remember the location of the installs, as we'll need the libraries to deploy with the web application. RESTEasy — a JAX-RS implementation   RESTEasy is a full open source implementation of the JAX-RS specification. This framework works within any Java Servlet container, but because it's developed by JBoss, it offers extra features that are not part of the JAX-RS requirements. For example, RESTEasy offers out-of-the-box Atom support and also offers seamless integration with the EJB container portion of JBoss (none of these features are explored here). Web service architecture By now, you should be familiar with the coding pattern. Because we want to reuse a large portion of code already written, we have separate layers of abstraction. In this article, therefore, we only talk about the web layer and study in detail how to implement a full RESTful web service using RESTEasy. The full architecture of our web service looks as follows: In this diagram, we depict clients making HTTP requests to our web service. Each request comes to the web container, which then delegates the request to our RESTful layer that is composed of RESTEasy resource classes. The actual serialization of user and message records is delegated to our business layer, which in turns talks directly to our database layer (a Db4o database). Again, RESTEasy is a platform independent framework and works within any Servlet container. For this article we deploy our web service in Tomcat, as we've been working with it so far and are now familiar with deploying web applications to it, though we could as easily use the JBoss web container.
Read more
  • 0
  • 0
  • 3825

article-image-keeping-extensions-secure-joomla-15-part-1
Packt
18 Nov 2009
7 min read
Save for later

Keeping Extensions Secure with Joomla! 1.5: Part 1

Packt
18 Nov 2009
7 min read
Introduction There's no such thing as a completely secure system. No matter how many precautions we take and how many times we verify our design and implementation, we will never be able to guarantee that we have created a truly secure Joomla! extension. Why not? This is because it is not possible to be prepared for every potential vulnerability. Common Weakness Enumeration (CWE) is a project dedicated to generating a formal categorization and identification system of security vulnerabilities. CWE published a list of the top 25 security weaknesses, which were selected on the basis of their frequency and consequences. This list includes some of the most publicized security weaknesses, such as code injection (CWE-94) and XSS (CWE-79). When considering the security of our extensions, this list can prove useful. For information about common programming mistakes that lead to security vulnerabilities, refer to http://cwe.mitre.org/top25/. This article includes references to the CWE weaknesses. These references are in the form of CWE IDs, that is, CWE-n. For information about a weakness, simply Search By ID on the CWE web site. These references are intended to help us better understand the weaknesses, the risks associated with the weaknesses, how the risks can be reduced using the Joomla! framework, and the suggested CWE mitigations. Something we should consider is the ramifications of security flaws. Whichever way we look at this, the answer always involves financial loss. This is true even of non-profit organizations. If a web site is attacked and the attacker managed to completely obliterate all the data held on that web site, it will cost the owner's time to restore a backup or replace the data. OK, it may not seem like a financial loss because it's non profit. It is a wastage of time if the web site owner spends two hours to restore his or her data, as those two hours could have been used elsewhere. For commercial web sites, the potential for financial loss is far more obvious. If we use a bank as an example, a security flaw could enable an attacker to transfer money from the bank to his or her own (probably untraceable) account. In 2004, the Internet bank Cahoot suffered a security flaw enabling any existing customer access to other customers' accounts. Cahoot did not suffer any obvious financial loss from the security flaw and they claimed there was no risk of financial loss. However, the customers' confidence in Cahoot was inevitably lost. This loss of confidence and bad press will certainly have affected Cahoot in some way. For example, some potential customers may have decided to open an account with a rival bank because of concerns over how secure their savings would, or would not, be with Cahoot. For more information, refer to http://news.bbc.co.uk/1/hi/business/3984845.stm. From the perspective of an extension developer, we should reflect on our moral duty and our liability. Disclaimers, especially for commercial software, do not relinquish us of legal responsibility. We should always try to avoid any form of litigation, and I'm not suggesting that we run to Mexico or our closest safe haven. We should take a holistic approach to security. We need a complete view of how the system works and of the various elements that need to be secure. Security should be built into our extension from the requirements gathering stage through to the ongoing system maintenance. How we do that depends on how we are managing our project and what the security implications of our extension are. For example, a shopping cart component with credit card processing facilities will require far greater attention to security than a content plugin that converts the occurrences of :) to smiley face images. Irrespective of the way we choose to manage the risks of weaknesses, we should always document how we are circumventing security threats. Doing so will make it easier to maintain our extension without introducing vulnerabilities. Documentation also provides us with proof of prudent risk management, which can be useful should we ever be accused of failing to adequately manage the security risks associated with our software. This is all starting to sound like a lot of work! This brings us back to the ramifications of vulnerabilities. If on the one hand, it costs us one extra month of development time to produce a piece of near-secure software. And on the other hand, it costs us two months to patch a non-secure piece of software and an incalculable amount of damage to our reputation. It is clear which route we should favor! Packt Publishing offers a book that deals specifically with Joomla! security. For more information, refer to http://www.packtpub.com/joomla-web-security-guide/. Writing SQL safe queries SQL injection is probably the most high profile of all malicious web attacks. The effects of an SQL injection attack can be devastating and wide ranging. Whereas some of the more strategic attacks may simply be aimed at gaining access, others may intend on bringing about total disruption and even destruction. Some of the most prestigious organizations in the world have found themselves dealing with the effects of SQL injection attacks. For example, in August 2007 the United Nations web site was defaced as a result of an SQL injection vulnerability. More information can be found at http://news.bbc.co.uk/1/hi/technology/6943385.stm. Dealing with the effects of an SQL injection attack is one thing, but preventing them is quite another. This recipe explains how we can ensure that our queries are safe from attack by utilizing the Joomla! framework. For more information about SQL injection, refer to CWE-89. Getting ready The first thing we need is the database handler. There is nothing special here, just the usual Joomla! code as follows: $db =& JFactory::getDBO(); How to do it... There are two aspects of a query that require special attention: Identifiers and names Literal values The JDatabase::nameQuote() method is used to safely represent identifiers and names. We will start with an easy example, a name that consists of a single identifier. $name = $db->nameQuote('columnIdentifier'); We must take care when dealing with multiple-part names (that is, names that include more than one identifier separated by a period). If we attempt to do the same thing with the name tableIdentifier.columnIdentifier, we won't get the expected result! Instead, we would have to do the following: // prepare identifiers$tableIdentifier = $db->nameQuote('tableIdentifier');$columnIdentifier = $db->nameQuote('columnIdentifier');// create name$name = "$tableIdentifier.$columnIdentifier"; Avoid hardcoding encapsulation Instead of using the JDatabase::nameQuote() method, it can be tempting to do this: $sql = 'SELECT * FROM `#__foobar_groups` AS `group`'. This is OK as it works. But the query is now tightly coupled with the database system, making it difficult to employ an alternative database system. Now we will take a look at how to deal with literal values. Let's start with strings. In MySQL, strings are encapsulated in double or single quotes. This makes the process of dealing with strings seem extremely simple. Unfortunately, this would be an oversight. Strings can contain any character, including the type of quotes we use to encapsulate them. Therefore, it is also necessary to escape strings. We do all of this using the JDatabase::Quote() method as follows: $tableIdentifier = $db->nameQuote('tableIdentifier');$columnIdentifier = $db->nameQuote('columnIdentifier');$sql = "SELECT * FROM $tableIdentifier " . "WHERE $columnIdentifier " . ' = ' . $db->Quote("How's the recipebook going?"); The JDatabase::Quote() method essentially does the following. The exact output will depend on the database handler. However, most databases escape and encapsulate strings in pretty much the same way.   Original Quoted How's the recipebook going? 'How's the recipebook going?'
Read more
  • 0
  • 0
  • 1451
Modal Close icon
Modal Close icon