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-digitally-signing-and-verifying-messages-web-services-part-2
Packt
22 Oct 2009
4 min read
Save for later

Digitally Signing and Verifying Messages in Web Services ( part 2 )

Packt
22 Oct 2009
4 min read
Signature Verification by Oracle WSM Oracle Web Services Manager can actually validate the signature in the incoming i.e. request SOAP message. By using Oracle WSM to validate the signature, organizations can actually centralize the policy enforcement and also the public key management. As organizations deploy more web services that are accessed by other divisions and business partners, managing the signature verification process might become tedious, as with each new consumer, the certificate information should be maintained. Oracle WSM can address such issues by centralizing those operations. This section  will describe how to configure Oracle WSM policy to validate the signature of the SOAP request message. In order to view the policy, you can click on Policy Management and then Manage Policies. This will bring you to the screen with the gateway information and a hyperlink for policies (see the following screen capture).   You can then click on Policies to see all the policies and you will see theVerifyAndSign policy too that is created by default. A default policy is attached to the service. We can now click Edit to edit the  policy. When you click Edit, you will see the policy steps as shown in the  following screenshot. In this section, we want to configure the Request pipeline to validate the signature of the incoming SOAP message. In order to validate the signature, click Add Step Below to add the Verify Signature policy step as shown in the following screenshot. Once you click OK, the verify signature policy step is added, but that policy step should be configured. If you click on the Configure button on the verify signature policy step, it will take you to the screen where you can configure the verify signature policy information as shown in the following screen capture. In the previous screenshot, I configured Verify Signature policy steps with: Location of the key store Key store type as PKCS12 Password of the key store Public key alias in the key store Set Remove Signatures to true to remove the digital signature after the signature validation Enforce Signing is set to true to make sure that the incoming requests are signed In order to generate a PKCS12 key store from certifcate that is installed already in Microsoft certifcate services, you should frst export the certifcate (with or without private key) and then import that certifcate in FireFox (Advanced option) and then export back to PKCS12. Once the verify signature policy has been configured and saved (Commit Policy), the policy would enforce that any request for the time service with the particular service ID be digitally signed. Signature Generation by Oracle WSM In the last section, we discussed how to digitally sign a web service request by Microsoft .NET application and how to validate the signature by Oracle WSM. In this section, we will discuss how to digitally sign the web service response message. In the earlier section, we discussed how to register the service and how to attach the verify signature policy step to the request pipeline. In order to digitally sign the response message, the response pipeline of the policy should be modified to include the sign message policy step. The policy with the request pipeline that is already configured to verify signature would look like: Now we have to add the step in the Response pipeline to actually sign the response message. In order to add the policy step, click on Add Step Below and then select the Sign Message policy step. Once the Sign Message policy step is added, it can then be configured, as shown in the following screenshot, to include the appropriate key store location for the public key to digitally sign the message. In the previous figure, the location of the key store that has the private key, along with the Keystore password, alias and part of message to be signed are specified. Once the policy is created, it would look like: In the previous screenshot, the Response pipeline has two log steps—one to log the message before digitally signing and one to log the message after digitally signing the message. In this sample, we are using the same WSEQuickStartServer certificate to sign the message. Once the policy is saved, the response message will be digitally signed. The client application (Microsoft .NET) can be configured to validate the signature.
Read more
  • 0
  • 0
  • 1866

article-image-testing-help-system-java-application
Packt
22 Oct 2009
6 min read
Save for later

Testing a HELP System in a Java Application

Packt
22 Oct 2009
6 min read
Introduction {literal}As more and more features get added to your software, the Help system for the software becomes extensive. It could probably contains hundreds of HTML files plus a similar number of images. We could always face the problems listed below. There could be broken links in the help index. Some files may not be listed in the index, therefore they can not be read by the customers. Some of the contextual help buttons could show the wrong topic. Some of the HTML files can contain broken links or incorrect image tags. Not all of the file titles would match their index entry. Another problem could occur when the user does a free text search of the help system. The result of such a search is a list of files, each represented by its title. In our system,  documents could have the title "untitled". In fact, the JavaHelp 2.0 System User's Guide contains the recommendation "To avoid confusion, ensure that the <TITLE> tag corresponds to the title used in the table of contents." Given that customers mostly use the Help system when they are already frustrated by our software, we should always see to it that such errors do not exist in our help system. To do this, we will write a tool, HelpGenerator, that generates some of the boilerplate XML in the help system and checks the HTML and index files for the problems listed above. We will also build tools for displaying and testing the contextual help. We've re-engineered and improved these tools and present them in this article. In this article we are assuming familiarity with the JavaHelp system. Documentation and sample code for JavaHelp can be found at: http://java.sun.com/products/javahelp. Overview A JavaHelp package consists of: A collection of HTML and image files containing the specific Help information to be displayed. A file defining the index of the Help topics. Each index item in the file consists of the text of the index entry and a string representing the target of the HTML file to be displayed for that index entry, for example: <index version="1.0"> <indexitem text="This is an example topic."target="Topic"> <indexitem text="This is an sub-topic."target="SubTopic"/> </indexitem></index> A file associating each target with its corresponding HTML file (or more generally, a URL)—the map file. Each map entry consists of the target name and the URL it is mapped to, for example: <map version="1.0"> <mapID target="Topic" url="Topic.html"/> <mapID target="SubTopic" url="SubTopic.html"/></map> A HelpSet file (by default HelpSet.hs) which specifies the names of the index and map files and the folder containing the search database. Our software will normally have a main menu item to activate the Help and, in addition, buttons or menu items on specific dialogs to activate a Help page for a particular topic, that is, "context-sensitive" Help. What Tests Do We Need?? At an overall structural level, we need to check: For each target referred to in the index file, is there a corresponding entry in the map file? In the previous example, the index file refers to targets called Topic and SubTopic. Are there entries for these targets in the map file? For each URL referred to in the map file, is that URL reachable? In the example above, do the files Topic.html and SubTopic.html exist? Are there HTML files in our help package which are never referred to? If a Help button or menu item on some dialog or window is activated, does the Help facility show the expected topic? If the Help search facility has been activated, do the expected search results show? That is, has the search database been built on the latest versions of our Help pages? At a lower level, we need to check the contents of each of the HTML files: Do the image tags in the files really point to images in our help system? Are there any broken links? Finally, we need to check that the contents of the files and the indexes are consistent Does the title of each help page match its index? To simplify these tests, we will follow a simple naming pattern as follows: We adopt the convention that the name of each HTML file should be in CamelCase format (conventional Java class name format) plus the .html extension. Also, we use this name, without the extension, as the target name. For example, the target named SubTopic will correspond to the file SubTopic.html. Furthermore, we assume that there is a single Java package containing all the required help files, namely, the HTML files, the image files, the index file, and the map file. Finally, we assume a fixed location for the Help search database. With this convention, we can now write a program that: Generates the list of available targets from the names of the HTML files. Checks that this list is consistent with the targets referred to in the index file. Checks that the index file is well-formed in that: It is a valid XML document. It has no blank index entries. It has no duplicate index entries. Each index entry refers to a unique target. Generates the map file, thereby guaranteeing that it will be consistent with the index file and the HTML files. The class HelpGenerator in the package jet.testtools.help does all this,and, if there are no inconsistencies found, it generates the map file. If an inconsistency or other error is found, an assertion will be raised. HelpGenerator also performs the consistency checks at the level of individual HTML files. Let's look at some examples. An HTML File That is Not Indexed Here is a simple help system with just three HTML files: The index file, HelpIndex.xml, only lists two of the HTML files: <index version="1.0"> <indexitem text="This is an example topic." target="ExampleTopic"> <indexitem text="This is an example sub-topic." target="ExampleSubTopic"/> </indexitem></index> When we run HelpGenerator over this system (we'll see how to do this later in this article), we get an assertion with the error messageThe Help file: TopicWithoutTarget.html was not referenced in the Index file: HelpIndex.xml.
Read more
  • 0
  • 0
  • 2795

article-image-deploying-your-dotnetnuke-portal
Packt
21 Oct 2009
7 min read
Save for later

Deploying Your DotNetNuke Portal

Packt
21 Oct 2009
7 min read
Acquiring a Domain Name One of the most exciting parts of starting a website is acquiring a domain name. When selecting the perfect name there are a few things that you need to keep in mind: Keep it brief: The more letters that a user has to type in to get to your site the more difficult it is going to be for them to remember your site. The name you select will help to brand your site. If it is catchy then people will remember it more readily. Have alternative names in mind: As time goes on, great domain names are becoming fewer and fewer. Make sure you have a few alternatives to choose from. The first domain name you had in mind may already be taken so having a backup plan will help when you decide to purchase a name. Consider buying additional top-level domain names: Say you've already bought www.DanielsDoughnuts.com. You might want to purchase www.DanielsDoughnuts.net as well to protect your name. Once you have decided on the name you want for your domain, you will need to register it. There are dozens of different sites that allow you to register your domain name as well as search to see if it is available. Some of the better-known domain-registration sites are Register.com and NetworkSolutions.com. Both of these have been around a long time and have good reputations. You can also look into some of the discount registers like BulkRegister (http://www.BulkRegister.com) or Enom (http://www.enom.com). After deciding on your domain name and having it registered, you will need to find a place to physically host your portal. Most registration services will also give the ability to host your site with them but it is best to search for a provider that fits your site's needs. Finding a Hosting Provider When deciding on a provider to host your portal, you will need to consider a few things: Cost: This is of course one of the most important things to look at when looking for a provider. There are usually a few plans to select from. The basic plan usually allows you a certain amount of disk space for a very small price but has you share the server with numerous other websites. Most providers also offer dedicated (you get the server all to yourself) and semi-dedicated (you share with a few others). It is usually best to start with the basic plan and move up if the traffic on your site requires it. Windows servers: The provider you select needs to have Windows Server 200/2003 running IIS (Internet Information Services). Some hosts run alternatives to Microsoft like Linux and Apache web server. .NET framework: The provider's servers need to have the .NET framework version 1.1 installed. Most hosts have installed the framework on their servers, but not all. Make sure this is available because DotNetNuke needs this to run. Database availability: You will need database server availability to run DotNetNuke and Microsoft SQL Server is the preferred back-end. It is possible to run your site off Microsoft Access or MySQL (with a purchased provider), but I would not suggest it. Access does not hold up well in a multi-user platform and will slow down considerably when your traffic increases. Also, since most module developers target MS SQL, MySQL, while able to handle multiple users, does not have the module support. FTP access: You will need a way to post your DotNetNuke portal files to your site and the easiest way is to use FTP. Make sure that your host provides this option. E-mail server: A great deal of functionality associated with the DotNetNuke portal relies on being able to send out e-mails to users. Make sure that you will have the availability of an e-mail server. Folder rights: The ASPNET or NetworkService Account (depending on server) will need to have full permissions to the root and subfolders for your DotNetNuke application to run correctly. Make sure that your host either provides you with the ability to set this or is willing to set this up for you. We will discuss the exact steps later in this article. The good news is that you will have plenty of hosting providers to choose from and it should not break the bank. Try to find one that fits all of your needs. There are even some hosts (www.WebHost4life.com) that will install DotNetNuke for you free of charge. They host many DotNetNuke sites and are familiar with the needs of the portal. Preparing Your Local Site Once you have your domain name and a provider to host your portal, you will need to get your local site ready to be uploaded to your remote server. This is not difficult, but make sure you cover all of the following steps for a smooth transition. Modify the compilation debug setting in the web.config file: You will need to modify your web.config file to match the configuration of the server to which you will be sending your files. The first item that needs to be changed is the debug configuration. This should be set to false. You should also rebuild your application in release mode before uploading. This will remove the debug tokens, perform optimizations in the code, and help the site to run faster: <!-- set debugmode to false for running application --> <compilation debug="false" /> Modify the data-provider information in the web.config file: You will need to change the information for connecting to the database so that it will now point to the server on your host. There are three things to look out for in this section (changes shown overleaf): First, if you are using MS SQL, make sure SqlDataProvider is set up as the default provider. Second, change the connection string to reflect the database server address, the database name (if not DotNetNuke), as well as the user ID and password for the database that you received from your provider. Third, if you will be using an existing database to run the DotNetNuke portal, add an objectQualifier. This will append whatever you place in the quotations to the beginning of all of the tables and procedures that are created for your database. <data defaultProvider=" SqlDataProvider" > <providers> <clear/> <add name = "SqlDataProvider" type = "DotNetNuke.Data.SqlDataProvider, DotNetNuke.SqlDataProvider" connectionStringname = "Server=MyServerIP;Database=DotNetNuke; uid=myID;pwd=myPWD;" providerPath = "~ProvidersDataProvidersSqlDataProvider" objectQualifier = "DE" databaseOwner = "dbo" upgradeConnectionString = "" />   Modify any custom changes in the web.config file: Since you set up YetAnotherForum for use on our site, we will need to make the modifications necessary to ensure that the forums connect to the hosted database. Change the to point to the database on the server: <yafnet> <dataprovider>yaf.MsSql,yaf</dataprovider> <connstr> user id=myID;password=myPwd;data source=myServerIP;initial catalog=DotNetNuke;timeout=90 </connstr> <root>/DotNetNuke/DesktopModules/YetAnotherForumDotNet/</root> <language>english.xml</language> <theme>standard.xml</theme> <uploaddir>/DotNetNuke/DesktopModules/yetanotherforum.net /upload/</uploaddir> <!--logtomail>email=;server=;user=;pass=;</logtomail--> </yafnet> Add your new domain name to your portal alias: Since DotNetNuke has the ability to run multiple portals we need to tell it which domain name is associated with our current portal. To do this we need to sign on as host (not admin) and navigate to Admin | Site Settings on the main menu. If signed on as host, you will see a Portal Aliases section on the bottom of the page. Click on the Add New HTTP Alias link:
Read more
  • 0
  • 0
  • 2724

article-image-customizing-plugins-joomla-15x-part-1
Packt
21 Oct 2009
9 min read
Save for later

Customizing Plugins in Joomla! 1.5x (Part 1)

Packt
21 Oct 2009
9 min read
The code used in this article can be downloaded from here. Plugin composition and operation     Like a module, in its simplest form, a plugin can consist of only two files, a PHP file with the actual code for the plugin, and an XML manifest that tells Joomla! what to do with the plugin. Despite this apparent simplicity, plugins are very powerful, and more difficult to understand than modules and components. Plugins are designed to run at certain times during the execution of our site, and they perform actions that can only be done at these times. For example, in our sample site we want to hide some of our content from guests, and only show it to paid subscribers. This action can only be performed when we are actually preparing the content to be displayed, because we need to wait until we identify if the viewer is a guest or subscriber, and then make the changes to the content dynamically. In a different example, checking if a subscriber's subscription is valid is something that only needs to be done when they try to login, and not on every page load. Plugin types Plugins are divided into eight types, as follows: Authentication Content Editors Editors-XTD Search System User XML-RPC Authentication Authentication plugins are designed to allow the site to check the user's authentication against a variety of sources. The default is to check the user's authentication against a username and password stored in the Joomla! database, which, as of Joomla! 1.5, will be the username and password fields in the #__user table (#__ is the table prefix we chose when setting up Joomla!). However, any source with a public API can be used to verify someone's authentication details. Common uses are LDAP, OpenID, a Google account, a subscription, community component, and more. On our site, for example, we are already using an authentication plugin to verify the subscriptions of users when they attempt to login. Content Possibly the most commonly used of all plugins, content plugins allow content items to be modified or have additional features added to them. We could, for example, use content plugins to cloak email addresses, embed audio or video into our pages, or do text replacements. We can even embed components and modules into our pages via plugins. We will later look at a content plugin that we will use to hide and show content depending on a user's subscription. Editors Editors plugins add WYSIWYG editors that we can use when editing our content. We installed JCE on our site earlier, which is the most popular Joomla! editor plugin as of this publication according to Joomla.org. Editors-XTD Editors-XTD (extended) plugins allow us to add additional buttons to the editors. The Image, Read more, and Pagebreak buttons on the default Joomla! WYSIWYG editor, for example, are actually plugins. Search Search plugins allow us to search through the data from different components. By default, Joomla! comes with plugins that search through content articles and the Contacts and Weblinks components. These can be expanded upon by creating or installing search plugins for other extensions. System System plugins are arguably the most powerful and most flexible types of plugins for Joomla!, as they can execute at several different pre-defined points during the execution of a Joomla! page plugin. They can be used to perform a vast array of functions, such as loading extra scripts or CSS into the header of a web page, redirecting people away from pages, logging statistics, and more. User User plugins allow us to perform actions at different times with respect to users. Such times include logging in and out, and also when saving changes to a user's profile. User plugins are often used to create a "bridge" between Joomla! and other web applications (such as the phpBB forum or the osCommerce e-commerce platform.). XML-RPC XML-RPC plugins are for communicating between our Joomla! site and other external applications, such as a desktop application or a different web site. Plugin events As a Joomla! site loads a page, it steps through a series of events as part of that process. The events it steps through are determined by the type of page it is loading. Plugins are always tied to one or more of these events, and are executed during those events as required. When loading a page of content, for example, we would step through a mix of the system and some of the content events. When loading the same page for editing, we will step through the system events, different content events, and also possibly editor events. The events triggered in Joomla! are: Authentication onAuthenticate Content onPrepareContent onAfterDisplayTitle onBeforeDisplayContent onBeforeContentSave onAfterContentSave Editors onInit onGetContent onSetContent onSave onDisplay onGetInsertMethod Editors XTD (Extended) onDisplay Search onSearch onSearchAreas System onAfterInitialise onAfterRoute onAfterDispatch onAfterRender User onLoginUsexr onLoginFailure onLogoutUser onLogoutFailure onBeforeStoreUser onAfterStoreUser onBeforeDeleteUser onAfterDeleteUser XML-RPC onGetWebServices Most of these events are easy to understand from their name, but just in case, more information can be found on the Joomla! documentation wiki at http://docs.joomla.org/CategoryPlugins. Some events are only activated at specific times, such as onAuthenticate, which is only activated when someone logs into their account. Others are activated on every page load. Content events are activated on all content pages and only on content pages, not on pages with components other than com_content. Content plugins are also only executed on the main body content itself and don't have access to the template or other module data. So a text replacement content plugin, for example, wouldn't change any text in modules or the template, only in the main content itself. It is actually possible for modules and components to manually activate plugin events with clever programming, but this is not the default Joomla! behavior. It is usually done when a developer wants to apply content plugin restrictions/changes to a module. Plugin order Aside from the events and types, there is a third important factor to consider when setting up our plugins. That is the order in which the plugins of a particular type are executed. This order is best observed on the Plugin Manager screen that can be found under the Extensions menu. The order in which the plugins execute is something not many people think about, but is really quite powerful and useful. This is because the plugins which execute later, can then use the output or effects of the earlier executing plugins as input. For example, imagine we have a plugin that displays different text for different user types, and we have another plugin that reads certain text values and replaces them with embedded video or audio. If we wanted to be able to show different videos to different groups, then we could use the first plugin to generate the different command strings for the second plugin, and have it generate them based on the user type. The second plugin, our media embedding plugin, doesn't even know that the first plugin exists. All it knows is which videos it needs to display based on what is in the content item. If the media plugin executes first, then it will generate both videos regardless of the user type. As another example, imagine we have some sort of external application and we log users into it after they authenticate via an authentication plugin. We need to make sure that this plugin is executed after all of our other authentication plugins that may check a user's credentials or account status. Otherwise, someone may get logged into our external application even though they were prevented from login into our Joomla! site. So a hacker, for example, could get access to our external application without needing to even successfully get into our main site. This was all because we had the order of our plugins wrong. So when we install and activate plugins, it is well worth taking the time to double check that everything happens in the order it is meant to be in. If one of our plugins is not behaving how it should, it might be worth checking the order to see if another plugin is conflicting with it. Customizing a Plugin Now that we have a better understanding of how our plugins work and fit together, we are going to try our hand at customizing one for our site. This will hopefully give us the understanding and confidence to make any other customizations we need in the future. As with modules, it is often easier to find a plugin that does most of what we want it to do and then make changes to it so that it meets our needs more completely. Looking back over our goals, one that requires a plugin is that we want to limit access to certain parts of our content to only our paying subscribers. This effect is going to be best achieved via content plugin, so we chose the Ninja Access plugin to fill this need. To use Ninja Access we first need to mark the content we want to restrict with special tags and indicate the user groups we want to see what is contained within the tags. When the page is produced, the plugin reads the visitor's user group and then compares it to the ones in the list provided by the tag. If the user groups match, then the content is displayed, if not, then it is hidden. For example: {njaccess 0}shows only to guest users{/njaccess}{njaccess 18,19,20,21,23,24,25}shows to all users who are not a guest{/njaccess} The numbers in the examples above indicate the default Joomla! user group ids. The most important ones are: 0 = Guests 18 = Registered 24 = Administrators 25 = Super Administrators We could use this as it is, but as we don't have a component installed to create new access groups, it won't be very flexible. We could get into trouble in the future if we decide to let people register without getting a subscription, or create a free subscription. In this instance, we will have paying and free subscribers all in the number 18 user group. Also, as we are always going to be restricting the same groups, we don't really need to type the parameters in every single time. Making our plugins always restrict the same groups automatically will save us some time and reduce mistakes. Lastly, do we really need to type njaccess every time? Let's shorten it to something like soc—subscriber only content. For our first dilemma, a better idea than groups might be to associate the access to certain AEC subscriptions that are currently active. That way if people's subscriptions expire, or they get a free account, the content is still properly controlled regardless of their user groups.
Read more
  • 0
  • 0
  • 2042

article-image-testing-save-dialog-java-using-swing
Packt
21 Oct 2009
10 min read
Save for later

Testing a Save As Dialog in Java using Swing

Packt
21 Oct 2009
10 min read
In this article, we will use an example from our demonstration application, Ikon Do It. The code from this article is in the packages jet.ikonmaker and jet.ikonmaker.test. Click here to download the code. The Ikon Do It 'Save as' Dialog The 'Ikon Do It' application has a Save as function that allows the icon on which we are currently working to be saved with another name. Activating the Save as button displays a very simple dialog for entering the new name. The following figure shows the 'Ikon Do It' Save as dialog. Not all values are allowed as possible new names. Certain characters (such as '*') are prohibited, as are names that are already used. In order to make testing easy, we implemented the dialog as a public class called SaveAsDialog, rather than as an inner class of the main user interface component. We might normally balk at giving such a trivial component its own class, but it is easier to test when written this way and it makes a good example. Also, once a simple version of this dialog is working and tested, it is possible to think of enhancements that would definitely make it too complex to be an inner class. For example, there could be a small status area that explains why a name is not allowed (the current implementation just disables the Ok button when an illegal name is entered, which is not very user-friendly). The API for SaveAsDialog is as follows. Names of icons are represented by IkonName instances. A SaveAsDialog is created with a list of existing IkonNames. It is shown with a show() method that blocks until either Ok or Cancel is activated. If Ok is pressed, the value entered can be retrieved using the name() method. Here then are the public methods: public class SaveAsDialog { public SaveAsDialog( JFrame owningFrame, SortedSet<IkonName> existingNames ) { ... } /** * Show the dialog, blocking until ok or cancel is activated. */ public void show() { ... } /** * The most recently entered name. */ public IkonName name() { ... } /** * Returns true if the dialog was cancelled. */ public boolean wasCancelled() { ... }} Note that SaveAsDialog does not extend JDialog or JFrame, but will use delegation. Also note that the constructor of SaveAsDialog does not have parameters that would couple it to the rest of the system. This means a handler interface is not required in order to make this simple class testable. The main class uses SaveAsDialog as follows: private void saveAs() { SaveAsDialog sad = new SaveAsDialog( frame, store.storedIkonNames() ); sad.show(); if (!sad.wasCancelled()) { //Create a copy with the new name. IkonName newName = sad.name(); Ikon saveAsIkon = ikon.copy( newName ); //Save and then load the new ikon. store.saveNewIkon( saveAsIkon ); loadIkon( newName ); }} Outline of the Unit Test The things we want to test are: Initial settings: The text field is empty. The text field is a sensible size. The Ok button is disabled. The Cancel button is enabled. The dialog is a sensible size. Usability: The Escape key cancels the dialog. The Enter key activates the Ok button. The mnemonics for Ok and Cancel work. Correctness. The Ok button is disabled if the entered name: Contains characters such as '*', '', '/'. Is just white-space. Is one already being used. API test: unit tests for each of the public methods. As with most unit tests, our test class has an init() method for getting an object into a known state, and a cleanup() method called at the end of each test. The instance variables are: A JFrame and a set of IkonNames from which the SaveAsDialog can be constructed A SaveAsDialog, which is the object under test. A UserStrings and a UISaveAsDialog (listed later on) for manipulating the SaveAsDialog with keystrokes. A ShowerThread, which is a Thread for showing the SaveAsDialog. This is listed later on. The outline of the unit test is: public class SaveAsDialogTest { private JFrame frame; private SaveAsDialog sad; private IkonMakerUserStrings = IkonMakerUserStrings.instance(); private SortedSet<IkonName> names; private UISaveAsDialog ui; private Shower shower; ... private void init() { ... } private void cleanup() { ... } private class ShowerThread extends Thread { ... }} UI Helper Methods A lot of the work in this unit test will be done by the static methods in our helper class, UI. Some of these are isEnabled(), runInEventThread(), and findNamedComponent(). The new methods are listed now, according to their function. Dialogs If a dialog is showing, we can search for a dialog by name, get its size, and read its title: public final class UI { ... /** * Safely read the showing state of the given window. */ public static boolean isShowing( final Window window ) { final boolean[] resultHolder = new boolean[]{false}; runInEventThread( new Runnable() { public void run() { resultHolder[0] = window.isShowing(); } } ); return resultHolder[0]; } /** * The first found dialog that has the given name and * is showing (though the owning frame need not be showing). */ public static Dialog findNamedDialog( String name ) { Frame[] allFrames = Frame.getFrames(); for (Frame allFrame : allFrames) { Window[] subWindows = allFrame.getOwnedWindows(); for (Window subWindow : subWindows) { if (subWindow instanceof Dialog) { Dialog d = (Dialog) subWindow; if (name.equals( d.getName() ) && d.isShowing()) { return (Dialog) subWindow; } } } } return null; } /** * Safely read the size of the given component. */ public static Dimension getSize( final Component component ) { final Dimension[] resultHolder = new Dimension[]{null}; runInEventThread( new Runnable() { public void run() { resultHolder[0] = component.getSize(); } } ); return resultHolder[0]; } /** * Safely read the title of the given dialog. */ public static String getTitle( final Dialog dialog ) { final String[] resultHolder = new String[]{null}; runInEventThread( new Runnable() { public void run() { resultHolder[0] = dialog.getTitle(); } } ); return resultHolder[0]; } ...} Getting the Text of a Text Field The method is getText(), and there is a variant to retrieve just the selected text: //... from UI/** * Safely read the text of the given text component. */public static String getText( JTextComponent textComponent ) { return getTextImpl( textComponent, true );}/** * Safely read the selected text of the given text component. */public static String getSelectedText( JTextComponent textComponent ) { return getTextImpl( textComponent, false );}private static String getTextImpl( final JTextComponent textComponent, final boolean allText ) { final String[] resultHolder = new String[]{null}; runInEventThread( new Runnable() { public void run() { resultHolder[0] = allText ? textComponent.getText() : textComponent.getSelectedText(); } } ); return resultHolder[0];} Frame Disposal In a lot of our unit tests, we will want to dispose of any dialogs or frames that are still showing at the end of a test. This method is brutal but effective: //... from UIpublic static void disposeOfAllFrames() { Runnable runnable = new Runnable() { public void run() { Frame[] allFrames = Frame.getFrames(); for (Frame allFrame : allFrames) { allFrame.dispose(); } } }; runInEventThread( runnable );} Unit Test Infrastructure Having seen the broad outline of the test class and the UI methods needed, we can look closely at the implementation of the test. We'll start with the UI Wrapper class and the init() and cleanup() methods. The UISaveAsDialog Class UISaveAsDialog has methods for entering a name and for accessing the dialog, buttons, and text field. The data entry methods use a Cyborg, while the component accessor methods use UI: public class UISaveAsDialog { Cyborg robot = new Cyborg(); private IkonMakerUserStrings us = IkonMakerUserStrings.instance(); protected Dialog namedDialog; public UISaveAsDialog() { namedDialog = UI.findNamedDialog( SaveAsDialog.DIALOG_NAME ); Waiting.waitFor( new Waiting.ItHappened() { public boolean itHappened() { return nameField().hasFocus(); } }, 1000 ); } public JButton okButton() { return (JButton) UI.findNamedComponent( IkonMakerUserStrings.OK ); } public Dialog dialog() { return namedDialog; } public JButton cancelButton() { return (JButton) UI.findNamedComponent( IkonMakerUserStrings.CANCEL ); } public JTextField nameField() { return (JTextField) UI.findNamedComponent( IkonMakerUserStrings.NAME ); } public void saveAs( String newName ) { enterName( newName ); robot.enter(); } public void enterName( String newName ) { robot.selectAllText(); robot.type( newName ); } public void ok() { robot.altChar( us.mnemonic( IkonMakerUserStrings.OK ) ); } public void cancel() { robot.altChar( us.mnemonic( IkonMakerUserStrings.CANCEL ) ); }} A point to note here is the code in the constructor that waits for the name text field to have focus. This is necessary because the inner workings of Swing set the focus within a shown modal dialog as a separate event. That is, we can't assume that showing the dialog and setting the focus within it happen within a single atomic event. Apart from this wrinkle, all of the methods of UISaveDialog are straightforward applications of UI methods. The ShowerThread Class Since SaveAsDialog.show() blocks, we cannot call this from our main thread; instead we spawn a new thread. This thread could just be an anonymous inner class in the init() method: private void init() { //Not really what we do... //setup...then launch a thread to show the dialog. //Start a thread to show the dialog (it is modal). new Thread( "SaveAsDialogShower" ) { public void run() { sad = new SaveAsDialog( frame, names ); sad.show(); } }.start(); //Now wait for the dialog to show...} The problem with this approach is that it does not allow us to investigate the state of the Thread that called the show() method. We want to write tests that check that this thread is blocked while the dialog is showing. Our solution is a simple inner class: private class ShowerThread extends Thread { private boolean isAwakened; public ShowerThread() { super( "Shower" ); setDaemon( true ); } public void run() { Runnable runnable = new Runnable() { public void run() { sad.show(); } }; UI.runInEventThread( runnable ); isAwakened = true; } public boolean isAwakened() { return Waiting.waitFor( new Waiting.ItHappened() { public boolean itHappened() { return isAwakened; } }, 1000 ); }} The method of most interest here is isAwakened(), which waits for up to one second for the awake flag to have been set, this uses a class, Waiting. Another point of interest is that we've given our new thread a name (by the call super("Shower") in the constructor). It's really useful to give each thread we create a name. The init() Method The job of the init() method is to create and show the SaveAsDialog instance so that it can be tested: private void init() { //Note 1 names = new TreeSet<IkonName>(); names.add( new IkonName( "Albus" ) ); names.add( new IkonName( "Minerva" ) ); names.add( new IkonName( "Severus" ) ); names.add( new IkonName( "Alastair" ) ); //Note 2 Runnable creator = new Runnable() { public void run() { frame = new JFrame( "SaveAsDialogTest" ); frame.setVisible( true ); sad = new SaveAsDialog( frame, names ); } }; UI.runInEventThread( creator ); //Note 3 //Start a thread to show the dialog (it is modal). shower = new ShowerThread(); shower.start(); //Note 4 //Wait for the dialog to be showing. Waiting.waitFor( new Waiting.ItHappened() { public boolean itHappened() { return UI.findNamedFrame( SaveAsDialog.DIALOG_NAME ) != null; } }, 1000 ); //Note 5 ui = new UISaveAsDialog();} Now let's look at some of the key points in this code. Note 1: In this block of code we create a set of IkonNames with which our SaveAsDialog can be created. Note 2: It's convenient to create and show the owning frame and create the SaveAsDialog in a single Runnable. An alternative would be to create and show the frame with a UI call and use the Runnable just for creating the SaveAsDialog. Note 3: Here we start our Shower, which will call the blocking show() method of SaveAsDialog from the event thread. Note 4: Having called show() via the event dispatch thread from our Shower thread, we need to wait for the dialog to actually be showing on the screen. The way we do this is to search for a dialog that is on the screen and has the correct name. Note 5: Once the SaveAsDialog is showing, we can create our UI Wrapper for it. The cleanup() Method The cleanup() method closes all frames in a thread-safe manner: private void cleanup() { UI.disposeOfAllFrames();}
Read more
  • 0
  • 0
  • 4122

article-image-managing-pages-liferay-portal-52-systems-development
Packt
21 Oct 2009
14 min read
Save for later

Managing Pages in Liferay Portal 5.2 Systems Development

Packt
21 Oct 2009
14 min read
Each site is represented as a community and each community is made up of a lot of pages, for example, public pages and private pages. In order to build web sites, we need to manage communities and, further, manage pages for each community. The Communities portlet provides the ability to create and manage communities and their users, as well as of the Manage Pages portlet. Extending Communities portlet The Communities portlet provides the ability to create and manage communities and their users. A community is a special group holding a number of users who share common interests. By default, a community is represented by the Group_ table with fields such as groupId, companyId, creatorUserId, name, description, type, typeSettings, friendlyURL, active, and so on. Now let's take an in-depth look at the customization of the community. As shown in the following screenshot, we may want to add one searchable field for each community, which is Keywords. For example, suppose we are creating a new community with the name Book Street, and the description a community for website www.bookpubstreet.com. Now we have a chance to add the new Keywords field with the value, for example, Book; Street; Palm Tree; Publication. Similarly, when editing the properties of a community—for example Name, Description, Type, and Active—we again have a chance to edit Keywords. In addition, we expect to have more fields in the customized communities: Created (when the community was created), ModifierUserId (who modified the community), and Modified (when the community was modified). As shown in the preceding screenshot, when listing communities, not only should the default fields (for example, Name, Type, Members, Online Now, Active, Pending Requests) and Actions icons (for example, Edit, Permissions, Manage Pages, Assign User Roles, Assign Members, Leave, and Delete) be displayed, but also the customized columns (for example, the username and Keywords) should be displayed. How do we implement these features? In this article, we're going to show how to customize the Communities portlet using the above requirements as examples. Obviously, it is open for you to customize this portlet in a number of ways according to your own requirements. In general, the processes for customization of this portlet should be the same. Building Ext Communities portlet The Communities portlet can be used to create and manage new portal communities and their users. As you can see, a community can be regarded as a separate portal instance; each community gets its own set of pages, content management system, shared calendar, and default permissions. Moreover, a user belonging to multiple communities can navigate among them within the same portal session. Generally speaking, we do not want to update the Communities portlet, but keep it as it is. Our goal is to customize and extend it. In general, this can be done by using the following two steps: Build a customized Ext Communities portlet, which has exactly the same functions, look, and feel as that of the original Communities portlet. Extend this customized portlet and let it have an additional model and service, and moreover, its own look and feel. In this part, let's build the Ext Communities portlet, having exactly same functions, look, and feel as that of the Communities portlet. Constructing the portlet Now let's define a Struts portlet with the name "Ext Communities". We first need to configure it in both portlet-ext.xml and liferay-portlet-ext.xml, and then set the title in Language-ext.properties, and then add the Ext Communities portlet to the Book category in liferay-display.xml. Locate the portlet-ext.xml file in the /ext/ext-web/docroot/WEB-INF folder and open it. Add the following lines between </portlet> and </portlet-app> and save the file: <portlet> <portlet-name>extCommunities</portlet-name> <display-name>Ext Communities</display-name> <portlet-class>com.liferay.portlet.StrutsPortlet</portlet-class> <init-param><name>view-action</name> <value>/ext/communities/view</value></init-param> <expiration-cache>0</expiration-cache> <supports><mime-type>text/html</mime-type></supports> <resource-bundle> com.liferay.portlet.StrutsResourceBundle </resource-bundle> <security-role-ref> <role-name>power-user</role-name> </security-role-ref> <security-role-ref> <role-name>user</role-name> </security-role-ref> </portlet> As shown in the code above, the portlet-name element contains the canonical name of the portlet (for example, extCommunities). The display-name element contains a short name that is intended to be displayed in the portal (for example, Ext Communities). The portlet-class element contains the fully qualified class name of the portlet (for example, com.liferay.portlet.StrutsPortlet). The init-param element contains a name-value pair, for example view-action-ext/communities/view, as an initialization parameter of the portlet. Further, the expiration-cache defines expiration-based caching for this portlet. The supports element contains the supported MIME-type. The resource-bundle element contains a resource bundle class, for example com.liferay.portlet. StrutsResourceBundle. Finally, the security-role-ref element contains the declaration of a security role reference in the code of the web application. Secondly, let's register the extCommunities portlet in liferay-portlet-ext.xml as follows: Locate the liferay-portlet-ext.xml file in the /ext/ext-web/docroot/WEB-INF folder and open it. Add the following lines immediately after <!-- Custom Portlets --> and save it: <portlet> <portlet-name>extCommunities</portlet-name> <struts-path>ext/communities</struts-path> <use-default-template>false</use-default-template> <restore-current-view>false</restore-current-view> </portlet> As shown in the code above, the Ext Communities portlet is registered in the portal. The portal will check struts-path to see whether a user has the required permissions to access the portlet or not. As you can see, struts-path has the value ext/communities. It means that all requests to the ext/communities/* path are considered a part of this portlet scope. Only those users whose request paths match ext/communities/* will be granted access. Moreover, the use-default-template element has the value false, so the portlet will not use any user's default template. The restore-current-view element has the value false so the portlet will reset the current view when toggling between maximized and normal states. Thirdly, add a title (for example, Ext Communities), for the Ext Communities portlet at Language-ext.properties as follows: Locate the Language-ext.properties file in the /ext/ext-impl/src/content folder and open it. Add the following line after javax.portlet.title.book_reports=Reports for Books and save it: javax.portlet.title.extCommunities=Ext Communities The code above provides mapping for the title of the portlet. If the mapping is not provided, the portal will show the default title javax.portlet.title.extCommunities. Finally, add the Ext Communities portlet to the Book category in liferay-display.xml as follows: Locate the liferay-display.xml file in the /ext/ext-web/docroot/WEBINF folder and open it. Add the following line immediately after the line <portlet id="book_reports" /> and save it: <portlet id="extCommunities" /> As shown in the code above, it adds the Ext Communities portlet to the category Book. From now on, you are able to select this portlet from the Book category directly when adding portlets to pages. Setting up actions Now, let's set up all actions required for the Ext Communities portlet. We need to prepare an action class, for example, ExtEditGroupAction. So how do we build this action? You can build the actions from scratch, but our purpose is to customize and extend the Communities portlet. In one word, we expect to reuse the out of the box portlet source code as much as possible and to write minimum code. As mentioned earlier, we have the portal project for the portal source code in the Eclipse IDE, which is referred to as the /portal prefix. We also have the ext project for customized code, which is referred to as the /ext prefix. The following is a process flow to build the ExtEditGroupAction action class of the Ext Communities portlet. Create a com.ext.portlet.communities.action package in the /ext/ext-impl/src folder. Create an ExtEditGroupAction class in this package and open it. Add the following lines and save it: public class ExtEditGroupAction extends EditGroupAction { public void processAction( ActionMapping mapping, ActionForm form, PortletConfig portletConfig, ActionRequest actionRequest, ActionResponse actionResponse) throws Exception { String cmd = ParamUtil.getString(actionRequest, Constants.CMD); try { if (cmd.equals(Constants.ADD) || cmd.equals(Constants.UPDATE)) { updateGroup(actionRequest); } else if (cmd.equals(Constants.DELETE)) { deleteGroup(actionRequest); } sendRedirect(actionRequest, actionResponse); } catch (Exception e) { if (e instanceof NoSuchGroupException || e instanceof PrincipalException) { SessionErrors.add(actionRequest, e.getClass().getName()); setForward(actionRequest, "portlet.ext.communities.error"); } else if (e instanceof DuplicateGroupException || e instanceof GroupFriendlyURLException || e instanceof GroupNameException || e instanceof RequiredGroupException) { SessionErrors.add(actionRequest, e.getClass().getName(), e); if (cmd.equals(Constants.DELETE)) { actionResponse.sendRedirect( ParamUtil.getString(actionRequest, "redirect")); } } else { throw e;} } } public ActionForward render(ActionMapping mapping, ActionForm form, PortletConfig portlonfig, RenderRequest renderRequest, RenderResponse renderResponse) throws Exception { try { ActionUtil.getGroup(renderRequest); } catch (Exception e) { if (e instanceof NoSuchGroupException || e instanceof PrincipalException) { SessionErrors.add(renderRequest, e.getClass().getName()); return mapping.findForward ("portlet.ext.communities.error"); } else {throw e;} } return mapping.findForward(getForward(renderRequest, "portlet.ext.communities.edit_community")); } } As shown in the code above, ExtEditGroupAction extends EditGroupAction from the com.liferay.portlet.communities.action package in the /portal/portal-impl/src folder. It overrides two methods (render and processAction) of EditGroupAction. Setting up page flow and page layout We have set up the action. We have also updated the forward path as the portlet.ext.communities.* value. In order to get the page flow working, we need to set up an action path and a page flow. First, let's set up the action path and page flow in struts-config.xml as follows: Locate the struts-config.xml file in the /ext/ext-web/docroot/WEB-INF folder and open it. Add the following lines after <struts-config> <action-mappings> and save it: <!-- Ext Communities --> <action path="/ext/communities/edit_community" type="com.ext.portlet.communities.action. ExtEditGroupAction"> <forward name="portlet.ext.communities.edit_community" path="portlet.ext.communities.edit_community" /> <forward name="portlet.ext.communities.error" path="portlet.ext.communities.error" /> </action> <action path="/ext/communities/view" forward="portlet.ext.communities.view" /> The code above defines a set of action paths associated with the action and forward paths, as well as those mentioned earlier. For example, the action path /ext/communities/edit_community is associated with the com.ext.portlet.communities.action.ExtEditGroupAction action and the forward path names portlet.ext.communities.edit_community and portlet.ext.communities.error. Then based on the page flow and JSP files, let's define the page layout in tiles-defs.xml: Locate the tiles-defs.xml file in the ext/ext-web/docroot/WEB-INF folder and open it. Add the following lines after <struts-config> <action-mappings> and save it: <!-- Ext Communities --> <action path="/ext/communities/edit_community" type="com.ext.portlet.communities.action. ExtEditGroupAction"> <forward name="portlet.ext.communities.edit_community" path="portlet.ext.communities.edit_community" /> <forward name="portlet.ext.communities.error" path="portlet.ext.communities.error" /> </action> <action path="/ext/communities/view" forward="portlet.ext.communities.view" /> The code above defines a set of action paths associated with the action and forward paths, as well as those mentioned earlier. For example, the action path /ext/communities/edit_community is associated with the com.ext.portlet.communities.action.ExtEditGroupAction action and the forward path names portlet.ext.communities.edit_community and portlet.ext.communities.error. Then based on the page flow and JSP files, let's define the page layout in tiles-defs.xml: Locate the tiles-defs.xml file in the ext/ext-web/docroot/WEB-INF folder and open it. Add the following lines after <tiles-definitions> and save it: <!-- Ext Communities --> <definition name="portlet.ext.communities" extends="portlet" /> <definition name="portlet.ext.communities.edit_community" extends="portlet.ext.communities"> <put name="portlet_content" value="/portlet/ext/communities/edit_community.jsp" /> </definition> <definition name="portlet.ext.communities.view" extends="portlet"> <put name="portlet_content" value="/portlet/ext/communities/view.jsp" /> </definition> <definition name="portlet.ext.communities.error" extends="portlet"> <put name="portlet_content" value="/portlet/communities/error.jsp" /> </definition> The code above defines the page layout for the Ext Communities portlet. For example, portlet.ext.communities.edit_community is associated with the JSP file /portlet/ext/communities/edit_community.jsp. In addition, it specifies that the community view page layout (for example, portlet.ext.communities.view) is associated with the JSP page file /portlet/ext/communities/view.jsp. Preparing JSP files We have now set up the actions. We have also set up page flow and page layout. Now let's set up the JSP files that are required for the Ext Communities portlet. We need to prepare JSP files such as view.jsp, edit_community.jsp, group_search.jsp, and so on. So how do we build this? You can build them from scratch. However, here we will copy and modify JSP files of the Communities portlet. In this section we expect to reuse the source code, including JSP files, as much as possible. First, let's create the view.jsp JSP file as follows: Create a communities folder within the /ext/ext-web/docroot/html/portlet/ext/ folder. Locate the view.jsp JSP file in the /portal/portal-web/docroot/html/portlet/communities folder, and copy it to the /ext/ext-web/docroot/html/portlet/ext/communities folder. Open view.jsp in the /ext/ext-web/docroot/html/portlet/ext/communities folder, update /communities/edit_community with /ext/communities/edit_community as shown in the following two lines, and save it: portletURL.setParameter("struts_action", "/ext/communities/view"); <liferay-ui:search-form page="/html/portlet/ext/communities/group_search.jsp" searchContainer="<%= searchContainer %>" showAddButton="<%= showTabs1 %>" /> Next, we need to create the JSP file edit_community.jsp as follows: Locate the JSP file edit_community.jsp in the /portal/portal-web/docroot/html/portlet/communities folder, and copy it to the /ext/extweb/docroot/html/portlet/ext/communities folder. Open edit_community.jsp in the /ext/ext-web/docroot/html/portlet/ext/communities folder, update /communities/edit_community with /ext/communities/edit_community as shown in following line, and save it: <form action="<portlet:actionURL windowState="<%= WindowState.MAXIMIZED. toString() %>"> <portlet:param name="struts_action" value="/ext/communities/edit_community" /> </portlet:actionURL>" method="post" name="<portlet:namespace />fm" onSubmit="<portlet:namespace />saveGroup(); return false;"> In addition, we need to make the button Add Community available, in the following manner: Locate JSP file group_search.jsp in the /portal/portal-web/docroot/html/portlet/enterprise_admin folder. Copy the JSP file group_search.jsp from /portal/portal-web/docroot/html/portlet/enterprise_admin to /ext/ext-web/docroot/html/portlet/ext/communities, and open it. Update /communities/edit_community with /ext/communities/edit_community as shown in the following lines, and save it: submitForm(document.<portlet:namespace />fm, '<portlet:renderURL windowState="<%= WindowState.MAXIMIZED.toString() %>"> <portlet:param name="struts_action" value="/ext/communities/edit_community" /> <portlet:param name="redirect" value="<%= currentURL %>" /> </portlet:renderURL>'); Congratulations! You have cloned the Communities portlet. Finally, we can deploy updates into Tomcat as follows: Stop Tomcat if it is running. Click on the Ant target: deploy at the Ant view ext. Start Tomcat. Open up a new browser with the URL http://localhost:8080. Click on Sign in and enter test@liferay.com / test. Click on Add Application | Book
Read more
  • 0
  • 0
  • 1738
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 €18.99/month. Cancel anytime
article-image-creating-pseudo-3d-imagery-gimp-part-1
Packt
21 Oct 2009
9 min read
Save for later

Creating Pseudo-3D Imagery with GIMP: Part 1

Packt
21 Oct 2009
9 min read
In the previous article I've written ( Creating Convincing Images with Blender Internal Renderer-part1), I discussed about creating convincing 3D still images through color manipulation, proper shadowing, minimal lighting, and a bit of post-processing, all using but one application – Blender. This time, the article you're about to read will give us some thoughts on how to mimic a 3D scene with the use of some basic 2D tools. Here again, I would stress that nothing beats a properly planned image, that applies to all genres you can think of. Some might think it's a waste of precious time to start sitting and planning without having a concrete output at the end of the thought process. But believe me, the ideas you planned will be far more powerful and beautiful than those ideas you just had, when you were just messing around and playing with the tool directly. In this article, I wouldn't be teaching you how to paint since I'm not good at it, rather I'll be leading you through a series of steps on how to digitally sketch/draw your scenes, give them subtle color shifts, add fake lighting, and apply filter effects to further emulate how 3D does its job. Primarily, this all leads you into a guide on how I create my digital drawings (though I admit they're not the best of its kind), but somehow I'm very proud, I eventually gave life to them from concept stage to digital art stage. It might be a bit daunting at first, but as you go along the series, you'll notice it gets simpler.  However, some might get confused as to how this applies to other applications since we're focusing on The GIMP in this article. That's not a problem at all once you are familiar with your own tool; it will just be a matter of working around the tools and options. I have been using The GIMP for a long time already, and as far as I can remember, I haven't complained on its shortcomings since those shortcomings are only but bits of features which I wouldn't be need at all.  So to those of you who have been and are using other image editing programs like Adobe Photoshop, Corel, etc., you're welcome to wander around and feel free to interpret some GIMP tools to that of yours.  It's all the same after all, just a tad bit difference on the interface. Just like what Jeremy Birn has said on one of his books: “Being an expert user of a 3D Program, bit itself, does not make the user into an artist more than learning to run a Word Processor makes someone into a good writer.” Additionally, one vital skill you have to develop is the skill of observation, which I myself ham yet to master. Methods Used Basic Drawing Selection Addition, Subtraction, Intersection Gradient Coloring Color Mixing Layering Layer Modes Layer Management Using Filters Requirements Latest version of The GIMP (download at http://www.gimp.org/downloads) Basic knowledge of image editing programs with layering capabilities Patience Let's Get Started! I would already assume you have the latest version of GIMP installed on your system and is running properly, otherwise, fix the problem or ask help from the forum (http://www.gimptalk.com). I'm also assuming you have all your previous tasks done before sitting down and going over this article (which I'm pretty much positive you are). And then lastly, be patient. Sketch it out The very first thing we're going to do is to sketch our ideas for the image, much like a single panel of a storyboard. It doesn't matter how good you draw it as long as you understand it yourself and you know what's going on in the drawing. This time, you can already visualize and create a picture of your final output and it's great if you did, if not, it's fine still. The important thing is we have laid down our scene one way or another. You can take your time sketching out your scenes and adding details to them like how many objects are seen, how many are in focus, what colors do they represent, how are your characters' facial expressions, what is the size of your image, etc. So just in case we forgot how it's going to look like in the end, we have a reference to call upon and that is your initial sketch. This way, you'll also be affected by the persistence of vision where after hours and hours (yay!) of looking on your sketch, you somehow see an afterimage of what you are about to create, and that's a good thing! I'm not good at sketching so please bear with my drawing: After this, it's now time to open up The GIMP and begin the actual fun part! First Run After executing GIMP, this should (and most likely) be the initial screen that's going to be displayed on your screen: The GIMP Initial Screen We don't want Wilbur (GIMP's Mascot) to be glaring at us from a blank empty window all the time, do we? And right now we could go ahead and add a canvas with which we'll be adding our aesthetic elements into, but before that you might want to inspect your application and tool preferences just to make sure you have set everything right. Activate the window with the menu bar at the top (since we currently have three windows to choose from), and then locate Edit > Preferences, as seen below: Locating GIMP's Preferences GIMP Preferences Everything you see here should be self-explanatory, if it isn't, just leave it for the moment and check the manual later, since I'm pretty much sure that thing you didn't understand on the Preferences must be something we will not use here.  So go ahead and save whatever changes you did and sometimes, GIMP might ask you to restart the application for the changes to take effect, then do what she says and we should be back on the black canvas shortly after application restart. By now, we should be having three windows, the main Toolbox Window (located on the left), the main Image Window (located on the middle), and the Layers Window (located on the right).  If, by any chance, the Layer Window is not there, go ahead and activate the Image Window and go to Windows > Layers or press CTRL + L to bring up the Layer Window. Showing the Layers Window Creating the Canvas Now that everything's set up, we'll go ahead and add a properly-sized canvas that we'll paint on, which will be the entire universe for our creation at a later stage. Let's go and create than now by going to File > New or by pressing CTRL+ N. A window will pop up asking you to edit and confirm the image settings for the canvas you're creating. You can choose from a variety of templates to use or you can manually input sizes (which we are going to do).  Before that, change the unit for coordinate display to inches just so we could have a better visual reference of how big our drawing canvass will be. Then on the Width input box, type 9 (for nine inches), and for the Height input box, type 6 (for six inches) respectively. This, however, is a very subjective portion, since you can just have any size you prefer, I just chose nine inches by six inches for the purposes of this article. Clicking the Advanced Options drop-down menu will reveal more options for you.  But right now, we'll never deal with that, just the width and height are sufficient for what we'll be need. When you're done setting up the dimensions and settings, click OK to confirm (is there a chance we could chance the OK buttons to “Alright” buttons, which sounds, uhmmm, better). Creating a New Image At this moment, we should be seeing a blank canvas with the dimensions that we've set awhile back. Then just at the right window (Layers Window), you'll notice there's already one layer present as compared to the default which is none. So everytime we add a new layer (which is very vital), we'll be referencing them over to the Layers Window. Since the creation of the layering system in image editors, it has been a blast to organize elements of an image and apply special effects on them as necessary. We can imagine layers as transparent sheets overlaying each other to form one final image; one transparent sheet can have a landscape drawn, another sheet contains trees and vegetation, and another sheet (which is above the tree sheets) is our main character. So together, we see a character with trees on a landscape in one. But as far as traditional layering is concerned, digital layering has been far more superior in terms of flexibility and the amount of modes we can experiment with. New Image with Layer This time might be a good idea to save our file natively, by that I mean save it in a format that is recognizable only by GIMP and that is lossless in format, so whether we save it a couple of times as such, no image compression happens and the image quality is not compromised. However, the native format is only related to GIMP and is not known elsewhere, so uploading such file to your website will show no image at all because it isn't recognized by the browser. In order to make it generally compatible, we export our image to known formats like JPEG, PNG, GIF, etc. depending on your need. Saving an image file on its native format preserves all the options we have like selections, paths, layers, layer modes, palettes, and many more. This native format that GIMP uses is known as .XCF which stands for “eXperimental Computing Facility”. Throughout this article, we'll save our files mainly in .xcf format and later on, when our tasks are done and we call our image finished, that's the time we export it to a readable and viewable format. Let's go ahead and save our file by going to File > Save, or by pressing CTRL + S. This brings up a window that we can type our filename into and browse and create the location for our files. Type whatever filename you wish and append the “.xcf” file extension at the end of the filename, or you can choose “GIMP xcf image” from a list on the lower half of the window. Saving an Image as XCF
Read more
  • 0
  • 1
  • 7704

article-image-creating-efficient-reports-visual-studio
Packt
21 Oct 2009
5 min read
Save for later

Creating efficient reports with Visual Studio

Packt
21 Oct 2009
5 min read
Report Services, Analysis Services, and Integration Services are the three pillars of Business Intelligence in Microsoft's vision that continues to evolve. Reporting is a basic activity, albeit one of the most important activities of an organization because it provides a specialized and customized view of the data of various forms (relational, text, xml etc) that live in data stores. The report is useful in making business decisions, scheduling business campaigns, or assessing the competition. The report itself may be required in hard copy in several document formats such as DOC, HTML, PDF, etc. Many times it is also required to be retrieved in an interactive form from the data store and viewed on a suitable interface, including a web browser. The Microsoft SQL Server 2005 Reporting Services, popularly known by its acronym SSRS, provides all that is necessary to create and manage reports and deploy them on a report server with output available in several document formats. The reader will greatly benefit from reading the several articles detailed in the author's Hodentek Blog. The content for the articles were developed using VS 2003, VS 2005, SQL 2000 and SQL 2005. (For more resources on Microsoft, see here.) The content for the present tutorial uses a Visual Studio 2008 Professional and a Microsoft SQL Server Compact 3.5 embeddable database for its data. In Visual Studio a Report Design Wizard guides you through fashioning a report from your choices. Create a Windows Project in VS2008 Create a new project from File | New | Project. Provide a name instead of the default name (WindowsApplicaiton1). This is changed to ReportDesign for this tutorial as shown in the next figure. VS 2008 supports multi-version targeting. In the top right of the New Project window you can see that this report is targeted for the NET 2.0 Framework Version and can be published to a Net 2.0 web site. Slightly enlarge the Form1. Drag and drop the Microsoft Report Viewer control shown in the next figure on to the form from the Toolbox. This has the same functionality as the ReportViewer control in VS 2005 as shown in the next figure. The control will be housed on the form as shown in the next figure. You can display the tasks needed to configure the Report Viewer by clicking on the Smart Task as shown in the same figure. The report will have all the functionalities like print, save to different formats, navigating through pages, etc. Working with the Report Wizard Now click on the Design a new report task. The opens the Report Wizard window as shown in the figure. Read the instructions on this page carefully. Click on the Next Button. This displays the Data Source Configuration Wizard shown in the next figure. Choosing a Data Source The application can obtain data from these different resources. Click on the Database icon and then click on the Next button. This displays the window where you need to select a connection to the data source. If there are existing connections you should be able to see them in the drop-down list box. Making a Connection to Get Data Click on the New Connection button. This brings up the Add Connection window showing a default connection to a Microsoft SQL Server Compact 3.5.NET Framework Data Provider. It also shows the location to be My Computer. This source can be changed by clicking on the Change... button. This will bring up the Change Data Source window where you can choose. As found in this version you have the following options: Microsoft SQL Server option lets you connect to SQL 2000 or 2005 using the .NET Framework Data Provider for SQL Server. Microsoft SQL Server Compact 3.5 lets you connect to a database file. Microsoft SQL Server Database File lets you connect to a Local Microsoft SQL Server Instance including a SQL Express. Although it is not explicitly stated what these versions are. For this tutorial the Compact 3.5 will be used (also uses a .NET Framework Data Provider of Compact 3.5). Click on the OK button in the Change Data Source window. VS 2008 installation also installs a database file on the computer for the SQL Server Compact 3.5. Click on Browse button (you could also create one if you like, herein it will be browsed). This brings up the Select SQL Server Compact 3.5 Database File window with the default location where the database file is parked as shown in the next figure. Click on the Northwind icon in the window and click on the Open button. This updates the Add Connection window with this information as shown in the next figure. You may test the connection by hitting the Test Connection button which should display a successful outcome as shown in the next figure. There is no need for a password as you are the owner. Click OK twice and this will take you back to the Data Source Configuration Wizard updating the connection information which you may review as shown in the next figure. Click on the Next button. This brings up the Microsoft Visual Studio message window giving you the option to bring this data source to your project.    
Read more
  • 0
  • 0
  • 6528

article-image-gateways-sipxecs-40-part-2
Packt
21 Oct 2009
5 min read
Save for later

Gateways in sipXecs 4.0: Part 2

Packt
21 Oct 2009
5 min read
Advanced Parameters The Advanced Parameters settings, shown as follows, are accessed by clicking on the Advanced Parameters item in the lefthand menu and are a collection of AudiCodes-specific settings. The following configuration options are available on this page (click on Show Advanced Settings to reveal all options): Secure SIP Calls: If this is enabled, gateways will only accept SIP calls from IP addresses listed below. The default is disabled (unchecked) Accepted IP Addresses: They are used in conjunction with the above setting. It is a space-separated list of IP addresses from which gateway will accept the calls. It is taken into account only if Secure SIP Calls is enabled. The default is the IP address provided for the PBX during install. Digit Delivery to Telephony Port: This setting enables a digit string to be played to the port at the far end, after off-hook. The default is disabled (unchecked). Digit Delivery to IP: This setting enables a digit string to be played to the port at the far end, after off-hook. The default is disabled (unchecked). DID Wink Support: When this is enabled, the gateway can connect to EIA/TIA 464B Loop Start DID lines. Both generation and detection are supported. The default setting is disabled (unchecked). Enable Call Disconnect on Polarity Reversal: If this is checked, enables port disconnect (on-hook) based on polarity reversal. Some POTS providers will reverse the polarity of the analog phone line to signal disconnection to a PBX. The default is disabled (unchecked). Enable Call Disconnect on Current Drop: If this is set to 1, enables port disconnect (on-hook) based on current drop. The default setting is disabled (0). Enable Call Disconnect on Broken Connection: If this is checked, the call is released if the gateway stops receiving RTP for a period of time. The default is enabled (checked). Broken Connection Timeout (10msec): The amount of time for which RTP is not received, before the call is cleared. In 10 ms steps, the default is 500, 10 ms steps (5 seconds). Enable Call Disconnect on Far End Silence: If this checked, enables disconnection of call based on silence. The default is disabled (unchecked). Silence Period for Disconnect: The detection period, in seconds, before the call is released based on silence. The default is 120 seconds. Silence Detection Method: This setting can be set to "None" (silence detection option is disabled), "Packets Count" (according to packet count), "Voice/Energy Detectors" (according to energy and voice detectors (default)) or "All" (according to packet count and energy / voice detectors). Silence Threshold: The threshold of packet count, in percentage, below which is considered as silence. The default setting is 8 packets. Detail Level in Debug Log: The detail level of the log messages sent to syslog server. Default is 0 (off), max is 5 (full). CDR Server IP Address: An optional separate syslog server to collect CDRs only. If null and CDR is enabled, the output is mixed with the log messages and is routed to the syslog server IP. (Default: 0.0.0.0) CDR Report Level: This can be set to "None", (Call Detail Recording or CDR information isn't sent to the Syslog server, which is the default value), "End Call" (CDR information is sent to the Syslog server at the end of each Call) and, "Start & End Call" (CDR information is sent to the Syslog server at the start and at the end of each Call). Port Busy-Out Method  : If there is a network-side failure on the gateway, the POTS interfaces can be set to busy. If this is  checked, telephony ports are busied out (special tone) in case of LAN failure or proxy communication failure. The default is disabled (unchecked). Delay After Reset [sec]: Amount of time delay before answering calls after gateway reset. The default is 7 seconds. Max Number of Active Calls: This is the maximum number of active calls the PBX can process. It should be set to the number of PSTN lines active. Max Call Duration [min]: This is the maximum duration of a phone call. The default is 0, which means no maximum. Enable LAN Watchdog: When LAN Watchdog is enabled, the gateway's overall communication integrity is checked periodically. If no communication for about 3 minutes is detected, the gateway performs a self test. If the self test succeeds, the problem is logical link down (for example, Ethernet cable disconnected on the switch side), and the "Busy Out" mechanism is activated if enabled (EnableBusyOut = 1). Lifeline is activated if enabled. If the self test fails, the gateway restarts to overcome an internal fatal communication error (default: unchecked). Enable SAS: This setting is to enable/disable Stand-Alone Survivability (SAS) (default: unchecked). • SAS Registration Time: This is the time after which SAS is enabled (default: 20 seconds). SAS Local SIP UDP port: This is the UDP Port for SAS SIP signaling (default: 5080). SAS Local SIP TCP port: This is the TCP Port for SAS SIP signaling (default: 5080). SAS Local SIP TLS port: This is the TLS Port for SAS SIP signaling (default: 5081). SAS Default Gateway: This is the SAS Default Gateway IP address (default blank). SAS Short Number Length: This is the SAS short number length. Click on the Apply button to keep any changes made on this page.
Read more
  • 0
  • 0
  • 4725

article-image-multiple-templates-django
Packt
21 Oct 2009
13 min read
Save for later

Multiple Templates in Django

Packt
21 Oct 2009
13 min read
Considering the different approaches Though there are different approaches that can be taken to serve content in multiple formats, the best solution will be specific to your circumstances and implementation. Almost any approach you take will have maintenance overhead. You'll have multiple places to update when things change. As copies of your template files proliferate, a simple text change can become a large task. Some of the cases we'll look at don't require much consideration. Serving a printable version of a page, for example, is straightforward and easily accomplished. Putting a pumpkin in your site header at Halloween or using a heart background around Valentine's Day can make your site seem timely and relevant, especially if you are in a seasonal business. Other techniques, such as serving different templates to different browsers, devices, or user-agents might create serious debate among content authors. Since serving content to mobile devices is becoming a new standard of doing business, we'll make it the focus of this article. Serving mobile devices The Mobile Web will remind some old timers (like me!) of the early days of web design where we'd create different sites for Netscape and Internet Explorer. Hopefully, we take lessons from those days as we go forward and don't repeat our mistakes. Though we're not as apt to serve wholly different templates to different desktop browsers as we once were, the mobile device arena creates special challenges that require careful attention. One way to serve both desktop and mobile devices is a one-size-fits-all approach. Through carefully structured and semantically correct XHTML markup and CSS selectors identified to be applied to handheld output, you can do a reasonable job of making your content fit a variety of contexts and devices. However, this method has a couple of serious shortcomings. First, it does not take into account the limitations of devices for rich media presentation with Flash, JavaScript, DHTML, and AJAX as they are largely unsupported on all but the highest-end devices. If your site depends on any of these technologies, your users can get frustrated when trying to experience it on a mobile device. Also, it doesn't address the varying levels of CSS support by different mobile devices. What looks perfect on one device might look passable on another and completely unusable on a third because only some of the CSS rules were applied properly. It also does not take into account the potentially high bandwidth costs for large markup files and CSS for users who pay by the amount of data transferred. For example, putting display: none on an image doesn't stop a mobile device from downloading the file. It only prevents it from being shown. Finally, this approach doesn't tailor the experience to the user's circumstances. Users tend to be goal-oriented and have specific actions in mind when using the mobile web, and content designers should recognize that simply recreating the desktop experience on a smaller screen might not solve their needs. Limiting the information to what a mobile user is looking for and designing a simplified navigation can provide a better user experience. Adapting content You know your users best, and it is up to you to decide the best way to serve them. You may decide to pass on the one-size-fits-all approach and serve a separate mobile experience through content adaptation. The W3C's Mobile Web Initiative best practices guidelines suggest giving users the flexibility and freedom to choose their experience, and provide links between the desktop and mobile templates so that they can navigate between the two. It is generally not recommended to automatically redirect users on mobile devices to a mobile site unless you give them a way to access the full site. The dark side to this kind of content adaptation is that you will have a second set of template files to keep updated when you make site changes. It can also cause your visitors to search through different bookmarks to find the content they have saved. Before we get into multiple sites, let's start with some examples of showing alternative templates on our current site. Setting up our example Since we want to customize the output of our detail page based on the presence of a variable in the URL, we're going to use a view function instead of a generic view. Let us consider a press release application for a company website. The press release object will have a title, body, published date, and author name.In the root directory of your project (in the directory projects/mycompany), create the press application by using the startapp command: $ python manage.py startapp press This will create a press folder in your site. Edit the mycompany/press/models.py file: from django.db import models class PressRelease(models.Model): title = models.CharField(max_length=100) body = models.TextField() pub_date = models.DateTimeField() author = models.CharField(max_length=100) def __unicode__(self): return self.title Create a file called admin.py in the mycompany/press directory, adding these lines: from django.contrib import adminfrom mycompany.press.models import PressRelease admin.site.register(PressRelease) Add the press and admin applications to your INSTALLED_APPS variable in the settings.py file: INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.admin', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'mycompany.press',) In the root directory of your project, run the syncdb command to add the new models to the database: $ python manage.py syncdb We will be prompted to create a superuser, go ahead and create it. We can access the admin site by browsing to http://localhost:8000/admin/ and add data. Create your mycompany/press/urls.py file as shown: urlpatterns = patterns('', (r'detail/(?P<pid>d+)/$', 'mycompany.press.views.detail'), (r'list/$','django.views.generic.list_detail.object_list', press_list_dict), (r'latest/$','mycompany.press.views.latest'), (r'$','django.views.generic.simple.redirect_to', {'url': '/press/list/'})) In your mycompany/press/views.py file, your detail view should look like this: from django.http import HttpResponsefrom django.shortcuts import get_object_or_404from django.template import loader, Contextfrom mycompany.press.models import PressRelease def detail(request, pid): ''' Accepts a press release ID and returns the detail page ''' p = get_object_or_404(PressRelease, id=pid) t = loader.get_template('press/detail.html') c = Context({'press': p}) return HttpResponse(t.render(c)) Let's jazz up our template a little more for the press release detail by adding some CSS to it. In mycompany/templates/press/detail.html, edit the file to look like this: <html><head><title>{{ press.title }}</title><style type="text/css">body { text-align: center;}#container { margin: 0 auto; width: 70%; text-align: left;}.header { background-color: #000; color: #fff;}</style></head><body><div id="container"><div class="header"><h1>MyCompany Press Releases</h1></div><div><h2>{{ press.title }}</h2><p>Author: {{ press.author }}<br/>Date: {{ press.pub_date }}<br/></p><p>{{ press.body }}</p></div></body></html> Start your development server and point your browser to the URL http://localhost:8000/press/detail/1/. You should see something like this, depending on what data you entered before when you created your press release: If your press release detail page is serving correctly, you're ready to continue. Remember that generic views can save us development time, but sometimes you'll need to use a regular view because you're doing something in a way that requires a view function customized to the task at hand. The exercise we're about to do is one of those circumstances, and after going through the exercise, you'll have a better idea of when to use one type of view over another. Serving printable pages One of the easiest approaches we will look at is serving an alternative version of a page based on the presence of a variable in the URL (aka a URL parameter). To serve a printable version of an article, for example, we can add ?printable to the end of the URL. To make it work, we'll add an extra step in our view to check the URL for this variable. If it exists, we'll load up a printer-friendly template file. If it doesn't exist, we'll load the normal template file. Start by adding the highlighted lines to the detail function in the mycompany/press/views.py file: def detail(request, pid): ''' Accepts a press release ID and returns the detail page ''' p = get_object_or_404(PressRelease, id=pid) if request.GET.has_key('printable'): template_file = 'press/detail_printable.html' else: template_file = 'press/detail.html' t = loader.get_template(template_file) c = Context({'press': p}) return HttpResponse(t.render(c)) We're looking at the request.GET object to see if a query string parameter of printable was present in the current request. If it was, we load the press/detail_printable.html file. If not, we load the press/detail.html file. We've also changed the loader.get_template function to look for the template_file variable. To test our changes, we'll need to create a simple version of our template that only has minimal formatting. Create a new file called detail_printable.html in the mycompany/templates/press/ directory and add these lines into it: <html><head><title>{{ press.title }}</title></head><body><h1>{{ press.title }}</h1><p>Author: {{ press.author }}<br/>Date: {{ press.pub_date }}<br/></p><p>{{ press.body }}</p></body></html> Now that we have both regular and printable templates, let's test our view.Point your browser to the URL http://localhost:8000/press/detail/1/, and you should see our original template as it was before. Change the URL to http://localhost:8000/press/detail/1/?printable and you should see our new printable template: Creating site themes Depending on the audience and focus of your site, you may want to temporarily change the look of your site for a season or holiday such as Halloween or Valentine's Day. This is easily accomplished by leveraging the power of the TEMPLATE_DIRS configuration setting. The TEMPLATE_DIRS variable in the settings.py file allows you to specify the location of the templates for your site. Also TEMPLATE_DIRS allows you to specify multiple locations for your template files. When you specify multiple paths for your template files, Django will look for a requested template file in the first path, and if it doesn't find it, it will keep searching through the remaining paths until the file is located. We can use this to our advantage by adding an override directory as the first element of the TEMPLATE_DIRS value. When we want to override a template with a special themed one, we'll add the file to the override directory. The next time the template loader tries to load the template, it will find it in the override directory and serve it. For example, let's say we want to override our press release page from the previous example. Recall that the view loaded the template like this (from mycompany/press/views.py): template_file = 'press/detail.html't = loader.get_template(template_file) When the template engine loads the press/detail.html template file, it gets itfrom the mycompany/templates/ directory as specified in the mycompany/settings.py file: TEMPLATE_DIRS = ( '/projects/mycompany/templates/',) If we add an additional directory to our TEMPLATE_DIRS setting, Django will look in the new directory first: TEMPLATE_DIRS = ( '/projects/mycompany/templates/override/’, '/projects/mycompany/templates/',) Now when the template is loaded, it will first check for the file /projects/mycompany/templates/override/press/detail.html. If that file doesn't exist, it will go on to the next directory and look for the file in /projects/mycompany/templates/press/detail.html. If you're using Windows, use the Windows-style file path c:/projects/mycompany/templates/ for these examples. Therein lies the beauty. If we want to override our press release template, we simply drop an alternative version with the same file name into the override directory. When we're done using it, we just remove it from the override directory and the original version will be served (or rename the file in the override directory to something other than detail.html). If you're concerned about the performance overhead of having a nearly empty override directory that is constantly checked for the existence of template files, we should consider caching techniques as a potential solution for this. Testing the template overrides Let's create a template override to test the concept we just learned. In your mycompany/settings.py file, edit the TEMPLATE_DIRS setting to look like this: TEMPLATE_DIRS = ( '/projects/mycompany/templates/override/', '/projects/mycompany/templates/',) Create a directory called override at mycompany/templates/ and another directory underneath that called press. You should now have these directories: /projects/mycompany/templates/override//projects/mycompany/templates/override/press/ Create a new file called detail.html in mycompany/templates/override/press/ and add these lines to the file: <html><head><title>{{ press.title }}</title></head><body><h1>Happy Holidays</h1><h2>{{ press.title }}</h2><p>Author: {{ press.author }}<br/>Date: {{ press.pub_date }}<br/></p><p>{{ press.body }}</p></body></html> You'll probably notice that this is just our printable detail template with an extra "Happy Holidays" line added to the top of it. Point your browser to the URL http://localhost:8000/press/detail/1/ and you should see something like this: By creating a new press release detail template and dropping it in the override directory, we caused Django to automatically pick up the new template and serve it without us having to change the view. To change it back, you can simply remove the file from the override directory (or rename it). One other thing to notice is that if you add ?printable to the end of the URL, it still serves the printable version of the file we created earlier. Delete the mycompany/templates/override/ directory and any files in it as we won't need them again.
Read more
  • 0
  • 0
  • 15561
article-image-gateways-sipxecs-40-part-1
Packt
21 Oct 2009
5 min read
Save for later

Gateways in sipXecs 4.0: Part 1

Packt
21 Oct 2009
5 min read
Gateways provide the connectivity required to reach other systems. These systems can be other sipXecs PBX's, traditional phone lines, or Internet Telephony Service Providers (ITSPs).Connecting the IP phone system to the outside world is one of the most difficult tasks in making the phone system work. If the network infrastructure is configured properly for quality of service, the connection to the outside world can most likely be the source of any call quality problems. Traditional analog Plain Old Telephone Service (POTS) lines are the largest source of frustration. If you can avoid them by utilizing a digital type of service or an ITSP, by all means take that avenue. For those not so lucky, you'll learn more about them then you ever thought you needed to. Typically, volume levels, line disconnect, and echo are the most common problems. Most gateways will have some advanced settings for dealing with these issues but they are different for every manufacturer. Adding gateways There are three types of gateways that can be configured to work in sipXecs; managed, unmanaged, and SIP Trunks. A managed gateway is a hardware device that connects to a traditional phone line. sipXecs knows how to generate configuration files (plug and play) for it. An unmanaged gateway is either a hardware device for which sipXecs doesn't know how to generate configuration files, or it may be another SIP PBX. A SIP Trunk is a connection to an ITSP. Managed gateways At present, there are eight gateways for which sipXecs generates configuration information (ACME 1000 and AudioCodes Models MP114, MP118, Mediant 1000/2000/3000/BRI, and TP260). This is just a small cross section of gateways available in the market. If your gateway is not in this list, see the following Unmanaged gateways subsection. The following detailed information about managed gateways may prove to be useful in setting up an unmanaged gateway. For the following example screens, we'll utilize an AudioCodes MP114 FXO (Foreign Exchange Office) gateway. This particular gateway has four analog ports for connecting to POTS lines. Information on the gateway is available at http://www.audiocodes.com/products/mediapack-1xx. To  add the gateway, click on the Gateways menu item in the  Devices menu. As shown in the following screenshot, there are no gateways configured by default. To add the gateway, click on the Gateways menu item in the Devices menu. As shown in the following screenshot, there are no gateways configured by default. To add a managed gateway, click on the Add new gateway drop-down box and select the appropriate gateway. The gateway configuration page will be displayed as follows: The following configuration information can be configured on this page (click on the Show Advanced Settings hyperlink to display all configuration items): Name: A name given to the gateway (no spaces). Address: The IP address of the gateway or the fully qualified hostname of the gateway (see manufacturer's documentation for information on configuring IP address and other basic settings). Port: An optional setting for UDP or TCP port if a non-standard port is used. Set to 0 to ignore this field. Transport protocol : This can be manually configured to UDP or TCP to force the SIP transport protocol. If it is set to Auto, the transport is determined through a DNS query. Serial Number : This is the Ethernet MAC address of the gateway. Firmware Version : Certain gateways may have different configuration file information or formats depending on the version of firmware in the device. Select the version of firmware that is loaded in the gateway (see manufacturer's documentation). Location: It is possible to restrict the gateway by selecting a specific location for which it can be used. A location is represented by a group of users. A user group must be created for every location that needs to be distinguished (remember that users can be in more than one group). This setting allows routing of calls based on the location or the user from which the call originates (source routing). This is useful if users located in a branch office would like to have a gateway preference so that calls are routed through their local gateway, for example, to preserve WAN bandwidth or to use caller ID offered by an analog gateway based on the PSTN number assigned to it. Only if that gateway is not available, will call routing fall back to other gateways specified for the corresponding dialing rule. Shared: If this setting is checked, this gateway can be used by any user in any location, even if a specific location is selected. This setting is checked by default so that users in an identified location still use their preferred gateway, but the gateway can also be used by other users in other locations. Description : This is for documenting the system configuration. Information about the lines connected to the gateway is very useful here. With all of the configuration information entered, click on the OK button and the Gateway page will be displayed as follows with the new gateway on it. Click on the gateway name to reveal more configuration options, as shown in the following screenshot: With all of the configuration information entered, click on the OK button and the Gateway page will be displayed as follows with the new gateway on it. Click on the gateway name to reveal more configuration options, as shown in the following screenshot: In the following subsections, we'll explore the managed gateway settings available.
Read more
  • 0
  • 0
  • 4509

article-image-facebook-application-development-ruby-rails
Packt
21 Oct 2009
4 min read
Save for later

Facebook Application Development with Ruby on Rails

Packt
21 Oct 2009
4 min read
Technologies needed for this article RFacebook RFacebook (http://rfacebook.rubyforge.org/index.html) is a Ruby interface to the Facebook APIs. There are two parts to RFacebook—the gem and the plug-in. The plug-in is a stub that calls RFacebook on the Rails library packaged in the gem. RFacebook on Rails library extends the default Rails controller, model, and view. RFacebook also provides a simple interface through an RFacebook session to call any Facebook API. RFacebook uses some meta-programming idioms in Ruby to call Facebook APIs. Indeed Indeed is a job search engine that allows users to search for jobs based on keywords and location. It includes job listings from major job boards and newspapers and even company career pages. Acquiring candidates through Facebook We will be creating a Facebook application and displaying it through Facebook. This application, when added into the list of a user's applications, allows the user to search for jobs using information in his or her Facebook profile. Facebook applications, though displayed within the Facebook interface, are actually hosted and processed somewhere else. To display it within Facebook, you need to host the application in a publicly available website and then register the application. We will go through these steps in creating the Job Board Facebook application. Creating a Rails application Next, create a Facebook application. To do this, you will need to first add a special application in your Facebook account—the Developer application. Go to http://www.facebook.com/developers and you will be asked to allow Developer to be installed in your Facebook account. Add the Developer application and agree to everything in the permissions list. You will not have any applications yet, so click on the create one link to create a new application. Next you will be asked for the name of the application you want to create. Enter a suitable name; in our case, enter 'Job Board' and you will be redirected to the Developer application main page, where you are shown your newly created application with its API key and secret. You will need the API key and secret in a while. Installing and configuring RFacebook RFacebook consists of two components—the gem and the plug-in. The gem contains the libraries needed to communicate with Facebook while the plug-in enables your Rails application to integrate with Facebook. As mentioned earlier, the plug-in is basically a stub to the gem. The gem is installed like any other gem in Ruby: $gem install rfacebook To install the plug-in go to your RAILS_ROOT folder and type in: $./script/plugin install svn://rubyforge.org/var/svn/rfacebook/trunk/rfacebook/plugins/rfacebook Next, after the gem and plug-in is installed, run a setup rake script to create the configuration file in the RAILS_ROOT folder: $rake facebook:setup This creates a facebook.yml configuration file in RAILS_ROOT/config folder. The facebook.yml file contains three environments that mirror the Rails startup environments. Open it up to configure the necessary environment with the API key and secret that you were given when you created the application in the section above. development: key: YOUR_API_KEY_HERE secret: YOUR_API_SECRET_HERE canvas_path: /yourAppName/ callback_path: /path/to/your/callback/ tunnel: username: yourLoginName host: www.yourexternaldomain.com port: 1234 local_port: 5678 For now, just fill in the API key and secret. In a later section when we configure the rest of the Facebook application, we will need to revisit this configuration. Extracting the Facebook user profile Next we want to extract the user's Facebook user profile and display it on the Facebook application. We do this to let the user confirm that this is the information he or she wants to send as search parameters. To do this, create a controller named search_controller.rb in the RAILS_ROOT/app/controllers folder. class SearchController < ApplicationController before_filter :require_facebook_install layout 'main' def index view render :action => :view end def view if fbsession.is_valid? response = fbsession.users_getInfo(:uids => [fbsession.session_user_id], :fields => ["current_location", "education_history", "work_history"]) @work_history = response.work_history @education_history = response.education_history @current_location = response.current_location endend
Read more
  • 0
  • 0
  • 3936

article-image-theming-modules-drupal-6
Packt
21 Oct 2009
5 min read
Save for later

Theming Modules in Drupal 6

Packt
21 Oct 2009
5 min read
Our Target Module: What We Want Before we begin developing a module, here's a brief overview of what we want to accomplish. The module we will write in this article is the Philosophy Quotes module (philquotes will be our machine-readable name). The goal of this module will be to create a block that displays pithy philosophical quotes. We will implement the following features: Quotes should be stored along with other basic content, making it possible to add, modify, and delete this content in exactly the same way that we create other articles. Since our existing themes aren't aware of this quotes module, it must provide some default styling. We will progress through the creation of this module by first generating a new "quote" content type, and then building a theme-aware module. Creating a Custom Content Type As Drupal evolved, it incorporated an increasingly sophisticated method for defining content. Central to this system is the idea of the content type. A content type is a definition, stored in Drupal's database, of how a particular class of content should be displayed and what functionality it ought to support. Out of the box, Drupal has two defined content types: Page and Story. Pages are intended to contain content that is static, like an "About Us" or "Contact Us" page. Stories, on the other hand, are intended to contain more transient content—news items, blog postings, and so on. Creating new pages or stories is as simple as clicking on the Create Content link in the default menu. Obviously, not all content will be classified as either a page or a story, and many sites will need specialized content types to adequately represent a specific class of content. Descriptions of events, products, component descriptions, and so on might all be better accomplished with specialized content types. Our module is going to display brief quotes. These quotes shouldn't be treated like either articles or pages. For example, we wouldn't want a new quote to be displayed along with site news in the center column of our front page. Thus, our quotes module needs a custom content type. This content type will be very simple. It will have two parts: the text of the quote and the origin of the quote. For example, here's a famous quote: The life of man [is] solitary, poor, nasty, brutish, and short.—Thomas Hobbes. The text of this quote is "The life of man [is] solitary, poor, nasty, brutish, and short", and the origin in this example is Thomas Hobbes. We could have been more specific and included the title of the work (Leviathan) or even the exact page reference, edition, and so on. But all this information, in our simple example, would be treated as the quote's origin. Given the simplicity of our content type, we can simply use the built-in Drupal content type tool to create the new type. To generate even more sophisticated content types, we could install the CCK (Content Creation Kit) module, and perhaps some of the CCK extension modules. CCK provides a robust set of tools for defining custom fields, data types, and features. But here our needs are simple, so we won't need any additional modules or even any custom code to create this new content type. Using the Administration Interface to Create a Content Type The process of creating our custom content type is as simple as logging into Drupal and filling out a form. The content type tool is in Administer | Content management | Content types. There are a couple of tabs at the top of the page: Clicking the Add content type tab will load the form used to create our new content type. On this form, we need to complete the Name and Type fields—the first with a human-friendly name, and the second with a computer-readable name. Description is often helpful. In addition to these fields, there are a few other form fields under the Submission form settings and Workflow settings that we need to change. In the Submission form settings section, we will change the labels to match the terminology we have been using. Instead of Title and Body, our sections will be Origin and Text. Changing labels is a superficial change. While it changes the text that is displayed to users, the underlying data model will still refer to these fields as title and body. We will see this later in the article. In the Workflow settings section, we need to make sure that only Published is checked. By default, Promoted to front page is selected. That should be disabled unless you want new quotes to show up as content in the main section of the front page. Once the form is complete, pressing the Save content type button will create the new content type. That's all there is to it. The Create content menu should now have the option of creating a new quote: As we continue, we will create a module that displays content of type quote in a block. Before moving on, we want a few pieces of content. Otherwise, our module would have no data to display. Here's the list of quotes (as displayed on Administer | Content management | Content) that will constitute our pool of quotations for our module.  
Read more
  • 0
  • 0
  • 1855
article-image-getting-grips-facebook-platform
Packt
21 Oct 2009
6 min read
Save for later

Getting to Grips with the Facebook Platform

Packt
21 Oct 2009
6 min read
The Purpose of the Facebook Platform As you develop your Facebook applications, you'll find that the Facebook Platform is essential—in fact you won't really be able to do anything without it. So what does it do? Well, before answering that, let's look at a typical web-based application. The Standard Web Application Model If you've ever designed and built a web application before, then you'd have done it in a fairly standard way. Your application and any associated data would have been placed on a web server, and then your application users will access it from their web browsers via the Internet: The Facebook model is slightly different. The Facebook Web Application Model As far as your application users are concerned, they will just access Facebook.com and your application, by using a web browser and the Internet. But, that's not where the application lives—it's actually on your own server: Once you've looked at the Facebook web application model and realized that your application actually resides on your own server, it becomes obvious what the purpose of the Facebook Platform is—to provide an interface between your application and itself. There is an important matter to be considered here. If the application actually resides on your server, and your application becomes very successful (according to Facebook there are currently 25 million active users), then will your server be able to able to cope with that number of hits? Don't be too alarmed. This doesn't mean that your server will be accessed every time someone looks at his or her profile. Facebook employs a cache to stop that happening: Of course, at this stage, you're probably more concerned with just getting the application working—so let's continue looking at the Platform, but just bear that point in mind. Different components of the Facebook platform There are three elements to the Facebook Platform: The Facebook API (Application Programming Interface) FBML—Facebook Markup Language FQL—Facebook Query Language We'll now spend some time with each of these elements, and you'll see how you can use them individually, and in conjunction to make powerful yet simple applications. The great thing is that if you haven't got your web server set up yet, don't worry, because Facebook supplies you with all of the tools that you would need in order to do a test run with each of the elements. The Facebook API If you've already done some programming, then you'll probably know what an API (or Application Programming Interface) is. It's a set of software libraries that enable you to work with an application (in this case, Facebook) without knowing anything about its internal workings. All you have to do is obtain the libraries, and start making use of them in your own application. Now, before you start downloading files, you can actually learn more about their functionality by making use of the Facebook API Test Console. The Facebook API Test Console If you want to make use of the Facebook Test Console, you'll first need to access the Facebook developers' section—you'll find a link to this at the bottom of every Facebook page: Alternatively, you can use the URL http://developers.facebook.com to go there directly in your browser. When you get to this page, you'll find a link to the Tools page: Or, again, you can go directly to http://developers.facebook.com/tools.php, where you'll find the API Test Console: You'll find that the API Test Console has a number of fields: User ID—A read-only field which (when you're logged on to Facebook) unsurprisingly displays your user ID number. Response Format—With this, you can select the type of response that you want, and this can be: XML JSON Facebook PHP Client Callback—If you are using XML or JSON, then you can encapsulate the response in a function. Method—The actual Facebook method that you want to test. Once you've logged in, you'll see that your User ID is displayed and that all the drop-downs are enabled: You will also notice that a new link, documentation, appears on the screen, which is very useful. All you have to do is to select a method from the drop-down list, and then click on documentation. Once you've done that you'll see: A description of the method The parameters used by the method An example return XML A description of the expected response. The FQL equivalent (we will discuss this later in the chapter.) Error codes For now, let's just change the Response Format to Facebook PHP Client, and then click on Call Method to see what happens: In this case, you can see that the method returns an array of user ids—each one is the ID of one of the friends of the currently logged in user (that is your list of friends because you're the person logged in). You could, of course, go on to use this array in PHP as part of your application, but don't worry about that at the moment. For the time being, we'll just concentrate on working with our prototyping in the test console. However, before we move on, it's worth noting that you can obtain an array of friends only for the currently logged in user. You can't obtain the list of friends for any other user. So, for example, you would not be able to use friends. get on id 286601116 or 705175505. In fact, you wouldn't be able to use friends. get for 614902533 (as shown in the example) because that's my ID and not yours. On the other hand, having obtained a list of valid IDs we can now do something more interesting with them. For example, we can use the users.getinfo method to obtain the first name and birthday for particular users: As you can see, a multidimensional array is returned to your PHP code (if you were actually using this in an application). Therefore, for example, if you were to load the array into a variable $birthdays, then $birthdays[0][birthday] would contain January 27, 1960. Of course, in the above example, the most important piece of information is the first birthday in the array—record that in your diary for future reference. And, if you're thinking that I'm old enough to be your father, well, in some cases this is actually true: Now that you've come to grips with the API Test console, we can turn our attention to FBML and the FBML Test Console.
Read more
  • 0
  • 0
  • 1954

article-image-creating-pseudo-3d-imagery-gimp-part-2
Packt
21 Oct 2009
6 min read
Save for later

Creating Pseudo-3D Imagery with GIMP: Part 2

Packt
21 Oct 2009
6 min read
The next step would be to play around with Layer Modes which, I believe, is one of the most exciting aspects of graphic design. Let's leave layer “lower shine” for awhile and let's get back to layer “upper shine”, and change its layer mode to make it look more appealing and following a scheme in accordance to the color of the sphere. To do this, let's select “upper shine” layer on the Layers Window and right above the Opacity Slider is a dropdown menu containing lots of interesting layer modes, each having its own distinct advantages. You can play around and choose whichever suits your vision the best. I chose Overlay for that matter. Ever since I've started GIMPing, this layer mode has been my best friend for a couple of years already, it works like a charm most of the time.  I wonder though why on some applications, applying the overlay layer mode does different results.  As in the case of Photoshop, the closest I could get with GIMP's overlay is the Screen mode.  You've got to play around a bit and see which works best for you. Do the same thing for the “lower shine” layer, choosing Overlay as the layer mode.  Then, whenever you see fit, you can duplicate the layers to achieve a multiplied effect of the mode. I did that because it felt that something was still missing in the luminous aspect of the shine. So I selected each layer, duplicated them both and voila. To duplicate a layer, you can either right click on the layer name and choose Duplicate Layer from the choices or just press the Duplicate Button on the bottom part of the Layers Window. Duplicated Layers Next, we'll add additional highlights to better emulate specular reflections. And again, we're exploiting the Ellipse Select Tool and another new technique called Feathering. I don't know exactly the definition of feathering in CG, but as far as my experience goes, feathering is a technique from sets of tools where you soften the edges of a selection creating a subtle transition and blurred edges. Create a new layer at the top of the layer stack and call it “blurred shine”, then give it a Layer Fill Type of Transparency, just like what we did with the previous layers.  And with layer 'blurred shine” active, let's create an elliptical selection on the upper left hand part of the sphere, just where the sharp shine has been cast. Creating the Specular Selection With the selection active, right click on the Image Window and choose Select > Feather, then input a value for the feather and the unit to be used. I used 50 pixels. You might have noticed now that the selection seemed to have become smaller, and that's alright, that means you've done it right.  And with the marching ants still active, grab the Bucket Fill Tool over at the Toolbox Window or press SHIFT + B to activate it. Change your foreground color to something close to white or simply pure white, then with the Bucket Fill Tool active, click on the active selection. Tadaaaa! You just created a replica of a specular highlight, though not so close enough. What's great about feathering selections as opposed to applying a blur filter is that you only blur the selection border and not the entire selection. So, say, you have a picture of yourself and you wanted your face fade out smoothly on a vast landscape that you have photographed. Simply create a selection around your face, then apply a Feather to that selection, invert the selection and delete the outer parts, thus leaving only your face and the landscape behind (supposing you have your picture on a separate layer above the landscape layer.) Feathering the Selection Applying the Color with the Bucket Fill Whew, that was pretty quick, isn't it? I hope you agree with me on that.  If so, let's create another one, though smaller and placed just on the left of the blurred shine.  Create a new layer for this new blurred shine and name it “small blurred shine”.  Follow the same procedure for the feathering and color-filling. I used the same feather value for the smaller selection (even though it obviously is smaller), just so it almost affects the center of the selection, blurring the whole selection already, which is what I like for this part. And then, just like what we did with the upper and lower shine respectively, we'll change the Layer Modes to Overlay and duplicate the layers as we see fit.  Doing so results in this image: Blurred Shines Overlay Our sphere now looks a lot better than it had been when we first added its color. However, the shading still looks a bit flat and volumeless. To deal with that, we'll simulate the strength with which the light diffused our sphere object, creating deeper shadows on the opposite side of the light source. Duplication of layers is not only a matter of multiplying the effects of layer effects or such, but it can also be a good way to trace your changes, or better yet, as safe backups where working on the duplicate doesn't affect the original one and you can go back each time to the untouched layer anytime you want to see the differences that have been made.  But be careful though, the more layers and contents of each layer you have, the more computing memory will be consumed and will eventually cause a system slow down. Let's select the “sphere” layer and duplicate in once.  Automatically, the duplicate layer which is now named “sphere copy” becomes the active layer.  Right Click on “sphere copy” layer and choose Alpha to Selection to create a selection out of the fully opaque sphere. Next step is to shrink the selection such that we create a smaller elliptical selection inside the sphere.  To do this, right click on the Image Window and choose Select > Shrink.  Then on the pop up window that appears, type in an appropriate value for the shrinking. I chose 50 pixels. Shrinking the Selection Shrinked Selection Remember how we moved the selection last time? I believe you do. To translate/move our selection, grab the Ellipse Select Tool and activate the selection by clicking on it (clicking the middle portion of the selection makes this easier) until you see your cursor change into crossed arrows, this means you have just activated the move tool for the selection. And since the light is coming from the upper left direction, we would want to move the selection over to the location where the specular reflections are and where the lightest shading is.  Thats because later on, we'll be using this same selection to create shadows on the opposite side of the shade.  Now go ahead and drag the selection over to the upper left portion of the sphere.
Read more
  • 0
  • 0
  • 3995
Modal Close icon
Modal Close icon