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-handler-and-phase-apache-axis2
Packt
21 Oct 2009
5 min read
Save for later

Handler and Phase in Apache Axis2

Packt
21 Oct 2009
5 min read
(For more resources on Axis2, see here.) Handler In any messaging system, the interceptor has its factual meaning in the context of messaging, where it intercepts the flow of messaging and does whatever task it is assigned to do. In fact, an interceptor is the smallest execution unit in a messaging system, and an Axis2 handler is also an interceptor. Handlers in Axis are stateless, that is, they do not keep their pass execution states in the memory. A handler can be considered as a logic invoker with the input for the logic evaluation taken from the MessageContext. A Handler has both read and write access permissions to MessageContext (MC) or to an incoming SOAP message. We can consider MessageContext as a property bag that keeps incoming or outgoing messages (maybe both) and other required parameters. It may also include properties to carry the message through the execution chain. On the other hand, we can access the whole system including the system runtime, global parameters, and property service operations via the MC. In most cases, a handler only touches the header block part of the SOAP message, which will either read a header (or headers), add a header(s), or remove a header(s). (This does not mean that the handler cannot touch the SOAP body, nor does it mean that it is not going to touch the SOAP body.) During reading, if a header is targeted to a handler and is not executing properly (the message might be faulty), then it should throw an exception, and the next driver in the chain (in Axis2, it is the Axis engine) would take the necessary action. A typical SOAP message with few headers is shown in the figure given below: Any handler in Axis2 has the capability to pause the message execution, which means that the handler can terminate the message flow if it cannot continue. Reliable messaging (RM) is a good example or use case for that scenario, when it needs to pause the flow depending on some of the preconditions and the postconditions as well and it works on a message sequence. If a service invocation consists of more than one message, and if the second message comes before the first one, then the RM handler will stop (or rather pause) the execution of the message invocation corresponding to the second message until it gets the first one. And when it gets, the first message is invoked, and thereafter it invokes or resumes the second message. Writing a Simple Handler Just learning the concepts will not help us in remembering what we have discussed. For that, we need to write a handler and see how it works. Writing a handler in Axis2 is very simple. If you want to write a handler, you either have to extend the AbstractHandler class or implement the Handler interface. A simple handler that extends the AbstractHandler class will appear as follows: public class SimpleHandler extends AbstractHandler{ public SimpleHandler() { }public InvocationResponse invoke(MessageContext msgContext) throws AxisFault { //Write the processing logic here // DO something return InvocationResponse.CONTINUE; }} Note the return value of the invoke method. We can have the following three values as the return value of the invoke method: Continue: The handler thinks that the message is ready to go forward. Suspend: The handler thinks that the message cannot be sent forward since some conditions are not satisfied; so the execution is suspended. Abort: The handler thinks that there is something wrong with the message, and cannot therefore allow the message to go forward. In most cases, handlers will return InvocationResponse.CONTINUE as the return value. When a message is received by the Axis engine, it calls the invoke method of each of the handlers by passing the argument to the corresponding MessageContext. As a result of this, we can implement all the processing logic inside that method. A handler author has full access to the SOAP message, and also has the required properties to process the message via the MessageContext. In addition, if the handler is not satisfied with the invocation of some precondition, the invocation can be paused as we have discussed earlier (Suspend). If some handler suspends the execution, then it is its responsibility to store the message context, and to forward the message when the conditions are satisfied. For example, the RM handler performs in a similar manner. Phase The concept of phase is introduced by Axis2, mainly to support the dynamic ordering of handlers. A phase can be defined in a number of ways: It can be considered a logical collection of handlers. It can be considered a specific time interval in the message execution. It can be considered a bucket into which to put a handler. One can consider a phase as a handler too. A flow or an execution chain can be considered as a collection of phases. Even though it was mentioned earlier that an Axis engine calls the invoke method of a handler, that is not totally correct. In fact, what the engine really does is call the invoke method of each phase in a given flow, and then the phase will sequentially invoke all the handlers in it (refer to the following figure). As we know, we can extend AbstractHandler and create a new handler; in the same way one can extend the Phase class and then create a new phase. But remember that we need not always extend the Phase class to create a new phase. We can do it by just adding an entry into axis2.xml (All the configuration that requires starting axis2 is obtained from axis2.xml). A phase has two important methods—precondition checking and postcondition checking. Therefore, if we are writing a custom phase, we need to consider the methods that have been mentioned. However, writing a phase is not a common case; you need to know how to write a handler.
Read more
  • 0
  • 0
  • 5045

article-image-integrating-zimbra-collaboration-suite-microsoft-outlook
Packt
21 Oct 2009
11 min read
Save for later

Integrating Zimbra Collaboration Suite with Microsoft Outlook

Packt
21 Oct 2009
11 min read
Introduction Let's face it, in today's business environment, there is only one email client that truly matters. I am not saying it is the best client, or that it offers more features, and I certainly am not saying it is the most secure. What I am saying is that you would be hard pressed to walk into an organization, of let's say more than 10 desktops, and not see users checking their email with Microsoft Outlook. Zimbra Collaboration Suite offers uncanny support for Outlook including: Native Sync with MAPI Support for both Online and Offline Modes Cached mode operation Support for multiple calendars Here, we will discuss these features and focus on configuring Outlook to work with the Zimbra server. As you will see with a Zimbra back end and an Outlook client, it is transparent to your users whether you are using Microsoft Exchange or Zimbra Collaboration Suite as your back end product. This transparency to users makes the migration from Exchange to Zimbra that much easier in the eyes of your users, especially when it comes to user training. The ability to seamlessly integrate Zimbra and Outlook is one of Zimbra's strongest assets and one of its strongest arguments for making the transition from Exchange to Zimbra. However, if you want to use the full power of Zimbra (not only the fancy look but great features such as the searches), you should use the Web Client. We will take a detailed look at Zimbra integration with Outlook, including: The Zimbra Connector for Outlook (ZCO) A look at Zimbra integration Sharing Outlook folders Outlook uses the Messaging Application Programming Interface (MAPI) to allow programs to communicate with messaging systems and stores. MAPI is proprietary to Microsoft and is key to Zimbra being able to synchronize and work with Outlook. Zimbra uses a connector to facilitate this communication—called the Zimbra Connector—for Outlook. The PST Import Wizard One of the beauties of Outlook's integration in Zimbra is that you won't start from scratch: Zimbra gives you tools that are able to import your data (emails, calendars, contacts, etc) either from a concurrent solution's server (Exchange or Domino) or directly from a PST file (the file used by Outlook to store all its data).   We'll have a look at the PST Import Wizard. To download it: Log in to the Administration Console at https://zimbra.emailcs.com:7071/. Click on the Downloads tab on the left of the navigation pane. 3. In the Content Pane, click on the PST Import Wizard to download the executable file. 4. Save the file to the local computer, or a network accessible shared folder. 5. Double click the .exe file to launch the wizard (there's no installation process). 6. Click on Next on the presentation page. 7. In the Hostname field enter: zimbra.emailcs.com. 8. In the Port field you can leave the default (80) and let the Use Secure Connection box unchecked. 9. In the Username field, enter your Zimbra's user (worker@emailcs.com) and in the Password field your Zimbra's password. Click on the Next button. You will now have to select the PST file that you want to import into the Zimbra server. The Zimbra Import Wizard helps you as it opens the default Outlook PST's directory when you click on the Browse button. Once you have selected the PST you want to import and clicked on the Open button, you can now click on the Next button of the initial window. Now, you can choose how your data will be imported: Import Junk-Mail Folder: If you leave this box checked, all your spam will be imported to the server and marked as spam on the server. Import Deleted Items Folder: With this, the deleted mails will be imported on the server. Ignore previously imported items: This option is used when you're importing your data in several attempts. If you leave it checked, the already imported mails won't be imported again. Import items received after: Checking this box and choosing a date in the calendar next to it, allows us to do a partial import based on date. Import messages with some headers but no message body: You should leave this one checked as it imports some badly formatted mails. Convert meeting, organized by me, from my old address to my new address: You need to check this box (and enter your previous email address) if you're getting a new email address on the Zimbra server. If you don't, the meetings will be imported but you won't be the owner. Migrate private appointments: This one is your own choice as Zimbra does not handle (yet) the private items; all the imported appointments will be viewable by anyone you share your calendar with.   Once your choices are made, you can click on the Next button. 14. Click OK in the confirmation window. 15. Next window will show you the import evolution (number of items and percentage). You can stop the import at anytime and start again later. Once the import is finished, a window pops up with a summary of the import session. 16. You can click on the OK button of the summary window then Finish in the last window. The Zimbra Connector for Outlook The Zimbra Connector for Outlook (ZCO) is a downloadable .msi installable file that must be installed on the desktop in order for Outlook and Zimbra to communicate. To download the ZCO to the client: Log in to the Administration Console at https://zimbra.emailcs.com:7071. Click on the Downloads tab on the left of the navigation pane. 3. In the Content Pane, click on the Zimbra Connector for Outlook to download the .msi installable file. Save the file to the local computer, or a network accessible shared folder. Double click the .msi file to start the installation process. The installation wizard will begin and go ahead and accept the License Agreement and accept all of the defaults. Once complete click FINISH. The ZCO creates a brand new profile within Outlook, called Zimbra. If you had previous profile(s) created on your computer, be sure to choose the "Zimbra" one. The ZCO is now installed, and the first time we run Outlook on this client, the connector will prompt us for configuration information. Zimbra currently supports Outlook 2003 only. In the Server Name field, enter: zimbra.emailcs.com. For port leave the default of 80. Email address will be the email address for this user. In our case, we will use the Worker Bee with an email address of worker@emailcs.com. For the password, enter the same password Worker would use to log in to the AJAX web client. Once completed, click OK and Outlook will open Worker's email box. The ZCO will now sync the Global Access List and will get all the emails from the server locally. It means that if you imported lots of item previously, you might need some time to get them back into Outlook from the server. Luckily, then the sync process happens in the background. As you can see in the following screenshot, the folders we created in the Web Client are now configured in Outlook. The first time Outlook is opened, it automatically performs a send/receive with the Zimbra server. After this initial synchronization, there is nothing a user needs to do from then on to initiate synchronization with the server. There is also nothing the user needs to set-up to let Outlook know whether or not the user is Online—connected to the server, or Offline—disconnected from the server. Outlook automatically checks the status and acts accordingly. Therefore, a user need not be connected to the server to work with email that has already been received, check the address book, or work with the Calendar. All changes that the user makes in Offline mode, will synchronize with the server the next time the server is connected and Outlook is online. At this time, we should take a quick look around Outlook and see how integrated Zimbra really is with Outlook. A Look at Zimbra Integration The integration of Zimbra is more than just the ability to send and receive email. Outlook is now acting as the front end to create contacts, appointments, and tasks that will be stored on the server. Let's take a moment to look at each one individually. Contacts The easiest way to see the integration of contacts between Outlook and Zimbra is to compose a new mail message, and instead of typing in an email address, click on the TO: button and select Global Address List from the Address Book drop-down menu. As you can see, this feature looks exactly the same whether you are using Exchange or Zimbra as your back end collaboration server. Users are familiar with this look and feel, and the ability to select users that are within the organization's Global Address List. This list comes directly from the Zimbra server and is maintained there as well. The user also has the option to select the own personal contact list. This list could be created and maintained either via the web client, through Outlook directly, or both as they will synchronize together. Appointments In most work organizations, the ability to create appointments, invite people to attend, and check invitees schedule is a key function of Exchange and Outlook. Luckily for us, the same functionality could be used with Zimbra and Outlook. As seen in the following figure, the process for creating an appointment is exactly the same. In the Calendar application, click New --> Appointment. Click on the Invite Attendees button. Click the To button and select the Global Address List from the drop-down menu. Select the CEO from the address list and click OK. Click on the Scheduling tab.   The Calendar is synced with the Zimbra server and is able to check the availability of the users within the organization, a key feature of any collaboration suite. Once you have found a schedule when all the attendees are free, go back to the Appointment tab, type in a Subject for your appointment then click on the Send button. The last feature we will look at is Sharing Outlook folders. Sharing Outlook Folders Users have the option to share any Outlook folder with users in the Global Address List. Essentially, this is the same ability we covered in an earlier chapter with the Web Client for the Contacts or Calendar. However, here the process is different. Users could be delegated different levels of access to Outlook folders. These levels include: Read View items in folder only Edit Edit any contents in the folder Create Create/add items to the folder Delete Delete/modify items in the folder Act on workflow Respond to meeting and task requests Administer Folder Modify the permissions on the folder There are also predefined roles that users could assign to other users in the Global Address List including: Administrator Has all rights to the folder listed above Delegate Has access to all rights except for Administer folder Editor Access to Read, Edit, Create and Delete Author Access to Read and Create Reviewer Read only To assign roles and rights to the folder: 1. Right click the folder and click Properties. 2. Click on the Sharing tab. 3. Click Add and select CEO from the Global Address List. 4. With CEO highlighted, select Administrator from the Permission Level drop-down-box. 5. With Administrator selected, you should be able to see all of the Permissions selected. 6. Change the Permission Level to Reviewer and you will see that only Read items, is selected. 7. Go ahead and play with the various levels so you can get a feel for the different permissions associated with the various levels. 8. Once complete, click OK. An email will be sent to the CEO informing him that he now has Administrator access to the Inbox of the Worker Bee. In order for the CEO to work with the new Shared Folder (the Worker's Inbox in this case), the CEO would simply: 1. Click on File --> Open --> Other User's Mailbox in the Outlook Menu bar. 2. Select Worker from the Global Address List. 3. Once the folder is added to Outlook, click on the Send/Receive button to synchronize the folder. Summary The goal of this article was to take a brief look at using the Microsoft Outlook client as a front end to the Zimbra Collaboration Suite. In my experience, users do not like change and they tend to be comfortable with applications they are familiar with. One of the most common objections to changing email systems is that users rely so heavily on their email and contacts that they do not want to have to learn a whole new system to access them. Hopefully, if I have done my job, you could now see how users need not be afraid of moving to a Zimbra system, because in the end, their everyday life and functionality is not going to change much. They could still use the tool that they are most familiar with, but still have the added benefit of using the AJAX Web Client when they are on the road or away from their desks.
Read more
  • 0
  • 0
  • 5411

article-image-supporting-editorial-team-drupal-6
Packt
21 Oct 2009
16 min read
Save for later

Supporting an Editorial Team in Drupal 6

Packt
21 Oct 2009
16 min read
What you will do In this article, you will: Create a team Add Roles to support the team Define new Node Content types Configure permissions to support the Roles Handle a former (and disgruntled) team member The Creative team Let's take a quick look at Drupal's jargon regarding teams. Users—the logins of the individuals that make up a team Roles—the different 'job descriptions' based on a person's responsibilities Permissions—the granting of authorization to perform a Drupal function As the system administrator, you are authorized to perform any action within the Drupal environment, but you would not want every member of a team to have this absolute capability, or else you would soon have chaos. Let's first create a team. Then, we will look at assimilating that team into the Drupal environment. Our Creative team will be made up of individuals, each having one or more of the responsibilities mentioned below (Note: the titles are not Drupal terms): Copy Writers—are the writers of short articles Feature Writers—are the writers of long pieces, in which style matters a much as content Ad Writers—are the writers of internal and external advertising that will appear in blocks Proofreaders—are the reviewers who check pieces for spelling, grammar and usage errors Associate Editors—are the reviewers that are concerned with style, readability, and continuity Style Editors—are responsible for the formatting of content Graphic Artists—are the creators of the illustrations and images that are used as copy Senior Editor—is responsible for the quality of all of the above Moderator—manages postings by site visitors, such as comments and blog posts Blogger—creates blog entries Administrator—addresses the aspects of the site unrelated to content With our team assembled, let's move on to creating the roles in our site. Roles Drupal comes with three roles installed: creator (also known as userID1), authenticated user and anonymous user. Only the latter two are listed when assigning permissions, because the creator role can do everything, including things that you might not want the administrator to be able to do. It's best not to use the creator's login as the administrator login. A separate administrator role should be created and granted the appropriate permissions. So, looking at the list above, we will need to create roles for all of our team members. Creating roles in Drupal is a quick and easy process. Let's create them. Activity 1: Creating Roles The Name of the role is assigned as per the responsibilities of the team member. Login as the administrator. Select the User management option. Select the Roles option. Enter the name of the role in the text box, as shown in the following screenshot, and then click on the Add role button. We'll add the rest of the roles in the same way. After a couple of minutes, we have the entire team added, as seen in following screenshot. The edit role links are locked for anonymous user and authenticated user, because those roles should remain constant and never be edited or deleted. Node Content types The default installation of Drupal contains two Node Content types namely: Page and Story. Some modules, when activated, create additional Node Content types. One such example is the Blog entry, and another is an Event, which is used when using an event calendar. We're using the term Node Content to differentiate content nodes in Drupal, such as Pages and Stories, from other non-node types of content, such as Blocks, which is the generic term for anything on the page. What is the purpose of having different Node Content types? If we want a feature  writer to be able to create Features, then how do we accomplish that? Currently, we have Stories and Pages as our Node Content types. So, if we give the Feature writer the ability to create a Page, then what differentiates that Page from any other Page on our site? If we consider a Page as a Feature, then anyone who can create a Page has created a Feature, but that's not right, because not every Page is a Feature. Activity 2: Node Content for our Roles Because we have role types that we want to limit to working with their respective Node Content types, we will need to create those Node Content types. We will assign a Node Content type of Feature for Feature Writers, Ads for Ad Writers, and so on. Let's create them. From the admin menu, we'll select Content management. On the Content management page, we'll choose Content types. The Node Content types are listed, and from the top of the page we'll select Add content type. We're going to start with the Feature writer, so in the Name field we'll enter Feature. The next field, Type, determines the term that will be used to construct the default URL for this Node Content type. We'll enter feature as the text value for this field. In the Description field, we'll enter a short description, which will appear next to the Node Content type's link on the admin page, as follows: Next, we'll click on the Workflow settings link to display the additional workflow fields. When our Feature Writer completes a piece, it will not be published immediately. It will have to be proofread and undergo an editorial review. So, we'll deselect the Published and Promote to front page boxes. At this point we've configured the new Node Content type as per our needs, so we'll click on the Save button, and then we can see it listed, as shown in the screenshot below. We already have a Node Content type of Blog entry, which was created by the Blog module. The only other Role that requires its own Node Content type is the Ad Writer. This is because the other Roles defined will only edit existing Node Content,  as opposed to creating it. It is here that we run into trouble. The pieces that are 'grabbed' by Drupal to appear (usually) at the center of the screen, which we have been referring to as Node Content, are nodes, whether a Page, a Story, or now a Feature. The small blocks that appear around the sides, or on top, or at the bottom, are Blocks. Because they are placed in those positions, and are not available for selection as Node Content, they are not nodes. The Benefit of BlocksWhen looking at a typical web page of a CMS site, you will see a main body area with Node Content, such as articles, and also small blocks of information elsewhere on the page, such as in the left and right margins, or along the top or bottom. The main content, nodes, are limited, as to where they appear. However, each of the blocks can be configured to appear on any or every page of the site. That is why ads are best created as blocks, so that they can be placed where they will be the most effective. Nodes are created via the Create content function, and that function is available from the front page to anyone who is granted the permission. Using the admin menu is not necessary. On the other hand, blocks are created and edited from the Block page, which is an admin function. Although we can grant that capability to a user without granting any other admin capabilities, it would be much better if we could have an Ad Writer create ads in the same way that they create other Node Content. The reason for this is that with nodes, separate permission can be given to create a node and to administer a node. With  blocks, there is only one permission. You can create, edit, delete, and rearrange all of the blocks, or none. This opens the door to an accidental disaster. We don't want the Ad Writer doing anything but creating ad copy. So, in order to address this concern, we've added a module to our site: Node blocks. This module allows us designate a Node Content type (other than Page and Story) to be used as a Block. With that in mind, let's create our final Node Content type. Where can you find this module? This module, as well as other modules, can be found at http://drupal.org/project/modules. Activity 3—creating a Block Node Content type We'll start by repeating Steps 1 to 3 from the previous activity. In the Title field, we'll type in Ad. In the Type field, we'll type in ad. For the description, we'll enter Advertisement copy that will be used as blocks. We'll click on Workflow settings and deselect Published and Promoted to front page, as we did with the Feature. There is a new heading in this dialog, Available as Block, as seen in the following screenshot. This comes from the module that we've added. We'll select Enabled, which will make any piece created with this Node Content type available as a Block. That's all we need to do, so now we'll save our new Node Content type   Permissions The way that we enable one user to do something that the other cannot is by creating different user types (which we have done), different Node Content types—where necessary—(which again has been done), and then assign permissions to the user types (which we'll do now). The administrator will not be listed as a user type under Permissions, because if permissions were accidentally removed from the administrator, there might be no other user type that has the permissions to restore them. Activity 4: Granting Permissions Let's now assign to the members of the Creative team the Permissions that suit them best. From the admin menu we'll select User management. On the User management page we'll choose Permissions. The screenshot below shows us the upper portion of the screen. There are numerous permissions, and we now have numerous User types, so the resulting grid is very large. Rather than step-by-step illustrations, I'll simply list each Role and the Permissions that should be enabled in the form of Heading→Permission. Ad Writer node module→access content node module→create ad content node module→delete any ad content node module→delete own ad content node module→edit any ad content node module→edit own ad content node module→view revisions fckeditor module→access fckeditor Because of the number of Node Content types, each having several permissions as seen above, combined with the permissions being alphabetical by verb within the heading, instead of Content type, the necessary permissions are somewhat distant from each other and require scrolling to find them all. Feature Writer node module→access content node module→create feature content node module→delete any feature content node module→delete own feature content node module→edit any feature content node module→edit own feature content node module→view revisions fckeditor module→access fckeditor Blogger blog module→create blog entries blog module→delete own blog entries blog module→edit own blog entries node module→access content node module→view revisions fckeditor module→access fckeditor Associate Editor—The Associate Editor is concerned with content, which means editing it. The ability to create or delete content, to affect where the content appears, and so on, is not required for this Role. fckeditor module→access fckeditor node module→access content node module→edit any ad content node module→edit any feature content node module→edit any page content node module→edit any story content node module→revert revisions node module→view revisions path module→create URL aliases Copy Writer fckeditor module→access fckeditor node module→access content node module→create page content node module→create story content node module→delete own page content node module→delete own story content node module→edit own page content node module→edit own story content node module→view revisions Graphic Artist blog module→edit any blog entry fckeditor module→access fckeditor fckeditor module→allow fckeditor fle uploads node module→access content node module→edit any ad content node module→edit any feature content node module→edit any page content node module→edit any story content Moderator blog module→edit any blog entry comment module→access comments comment module→administer comments fckeditor module→access fckeditor node module→access content node module→edit any ad content node module→edit any feature content node module→edit any page content node module→edit any story content Proofreader blog module→edit any blog entry fckeditor module→access fckeditor node module→access content node module→edit any ad content node module→edit any feature content node module→edit any page content node module→edit any story content Style Editor block module→administer blocks fckeditor module→access fckeditor fckeditor module→allow fckeditor fle uploads node module→access content node module→edit any ad content node module→edit any feature content node module→edit any page content node module→edit any story content Senior Editor block module→administer blocks blog module→delete any blog entry blog module→edit any blog entry comment module→access comments comment module→administer comments fckeditor module→access fckeditor fckeditor module→allow fckeditor fle upload node module→access content node module→delete any ad content node module→delete any feature content node module→delete any page content node module→delete any story content node module→delete revisions node module→edit any ad content node module→edit any feature content node module→edit any page content node module→edit any story content node module→revert revisions node module→view revisions path module→create URL aliases view module→access all views view module→administer views With that, we have assigned the required permissions to all of our team members, which will allow them to do their jobs, but keep them out of trouble! However, what do you do when someone intentionally gets into trouble? The disgruntled team member So, we've been marching along as one big happy team, and then it happens. Someone gets let go, and that someone isn't happy about it, to say the least. Of course, we'll remove that person's login, but there is public access to our site as well, in the form of comments. Is there a way for us to stop this person from looking for ways to annoy us, or worse? Yes! Activity 5: Blocking Let's now perform the tasks necessary to keep disgruntled employees (and trouble-makers) at bay. From the admin menu, select User management. On the User management page, we'll select the Access rules option. We'll choose the Add rule option on the Access rules page. On the Add rule page, we have the option to deny access to a user, email address, or host. The username and email address options will block someone from registering, but will not affect someone already registered. The host name will stop anyone with that host name from accessing the system at all. Wild cards can be used: % will match any number of characters, and _ will match one character. Allow rules can be used to give access to someone who would otherwise be blocked by a host or wild card rule. In our case, let's say that the disgruntled former team member is spamming our comments from a host called spamalot.com, and is doing it from many emails. The first thing we want to do is create a 'deny' rule that will deny access to anyone from that host, as shown in the following figure, and then click on the Add rule button. We're also going to create an email deny rule for %@spamalot.com. We shouldn't have to (as we've already denied the host, which in turn would include all of the emails from that host), but we need to, because the rules testing logic ignores that hierarchy at this time. Let's also say that we've received an email from someone whose email address is its_not_me@spamalot.com, who would like to be a member of our site, and we verify that this person is not our former team member. In such a scenario, we will need to create an Allow rule, as shown in the following screenshot, so that this person can get past our previous Deny rule. Our rules now appear, as shown below, when we click on the List button, which is at the top of the page. It's always good to check and make certain that we've created the rule(s) correctly. If we don't do this, then we might inadvertently block the wrong users. Let's click on the Check rules tab at the top of the Access rules page. In the email box, we'll first try disgruntled@spamalot.com. Next, we'll try its_not_me@spamalot.com. In this last activity we have created some access rules. Drupal uses these access rules to determine who can and cannot access the site. In some cases, you may be having difficulty with a particular user adding comments to your site. Of course, if you set comments to require moderation, then the questionable ones won't appear, but it can still be a pain having to review a steady stream of them. In that case, you can block a specific user. You might be having difficulty with comments from more than one user at a given email domain. You can, if you like, block everyone from that location. On the other hand, your site might be meant for users of a particular domain, perhaps a university. In that case, you can allow users from that domain and only them. Summary In this article we learned about: Roles—defining types of users Permissions—defining capabilities for each role Node Content types—as they apply to Roles Access Rules—for those pesky, misbehaving users These features have been explained and learned with the help of activities where we have: Created a team Added Roles to enable the team Defined new Node Content types to suit the requirements of some team members Configured permissions to support the Roles and Node Content types Handled a former (and disgruntled) team member
Read more
  • 0
  • 0
  • 2529

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-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-putting-sakai-work
Packt
21 Oct 2009
16 min read
Save for later

Putting Sakai to Work

Packt
21 Oct 2009
16 min read
The fundamental determinants of course quality have always been, and remain, the course content, the instructor(s), the learning activities in which the students are engaged, and the students themselves. We do not make any exaggerated promises about the transformative nature of technology in education. Technology like Sakai can be used to improve your course by allowing you and your students to do things that might have been impractical without the technology or by reducing the amount of time spent on administrative issues. But the tools Sakai provides are just that—tools—and unless they are used purposefully they will not make much of a difference. So it is most important for you to consider what you want to accomplish with your students and how the capabilities Sakai provides can support the course activities. There is not a single "best" way of teaching. What works in a small graduate seminar in philosophy may not work in a large introductory computer science class, and what works for one instructor may not work for another. The good news is that Sakai is designed with this variety in mind. The tools and structure of a Sakai site You can think of Sakai as a framework that allows you to create the kind of online experience you want for your students. There is not a single way that a Sakai course site needs to function—it is ultimately up to you, with assistance from your Sakai user support team, to determine how the course is presented to the students online. Not all Sakai sites are used for courses. In many institutions, it is common to find Sakai used for research work groups and administrative collaboration. In fact, at many institutions, there are more "collaboration sites", as they are called in the Sakai community, than there are course sites. So, these types of sites are included in the overview. Many institutions integrate Sakai with other enterprise systems—automatically creating a Sakai site for each course being taught, for example, and adding students who are registered for the course to the site. Other organizations require instructors to create a site online but, once that's created, students are added and removed based on data from the registrar's office. Regardless of the type of course (or collaboration site) you might be teaching, there is a basic structure to Sakai that is useful to understand. This section describes that basic structure and common tools. It also gives you a quick and easy way to customize a Sakai site, so we recommend having a browser window handy with access to an instance of Sakai. If you have not yet created a Sakai site or if you don't have access to an instance of Sakai at your organization, several Sakai Commercial Affiliates host trial versions of Sakai that you can access free of charge. Check www.sakaiproject.org for the current listing. At the time of writing, hosted trials were available from rSmart (http://sakaisandbox.com), Serensoft (http://sakaisthelimit.com), and Unicon (http://testdrivesakai.com). When you create your account, a site is automatically created for you. Sakai's site structure Once you've logged into Sakai the top of the screen consists of a Sakai banner that contains your organization's branding and a logout button. Just below that banner is a series of tabs, one for each Sakai site that you are a member of. Every course or project consists of a Sakai site and is accessed by clicking a tab labeled with the name of the site. If you are a member of more than one site, you have more than one tab across the top of your screen. If you have too many sites to fit, a More Sites menu (often renamed My Sites or My Active Sites) is present; it enables you to access the appropriate site. Always be sure you're in the correct site when you're doing your work. My Workspace There is also a tab called My Workspace, a special site that only you have access to. You use it to manage your preferences, store personal files, manage site memberships, and even provide a calendar that pulls information from all the Sakai sites to which you belong. Contact your local Sakai support team for more information about uses of My Workspace. You can modify which sites appear across the top of the page so that your most frequently accessed sites are a single click away. To do that, go to your My Workspace site and choose the Preferences tool. The Customize Tabs function enables you to change which sites are visible. A basic Sakai site is a collection of tools that users have access to, typically presented to users in a sidebar on the left of the screen. In most Sakai installations, each link in the left sidebar corresponds to a single tool. To access the Assignments tool, for example, a user clicks the Assignments link in the sidebar. The Assignments tool then appears in the main content area of Sakai. In most cases, it is as simple as that. The major exception to this rule is the site Home page. It is a significant exception because it is the first page you see when you access a site. The Home tool contents Unlike most tools, the Home tool is not a tool at all. It is really a summary page. It generally includes information pulled from several different tools. Sakai tries to be helpful by providing the most commonly useful information and, therefore, a typical course site Home page includes areas (called panels) that present the following information: A site description (a description of the course or project) Recent course announcements Recent discussion forum posts Recent chat messages A course calendar Most of the panels on the Home page can be configured directly from the Home page. The Calendar panel, for example, allows you to specify whether the calendar is presented by week or by month. To add events to the Calendar, however, you need to use the Calendar tool itself. The Announcements panel lets you to determine how many recent announcements are shown (you can specify either a certain number of announcements or have the panel display announcements that have been created since a specific number of days in the past). Some panels enable you to edit the content itself. The Site Description panel, for example, provides an Options link that allows you to edit the content directly, obviating the need to access the tool directly. Of course, if you are not planning to use a tool in your site you do not want its information panel to appear on the course Home page. If you are not going to make a chat room available in your course, for instance, you do not want your course Home page to include a summary of recent chat messages because that would make your site look unfinished. Thankfully, Sakai is generally very smart about this—if you turn off the Chat tool in your site, the recent chat messages summary panel on the Home page simply disappears. Except for editing the Course Description content, you can mostly ignore the Home page and let Sakai take care of it for you. To edit the Site Description, simply click on the Options button. There are four things you can do: Specify the title for the panel. A good title reflects the type of site you have (for example changing the default Site Description to Course Description or, better yet, Welcome to Theater 101). Create the content that appears in the body of the panel. An easy-to-use HTML editor enables you to enter whatever content you want. If you don't know HTML, the default WYSIWYG mode can be used like a simple word processor. Just type away using the built-in text styling buttons to add bold, italics, bulleted lists, and so on. You can also add images, hyperlinks, and tables quite easily. If you know HTML, you can use the source code mode to view and edit the HTML directly. Specify the height for the panel. You want to make the panel large enough so there is no scroll bar within the panel itself. This is easy if there is not another panel just below it. If there is, make the panel just large enough to hold your content but not so large that there is excessive white space between the panels. This may take a bit of trial and error. Enter a URL instead of writing content. If you already have an HTML page that describes the site published elsewhere, you can simply enter that web address. Sakai will display that page in the Site Description panel. Then simply click Update Options to save the changes you've made. If you have access to Sakai, this would be a good time to try it out. Remember to ensure you are working in the correct site. There are, certainly, many instructors who want their course Home page to appear in a very specific manner. There are risks to that level of customization—remember that your students are likely taking several courses at one time and they may benefit from a consistent Home page experience. Nonetheless, it is often quite appropriate to create a custom Home page. Later, you'll see a number of ways to significantly customize the appearance of your site, including the Home page. First, though, let's review tools to make available and just let the Sakai Home page do most of the work. The basic collaboration tools There are four basic tools that almost every Sakai site uses, regardless of whether it is a course or a collaboration site: Resources. The tool for storing files that can be accessed by other members of the site. You can create folders to organize these files, and even make certain files publicly viewable (such as a web page you want to show to those who aren't part of your site). Announcements. Use it to send announcements to members of the site. These announcements appear on the site Home page and can be sent to all site members via email. Email Archive. This tool provides a dedicated email address for your site (mysitename@sakai.myschool.edu, for instance). While permissions can be configured to make Sakai behave differently, typically members of your site can send email to this address and everyone belonging to the site will get the email. All emails are archived and accessible using the Email Archive tool. Calendar. Sometimes called Schedule, the Calendar tool allows you to put important events on a calendar. The Sakai Calendar supports recurring events and has different icons for different types of events such as class meetings, exams, and special events. Site administration As a site owner, there are certain tasks that you may want to undertake to modify the site and/or the members of the site. The Site Info tool allows you to: Modify the tools available in your site, including modifying the order in which those tools appear in the toolbar and changing the names of the tools. Manage access to the site, including specifying whether individuals can join your site without your approval. Manage the membership of your site. What you can and cannot do with membership depends on your local Sakai installation and often varies based on organizational policies, but typically includes the capability to add and remove members and change the role of individual members. Manage groups of users in your site. Many Sakai tools have special features that allow you to work with a particular set of users inside your site. Groups and class sections are good examples of predefined groups that may be automatically created by your Sakai administrators. You can also create ad hoc groups for particular purposes. If you have project teams in your course, for example, it might be useful to create a group for each team. Import content from an existing site or export content from the current site to a new one. As a site owner, you always have access to the Site Info tool. Depending on how you use Sakai and how Sakai is integrated with other systems on your campus, you may never use Site Info. Still, you should take a quick look to familiarize yourself with what is available to you. Every Sakai installation is different from every other. Your organization may not make the same Sakai tools available as another organization. This article mainly restricts itself to those tools that will be commonly available in installations of Sakai version 2.6.x, but there may be instances where we mention a tool that is not available in your instance of Sakai. In many cases, you can request these tools from your Sakai administrator. We also try to mention alternatives to the recommended tool where they exist. The basic teaching and learning tools In addition to the basic collaboration and administration tools, there are three tools that are commonly used in Sakai Course sites: Syllabus, Assignments, and Gradebook. Syllabus. Use this tool to put your syllabus (clear guidelines and expectations for your course) online. You can upload a document (such as a Microsoft Word document or a PDF), build a structured syllabus in Sakai, or even point to an existing syllabus you have posted online in another location. Regardless of how you use the tool, you can have Sakai automatically email students when you've made a change to the syllabus. Assignments. This tool allows you to create and post assignments that students can submit electronically. Using the tool can help eliminate paper assignments and reduce class time spent collecting and returning student work. It allows students to send questions about assignments and enables you to post online comments, grade assignments, and transfer grades to the Gradebook automatically. The tool lets you set opening and closing times for each assignment, supports resubmissions, and marks each student submission with a date and time stamp. Gradebook. The Gradebook tool allows instructors to record and compute cumulative student grades. Students can refer to the Gradebook to check their progress in a course. The Gradebook tool is often used hand-in-hand with the Assignments tool although they can be used separately. With these three tools and the four basic collaboration tools reviewed earlier, you can create a solid online presence for your class. Students will get course announcements and can send and receive emails via the class email address and can check past messages online. You can post reading material and other resources for students online and build a course calendar to remind students of important events and deadlines. Your syllabus is available online and students are automatically updated with any modifications to it. You've provided a facility for students to submit their assignments electronically, and they can receive feedback on those assignments via Sakai as well. Their grades are computed online and they can check to see how they are doing at any time. Now that you have your course's online infrastructure set up, we can begin to add some more sophisticated uses of online tools. We'll do this by turning our attention to the several common types of courses and discuss how a Sakai site can be structured to support each type of course. Types of Sakai sites There are more than four thousand universities and colleges in the United States alone. Each of these teaches hundreds or even thousands of classes every year. Trying to create some structure from such a diverse world would be an exercise in oversimplification. The categories discussed here along with the associated recommendations about how to support them in Sakai are not meant to be rules or even best practices but rather a place to start when thinking about structuring your Sakai site. Do read through all of the site types because it is likely that your course mixes the structures and activities in two or more site types. And your own personal comfort with technology will also determine how many (and which) tools you might want to use. The site types you'll be working with are as follows: Problem-based courses Small discussion courses Large, introductory courses Project-based courses Collaboration sites The following sections highlight a small number of tools that are especially useful in a site used for that purpose. Other tools are often useful as well, but because you're just starting out, you'll have more success using a few tools well. Still, we encourage you to read through all the class types and mix and match the tools you feel will work best for your situation. Problem-based courses A problem-based course presents learners with one or more problems to solve on a regular basis (weekly, for instance). The problems are presented by the instructor and generally have either correct answers (such as a Calculus problem set) or at least a fairly clear way to distinguish better solutions (such as an analysis of a poem in an English literature class). Problem-based courses are often targeted at developing skills related to the topic at hand and students are therefore asked to apply what they've learned by solving problems. Math courses might include weekly problem sets, computer science courses might include small programming assignments, creative writing classes may have weekly writing exercises, an acting class may have a series of small scene studies—the general approach is to increase the level of student skill through repeated practice with frequent feedback. The tools introduced so far serve this type of course very well, with a special emphasis on the Assignments and Resources tools, and with the addition of just a few extra tools, you can make the online aspect of your problem-based class very effective: Assignments. Use this tool to enter all or most of the term's assignments at the beginning of the term. That provides students with an excellent guide to the weeks ahead and helps them plan their time accordingly. Resources. For problems with correct answers, use this tool to share sample problems and solutions to past problem sets. For classes where high-quality answers are less well defined (such as a performing arts or product design class), share samples of previous classes' best work. You can even upload video or audio recordings. By providing examples of excellent solutions to open-ended problems, you help your students understand what you're looking for. Forums. This tool provides online discussion that allows students to help each other with difficult problems. You can set up a forum for each problem set. (Be sure to monitor the forum to ensure that students are giving each other good advice and aren't crossing the boundaries by helping too much.) Chat. Use this tool to provide online problem-set help two nights before an assignment is due (don't encourage procrastination by scheduling it the night before the assignment is due). From the comfort of your home, you can take student questions about the assignment and suggest resources they might refer to while working on it.
Read more
  • 0
  • 0
  • 3694
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-configuring-opencms-search
Packt
21 Oct 2009
6 min read
Save for later

Configuring OpenCms Search

Packt
21 Oct 2009
6 min read
A Quick Overview of Lucene Included with OpenCms is a distribution of the Lucene search engine. Lucene is an open source, high-performance text search engine that is both easy to use and full-featured. Lucene is not a product. It is a Java library providing data indexing, and search and retrieval support. OpenCms integrates with Lucene to provide these features for its VFS content. Though Lucene is simple to use, it is highly flexible and has many options. We will not go into the full details of all the options here, but will provide a basic overview, which will help us in developing our search code. A full understanding of Lucene is not required for completing this article, but interested readers can find more information at the Lucene website: http://jakarta.apache.org/lucene. There are also several excellent books available, which can easily be found with a web search. Search Indexes For any data to be searched, it must first be indexed. Lucene supports both disk and memory based indexes, but OpenCms uses the more suitable disk based indexes. There are three basic concepts to understand regarding Lucene search indexes: Documents, Analyzers, and Fields. Document: A document is a collection of Lucene fields. A search index is made up of documents. Although each document is built from some actual source content, there is no need for the document to exactly resemble it. The fields stored in the document are indexed and stored and used to locate the document. Analyzer: An analyzer is responsible for breaking down source content into words (or terms) for indexing. An analyzer may take a very simple approach of only parsing content at whitespace breaks or a more complex approach by removing common words, identifying email and web addresses, and understanding abbreviations or other languages. Though Lucene provides many optional analyzers, the default one used by OpenCms is usually the best choice. For more advanced search applications, the other analyzers should be looked at in more depth. Field: A field consists of data that can be stored, indexed, or queried. Field values are searched when a query is made to the index. There are two characteristics of a field that determine how it gets treated when indexed: Field Storage: The storage characteristic of a field determines whether or not the field data value gets stored into the index. It is not necessary to store field data if the value is unimportant and is used only to help locate a document. On the other hand, field data should be stored if the value needs to be returned with the search result. Field Indexing: This characteristic determines whether a field will get indexed, and if so, how. There is no need to index fields that will not be used as search terms, and the value should not be indexed. This is useful if we need to return a field value but will never search for the document using that field in a search term. However, for fields that are searchable, the field may be indexed in either a tokenized or an un-tokenized fashion. If a field is tokenized, then it will first be run through an analyzer. Each term generated by the analyzer will be indexed for the field. If it is un-tokenized, then the field's value is indexed, verbatim. In this case, the term must be searched for using an exact match of its value, including the case. The two field types may be combined to form four combinations. While choosing a field type, consideration should thus be given to how the item will need to be located, as well as what data will need to be returned from the index. Lucene also provides the ability to define a boost value for a field. This affects the relevance of the field when it is used in a search. A value other than the default value of 1.0 may be used to raise or lower the relevance. These are the important concepts to be understood while creating a Lucene search index. After an index has been created, documents may be searched through queries. Search Queries Querying Lucene search indexes is supported through a Java API and a search querying language. Search queries are made up of terms and operators. A term can be a simple word such as "hello" or a phrase such as "hello world". Operators are used to form logical expressions with terms, such as AND or NOT. With the Java API, terms can be built and aggregated together along with operators to form a query. When using the query language, a Java class is provided to parse the query and convert it into a format suitable for passing to the engine. In addition to these search features, there are more advanced operations that may be performed such as fuzzy searches, range searches, and proximity searches. All these options and flexibility allow Lucene to be used in an application in many ways. OpenCms does a good job of using these options to provide search capabilities for a wide range of content types. Next, we will look at how OpenCms interfaces with Lucene to provide this support. Configuring OpenCms Search OpenCms maintains search settings in the opencms-search.xml configuration file located in the WEB-INF/config directory. Prior to OpenCms 7, most of the settings in this configuration file needed to be made by hand. With OpenCms 7, the Search Management tool in the Administration View has been improved to cover most of the settings. We will first go over the settings that are controlled through the Search Management view, and will then visit the settings that must still be changed by hand. The first thing we'll do is define our own search index for the blog content. Creating a new search index is simple with the Administration tool. We access it by clicking on the Search Management icon of the Administrative View, and then clicking on the New Index icon: The Name field contains the name of the index file. This name can also be passed to a Java API. If the content differs between the online and offline areas, we can create an index for each one. For now, we will start with the offline index. We'll name it: Blogs – Offline. The other fields are: Rebuild mode: This determines if the index is to be built manually or automatically as content changes. We want automatic updating and will hence choose auto. Locale: We must select a locale for the content. OpenCms will extract the content for the given locale when it builds our index. If we were supporting more than one locale, then it would be a good idea to include the locale in the index name. Project: This selects content from either the Online or Offline project. Field configuration: This selects a field configuration to be used for the index. We do not have our own field configuration yet; so for now press OK to save the index. Next, we will define a field configuration for the blog content.
Read more
  • 0
  • 0
  • 3529

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-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-showing-drupals-cck-module-fields-flash
Packt
21 Oct 2009
6 min read
Save for later

Showing Drupal's CCK Module Fields in Flash

Packt
21 Oct 2009
6 min read
Building a Recipe widget in Flash We will start out by first increasing the size of our stage in Flash to 500 x 640. Once we have done this, we will need to resize our background so that it fits to the new stage. We will start this by first selecting the whole background region, and then converting that into a new Movie Clip by selecting Modify | Convert to Symbol from the Flash menu. This will t hen bring up a new dialog, where we can give our new Movie Clip a name, which we will call mcBackground. We then need to make sure that we check the Enable guides for 9-slice scaling, which will allow us to resize the background without affecting the rounded edges. Once we create a new movie clip from our background, we will then enter this Movie Clip and then adjust the 9-scale guides so that they only cover the rounded edges. We can now ex it the background movie clip, and then resize the movie clip to a new height of 632 using the Properties panel. Our next task is to move the current title field to the top-left of our Flash application, and then create some background regions that will hold our new fields. The design of how this will look is completely up to you, but here is an illustration of what I just described: Now that our layout is ready for new content, the next step is to add new TextFields to hold our recipe content. Adding dynamic TextFields for Drupal content The important thing to note here is that we will need to create a new layer for each text element within our Flash application, so that we can keep track of each field separately. We will do this within the timeline by creating three new layers for each of our new fields, and by then labeling them so that we can easily determine what they contain. Now that we have each one of these separated, we can add new text fields in each layer, to be used for the description, ingredients, and the instructions. For each new Text field that we create, we will need to make sure to give them an instance name so that we can reference them within ActionScript. Each of these instance names should reflect the names of the fields that we created for our Recipe content type, which will be description, ingredients, and instructions respectively. When we are done, we should have something that resembles the following: We are now ready to hook up these TextFields to real Drupal content. Using ActionScript to show Drupal CCK fields We can start this off by opening up our main.as file, and then we will shift our focus to the onNodeLoad function. // Called when Drupal returns with our node.function onNodeLoad( node:Object ){ // Print out the node title. title.text = node.title;} This function gets called after our service call to Drupal's node.get service call and returns with the contents of the node. Since we have new TextFields for each custom recipe field, we can use the node object, passed to the onNodeLoad function, to reference the data from these custom fields, and populate our TextFields with that data. Since the contents of this node object are somewhat a mystery, there is a fantastic tool that is provided with Drupal that will allow us to examine how this node is structured. We will then be able to use that information to fill out the contents of our onNodeLoad function to show our complete recipe node. Using the Services Administrator We now need to shift our focus back to Drupal, where we will navigate to the Service Administrator section by going to Administer | Services. The Services module comes equipped with a fantastic tool for analyzing any service routine when working with external applications. It allows for you to call any service routine, with any specified argument, and then see the result of that routine call. This can be used to easily analyze the data structure that our Flash application will receive after it makes a call to any of the service routines available. Since we are using the node.get service routine to load each recipe node, we should be able to examine how the Description, Ingredients, and Instructions fields are represented, and then easily apply that to our Flash application. Let's do this by clicking on the link that says node.get in the node section. This will bring up the following page: The Services module automatically places a valid Session id in the session field, so we can just keep this field as it is. Because of this, all we really need to provide is the nid (node ID) of our Recipe node—since the fields field is optional. In order to determine the node ID for any node within the Drupal web site, simply navigate to Administer | Content, which will list all the content within the Drupal web site. The node ID can be found by hovering over any content link and then reading the last number in the URL. For example, if we hover over our Recipe node, we should see a URL similar to http://localhost/drupal6/node/5, which means that our node ID for this node is 5. After we have the entered the node ID in the nid field, we can now click on the button that says Call Method. This will then show the results of that call within the Results section just below the Call Method button. To the untrained eye, this may look intimidating, but really what this is showing is the results for all the data contained within the recipe node that we just created, including the Ingredients and Instructions. If we look within this data structure, we should see something that looks similar to the following: [field_ingredients] => Array( [0] => Array ( [value] => 1 skinless, boneless chicken breast half 2 tablespoons minced green onion 2 tablespoons minced red bell pepper 3/4 cup shredded Monterey Jack cheese 5 (6 inch) flour tortillas [format] => 1 )) Within our Flash application, we can now access the Ingredients field in the node object (which is what is returned when you call node.get). The ActionScript code to reference this field should look similar to the following: node.field_ingredients[0]["value"] Now, let's apply this concept to show the ingredients and instructions in our Flash application.
Read more
  • 0
  • 0
  • 1964
article-image-setting-plone-development-environment
Packt
21 Oct 2009
13 min read
Save for later

Setting up the Plone Development Environment

Packt
21 Oct 2009
13 min read
(For more resources on Plone, see here.) Prerequisites Pre-built packages for Zope and Plone are available for many operating systems. These can be tempting, but as developers it is normally better to configure the environment ourselves, in order to fully understand and control it. During development, we need write access to the Python code and configuration files. We may also need to run different versions of Zope and Plone in parallel. We will assume that you have at least the following as part of your regular development environment:   Python 2.4. We will assume that Python 2.4 gets invoked when you run python on the command line. Unfortunately, Zope, at version 2.10, does not yet support Python 2.5. Note that many Linux distributions have two packages for Python—one containing the binaries, and one containing header files (typically called python-dev or something similar). You will need both in order to compile Zope. PIL, the Python Imaging Library (http://www.pythonware.com/products/pil), should be installed for this Python interpreter. elementtree, an XML processing library, is required for Plone to start up. Most operating systems have packages for this. It can also be downloaded from http://effbot.org/zone/element-index.htm. A programmer's text editor. Preferably one with Python, XML/HTML and CSS syntax highlighting. You should set up your editor so that a tab/indent is output as four spaces. This makes Python development a lot more predictable. A shell. Most examples in this book will show a Bash interpreter shell, though we will cover Windows syntax when it differs significantly. Bear in mind that path separators on Windows are backslashes (), while other environments use forward slashes (/). Also, environment variables on Windows are referred to as %NAME%, while in most Unix shells, including Bash, variables are dereferenced with $NAME. A Subversion client. We will show the command line client syntax, but you can use a graphical client if you are more comfortable with that. Subversion can be obtained from http://subversion.tigris.org. A C compiler. You will need this to compile Zope. The venerable gcc is fine on UNIX-like systems. On Windows you probably want mingw32 (http://www.mingw.org). Alternatively, you can use a Zope Windows installer to get a binary Zope distribution.   Quick Start Understanding your development environment is an important step in becoming a productive developer. If you need to get up and running quickly, however, and you have the prerequisites outlined above in order, here are the key steps. We will assume you have Python 2.4 as your main Python interpreter. First download easy_install if you do not have it already, and use it to install ZopeSkel:   $ wget http://peak.telecommunity.com/dist/ez_setup.py   $ python ez_setup.py   $ easy_install ZopeSkel Note: If you do not have wget (e.g. because you are using Windows), you can just as easily download the ez_setup.py script using a web browser. When you run this script, it will install the easy_install binary to a directory that may not already be in your system PATH. Watch the ez_setup.py output to identify this directory. If it is not in your PATH, you should add it, allowing you to run easy_install as shown. Then, use paster, which was installed as a dependency of ZopeSkel, to create a new buildout. This folder holds our source code and dependencies, including the Zope application server:   $ paster create -t plone3_buildout myproject You can accept the defaults for all the questions, except for the password, which you must enter. Then, build the environment like so:   $ cd myproject   $ python bootstrap.py   $ ./bin/buildout Note: If you are using Windows, be sure to read the README.txt file that is generated in the myproject directory before running the buildout command. This last step may take some time, and you will need a live Internet connection.When it is complete, you can start Zope with:   $ ./bin/instance fg Go to http://localhost:8080/manage and you should see the Zope Management Interface. Use the drop-down box to add a Plone Site. If you call this mysite, it will beaccessible from http://localhost:8080/mysite. Glossary Let us now take a step back and consider our development environment in more detail. The table below summarizes the various terms and technologies that you will encounter in this chapter. It pays to be familiar with these names, because you will find them again not only throughout this book, but also in other Plone documentation. Term Definition Zope installation Zope consists of Python code, C extensions, configuration files, documentation, scripts, and utilities. Collectively, these are known as the Zope installation. Software home The part of the Zope installation that contains the main Zope runtime. This is found in the lib/python directory of the Zope installation. The full path is assigned to the $SOFTWARE_HOME environment variable when Zope is run. Zope instance The same Zope installation can be used to power multiple Zope servers, possibly running concurrently on different ports. Each instance has a directory containing a configuration file, instance-specific software components (e.g. an installation of Plone), and the local Zope database storage. Instance home When a Zope instance is running, the $INSTANCE_HOME environment variable refers to the directory where the instance is set up. Package A generic term for a distributable bundle of Python modules and supporting files. Product The traditional way to redistribute software for Zope 2 is in a "Product", which we will sometimes refer to as an "old-style Product". Products are placed in a special directory (Products/) and automatically discovered by Zope. The term "product" is also used more generally to refer to add-on components that extend Plone, even if they are not actually packaged as old-style Products. Egg A more generic and flexible alternative to products. Eggs are not specifi c to Zope, and Zope has only recently been made egg-aware. In addition to code, eggs contain metadata such as version, dependencies, and license information. Egg management tools can use this information to manage concurrent versions or automatically fetch dependencies, for example. $PYTHONPATH The $PYTHONPATH environment variable lists the directories containing Python packages that should be available at run time. It can also reference specific eggs. You should not have to set this manually. setuptools A Python library, which extends Python's built-in distutils package to support extended egg metadata and offers enhanced functionality when using software packaged as eggs. The Cheese Shop Also known as PyPI (Python Package Index). An online repository of Python eggs. Anyone can upload a package here. Egg-aware tools can use the Cheese Shop to locate dependencies and download them automatically when installing other eggs. easy_install A command-line tool, which searches the Cheese Shop for a given package, and downloads and installs it. Note that, by default, easy_install puts packages in the global site-packages folder for the Python interpreter that was used to install easy_install itself. Normally, we want our Plone packages to be local to a specific Zope instance, necessitating different tools. paster (Paste Script) paster, part of the Python Paste package, is a command runner. The paster create command invokes Paste Script templates, which are used to create skeleton packages based on command-line options and questions. ZopeSkel A collection of Paste Script templates for Zope and Plone development. We will use this to create new egg-ready packages, as well as the buildout that manages our development environment. Buildout (zc.buildout) A "buildout", using the zc.buildout toolset, is a self-contained environment that is controlled through a single configuration file (buildout.cfg). We will use it to download, install, and configure Zope, Plone, and other dependencies. Buildouts are "repeatable", meaning that they can be used to replicate a particular setup across multiple servers or developers' machines.     Understanding Eggs and Setuptools Python eggs are not specific to Zope or Plone. However, since Zope has only recently become egg-aware, they are new to many developers. Traditionally, almost all Zope add-on products, including Plone, have been distributed as Zope products. These are fairly easy to manage—you typically copy or symlink them into $INSTANCE_HOME/Products. Zope will scan this directory on startup, taking care of any product initialization and registration. However, code inside products is nearly impossible to re-use outside Zope because Zope does magic things with the Products.* namespace. Further, the namespace quickly becomes crowded, which deters developers from breaking up functionality into smaller, more re-usable and better-isolated packages. The Zope 3 philosophy is to be as close to "plain Python" as possible, and that means distributing code as such small packages. So long as its dependencies are in order, any package should be able to run in any environment. For example, the zope.interface package is used by the Twisted project, which is not otherwise dependent on Zope. This design goal has made it much easier to adopt Zope 3 packages in Zope2 and Plone. Starting with Plone 3, the Plone community has also embraced "plain Python" packages and uses them wherever possible. A number of packages, such as plone.memoize and plone.portlets are generic enough to work without any dependencies on the rest of Plone. Others are more specific to Plone and live in the plone.app namespace, such as plone.app.layout and plone.app.portlets, thelatter containing Plone-centric extensions to the generic plone.portlets package. All that is needed to use these packages is a sensible $PYTHONPATH. Thus, we can copy or link packages into $INSTANCE_HOME/lib/python/plone/memoize, lib/python/plone/portlets, lib/python/plone/app/portlets, and so forth for Zope to find them. This works, but it is pretty tedious when there are many packages, and it can become outright confusing when there are nested namespaces being used bymultiple packages. Luckily, other Python programmers have solved these problems, first creating distutils, then its successor setuptools and with setuptools, Python eggs. Note: For the setuptools documentation, see http://peak.telecommunity.com/DevCenter/setuptools. Installing Eggs When using setuptools, each project or package lives in a directory that has a toplevel setup.py file. This contains metadata about the package itself, and declares its current version as well as any dependencies. Dependencies can be specifieddown to particular versions (e.g. ">=0.2,<1.0" means "later than version 0.2 but before version 1.0"). When a package is installed, setuptools will attempt to fulfilldependencies by downloading and installing them if necessary. If you have a setuptools-enabled package, you can use setup.py to install it globally, by running:   $ python setup.py install This will copy the source code to the system-wide Python site-packages directory. Having to re-run this command each time you make a change can make development a little awkward, so while you are working on a particular package,you can install a development egg. This is essentially a link to the package's source code that ensures it is added to the $PYTHONPATH. To install a development egg, run:   $ python setup.py develop New packages can be released as binary eggs for distribution, which are just ZIP files of the package with some additional metadata. You can build an egg from within apackage by running:   $ python setup.py bdist_egg The new egg will be placed in the dist sub-directory, which will be created if necessary. Eggs can be uploaded to the Cheese Shop, also known as PyPI (the PythonPackage Index). This central repository makes it easy to fi nd packages. You canbrowse packages at http://cheeseshop.python.org/pypi. New packages can beuploaded via this website, or directly from the command line:   $ python setup.py egg_info -RDb "" sdist bdist_egg register upload You will be asked to specify or create a Cheese Shop account if this is the first time you run this command. A script called easy_install lets you search the Cheese Shop (or a similar index, if you specify a URL) for packages that it can download and install into the global Python environment. Dependencies will be included automatically. This is great for simple libraries and end-user applications, but less great when you are working on multiple Zope projects that may have different version requirements. This is why we tend to manage our eggs inside $INSTANCE_HOME or, as you will see in the next section, as part of a controlled buildout. Note: A tool called workingenv.py can create a mini-environment where global commands are restricted to a particular directory. We will not cover workingenv in this book, but you can download and read more about it at http://cheeseshop.python.org/pypi/workingenv.py. When eggs are activated (either explicitly, or implicitly by being unambiguouslyfound in the $PYTHONPATH), they can be discovered by other packages listening for plug-ins, using a mechanism called entry points (see http://peak.telecommunity.com/DevCenter/setuptools#dynamic-discovery-of-services-and-plugins). Zope does not yet directly use entry points, so we will not be covering them inany detail here. However, entry points are a very powerful system, and there areproposals to let Zope's discovery of packages use entry points instead of scanningmagic directories. With eggs, we therefore have the tools to manage multiple packages, from differentdevelopers and repositories, possibly across multiple versions. By using the packagemanagement tools that the rest of the Python community employs, we also make iteasier to re-use other libraries and share our own code with outside developers. Automating the Build Process with zc.buildout Creating a Zope instance and copying or linking packages into $INSTANCE_HOME/lib/python as is done in the manual process is not too difficult, but this approach has a few limitations. The process is manual and cumbersome to repeat across multiple environments. Multiple developers working on the same project may share the code in eggs and products by using a version control system such as Subversion. However, each developer would be responsible for setting up their development environment, and subtle differences may cause problems that are difficult to debug. Packages are installed manually, and so cannot benefit from setuptools' ability to manage dependencies and updates. Complex deployments that include other libraries, non-python code, or specific configurations will also need to be taken care of manually. Luckily, there are tools to make deployment easier. zc.buildout is one such tool, written largely by Zope founder Jim Fulton at Zope Corporation. It makes heavyuse of eggs and setuptools and is very flexible in supporting a wide range of deployment scenarios. Central to a buildout (i.e. what zc.buildout is managing for us) is a file called buildout.cfg. This specifies various options, including a list of parts, which will be executed when the buildout is run. Each part is associated with a recipe—a named egg, which will be called upon to parse the options provided, and perform a particular task, such as building a Zope instance or downloading Plone. A project-specific buildout directory can be checked into a version control system and shared among developers. It can also be used to replicate a particular environment across different servers with a high degree of predictability. By writing custom recipes, you can make zc.buildout do almost anything. Writing a recipe is not particularly hard, and there are plenty of examples and generic solutions available. However, we will not cover creating new recipes in this book, because all the recipes we need already exist.
Read more
  • 0
  • 0
  • 2318

Packt
21 Oct 2009
6 min read
Save for later

Binding Web Services in ESB—Web Services Gateway

Packt
21 Oct 2009
6 min read
Web Services Web services separate out the service contract from the service interface. This feature is one of the many characteristic required for an SOA-based architecture. Thus, even though it is not mandatory that we use the web service to implement an SOA-based architecture, yet it is clearly a great enabler for SOA. Web services are hardware, platform, and technology neutral The producers and/or consumers can be swapped without notifying the other party, yet the information can flow seamlessly. An ESB can play a vital role to provide this separation. Binding Web Services A web service's contract is specified by its WSDL and it gives the endpoint details to access the service. When we bind the web service again to an ESB, the result will be a different endpoint, which we can advertise to the consumer. When we do so, it is very critical that we don't lose any information from the original web service contract. Why Another Indirection? There can be multiple reasons for why we require another level of indirection between the consumer and the provider of a web service, by binding at an ESB. Systems exist today to support business operations as defined by the business processes. If a system doesn't support a business process of an enterprise, that system is of little use. Business processes are never static. If they remain static then there is no growth or innovation, and it is doomed to fail. Hence, systems or services should facilitate agile business processes. The good architecture and design practices will help to build "services to last" but that doesn't mean our business processes should be stable. Instead, business processes will evolve by leveraging the existing services. Thus, we need a process workbench to assemble and orchestrate services with which we can "Mix and Match" the services. ESB is one of the architectural topologies where we can do the mix and match of services. To do this, we first bind the existing (and long lasting) services to the ESB. Then leverage the ESB services, such as aggregation and translation, to mix and match them and advertise new processes for businesses to use. Moreover, there are cross service concerns such as versioning, management, and monitoring, which we need to take care to implement the SOA at higher levels of maturity. The ESB is again one way to do these aspects of service orientation. HTTP HTTP is the World Wide Web (www) protocol for information exchange. HTTP is based on character-oriented streams and is firewall-friendly. Hence, we can also exchange XML streams (which are XML encoded character streams) over HTTP. In a web service we exchange XML in the SOAP (Simple Object Access Protocol) format over HTTP. Hence, the HTTP headers exchanged will be slightly different than a normal web page interaction. A sample web service request header is shown as follows: GET /AxisEndToEnd/services/HelloWebService?WSDL HTTP/1.1User-Agent: Java/1.6.0-rcHost: localhost:8080Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2Connection: keep-alivePOST /AxisEndToEnd/services/HelloWebService HTTP/1.0Content-Type: text/xml; charset=utf-8Accept: application/soap+xml, application/dime, multipart/related, text/*User-Agent: Axis/1.4Host: localhost:8080Cache-Control: no-cachePragma: no-cacheSOAPAction: ""Content-Length: 507 The first line contains a method, a URI and an HTTP version, each separated by one or more blank spaces. The succeeding lines contain more information regarding the web service exchanged. ESB-based integration heavily leverages the HTTP protocol due to its open nature, maturity, and acceptability. We will now look at the support provided by the ServiceMix in using HTTP. ServiceMix's servicemix-http Binding external web services at the ESB layer can be done in multiple ways but the best way is to leverage JBI components such as the servicemix-http component within ServiceMix. We will look in detail at how to bind the web services onto the JBI bus. servicemix-http in Detail servicemix-http is used for HTTP or SOAP binding of services and components into the ServiceMix NMR. For this ServiceMix uses an embedded HTTP server based on the Jetty. The following are the two ServiceMix components: org.apache.servicemix.components.http.HttpInvoker org.apache.servicemix.components.http.HttpConnector As of today, these components are deprecated and the functionality is replaced by the servicemix-http standard JBI component. A few of the features of the servicemix-http are as follows: Supports SOAP 1.1 and 1.2 Supports MIME with attachments Supports SSL Supports WS-Addressing and WS-Security Supports WSDL-based and XBean-based deployments Support for all MEPs as consumers or providers Since servicemix-http can function both as a consumer and a provider, it can effectively replace the previous HttpInvoker and HttpConnector component. Consumer and Provider Roles When we speak of the Consumer and Provider roles for the ServiceMix components, the difference is very subtle at first sight, but very important from a programmer perspective. The following figure shows the Consumer and Provider roles in the ServiceMix ESB: The above figure shows two instances of servicemix-http deployed in the ServiceMix ESB, one in a provider role and the other in the consumer role. As it is evident, these roles are with respect to the NMR of the ESB. In other words, a consumer role implies that the component is a consumer to the NMR whereas a provider role implies the NMR is the consumer to the component. Based on these roles, the NMR will take responsibility of any format or protocol conversions for the interacting components. Let us also introduce two more parties here to make the role of a consumer and a provider clear—a client and a service. In a traditional programming paradigm, the client interacts directly with the server (or service) to avail the functionality. In the ESB model, both the client and the service interact with each other only through the ESB. Hence, the client and the service need peers with their respective roles assigned, which in turn will interact with each other. Thus, the ESB consumer and provider roles can be regarded as the peer roles for the client and the service respectively. Any client request will be delegated to the consumer peer who in turn interacts with the NMR. This is because the client is unaware of the ESB and the NMR protocol or format. However, the servicemix-http consumer knows how to interact with the NMR. Hence any request from the client will be translated by the servicemix-http consumer and delivered to the NMR. On the service side also, the NMR needs to invoke the service. But the server service is neutral of any specific vendor's NMR and doesn't understand the NMR language as such. A peer provider role will help here. The provider receives the request from the NMR, translates it into the actual format or protocol of the server service and invokes the service. Any response will also follow the reverse sequence.
Read more
  • 0
  • 0
  • 1936

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-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-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