Content Management Guide

     Previous  Next    Open TOC in new window    View as PDF - New Window  Get Adobe Reader - New Window
Content starts here

Using Syndicated Feeds

A syndicated feed, also called a web feed, provides users with frequently updated content. Syndicated feeds allow you to publish content to a third-party feed reader. For example, content publishers can configure a feed reader on their local machine that reads a syndicated feed that includes all content that is ready to publish. By subscribing to a syndicated feed, using a feed reader or aggregator, a user stays up to date on content changes.

WebLogic Portal provides a Syndication Producer Servlet and several preconfigured syndicated feeds that you can modify. You can also create your own custom feeds. The preconfigured syndicated feeds are compatible with RSS feed technology and consist of URL formats that can be read by most RSS readers. They conform to the RSS 2.0 Specification.

Note: Internet Explorer 6 does not support syndicated feeds.

This chapter includes the following sections:

 


Using and Modifying the Preconfigured Syndicated Feeds

The preconfigured syndicated feeds include basic examples of using display template JSPs to select and display content. These JSPs display general metadata, such when the content was created, who created it, and the name of the content node. They are generic display templates that show the information in a simple format.

Tip: Use these basic preconfigured syndicated feeds as a starting place for developing your own custom syndicated feeds.

URL Format for Syndicated Feeds

The URL format for syndicated feeds is shown in Listing 12-1.

Listing 12-1 URL Format for Syndicated Feeds
http://<Administration Console Host Machine Name>: <Administration Console Port
default is 7001)>/<WebApp>/SyndicationProducer?feedName=<feedName>
&syndicationStyleName=<styleName>

Table 12-1 lists the three preconfigured syndicated feed URLs provided with WebLogic Portal.

Table 12-1 Pre-Configured Syndicated Feeds
Feed Name
Description
Syndicated Feed URL
Latest Content
Shows the most recent files added to the repository.
http://<hostname>:7001/<WebApp>/SyndicationProducer?feedName=LatestContent&syndicationStyleName=rss
Need to Approve
Shows the documents that need approval before publishing.
http://<hostname>:7001/<WebApp>/SyndicationProducer?feedName=NeedToApprove&syndicationStyleName=rss
Directory Contents
Shows the files in a particular directory with the latest files at the top of the directory.
http://<hostname>:7001/<WebApp>/SyndicationProducer?feedName=DirectoryContents&syndicationStyleName=rss

Changing the Search Results Using a URL

If you want to change the search results for a particular feed, you can modify its URL. Modifying the URL allows you to pass parameters into the Syndication Producer Servlet without modifying the syndication configuration file, which sets the parameters passed to the Syndication Producer Servlet. For example, to change the number of articles displayed in a syndicated feed and the reader type, you would add the searchMaxResults parameter between ampersands and change the value of the syndicationStyleName to atom. The resulting URL looks like:

http://www.bea.com:7001/myWebApp/SyndicationProducer?feedName=LatestContent&searchMaxResults=5&syndicationStyleName=atom

Note that the URL follows the format in Listing 12-1. The available parameters are listed in Table 12-2. Be sure to separate each parameter with an ampersand.

Note: Any parameters not set in the URL should be set in the syndication configuration (wlp-syndication-config) file. Otherwise, you may get undesirable results or failure. For example, if the searchMaxResults parameter is not set anywhere, the syndicated feed could display hundreds of entries.

For more information about the wlp-syndication-config.xml file, see Modifying the Syndication Configuration File.

Modifying the URL is especially useful during development. You can use the URL to help determine and test the parameters that you want to pass into the Syndication Producer Servlet. This saves you time because changing syndication configuration file requires redeployment of the application. After establishing the correct parameters, you can edit the wlp-syndication-config.xml file and redeploy.

The parameters passed in through a URL have precedence over parameters passed in from the syndication configuration file. The Syndication Producer Servlet sets the priority in the following order:

  1. URL query parameters
  2. Syndication-feed settings in wlp-syndication-config.xml
  3. Syndication-style settings in wlp-syndication-config.xml

Modifying the Preconfigured Syndicated Feeds

To modify the preconfigured syndicated feeds, you need to change the following files:

About the Syndicated Feed JSPs

WebLogic Portal contains four preconfigured JSPs. The first three JSPs generate the list of content items, and the fourth generates the content itself. See Figure 12-1 and Figure 12-2.

Figure 12-2 shows the article itself, which is displayed by the rss_detailed_view.jsp.

Figure 12-2 Article Displayed by rss_detailed_view.jsp

Article Displayed by rss_detailed_view.jsp

Modifying the Preconfigured Syndicated Feed JSPs

To modify the preconfigured syndicated feeds JSPs in WorkSpace Studio, from the Merged Projects View, copy the RSS JSP files from the myPortalWebProject folder to your web project, and then edit the files. For information on how to use WorkSpace Studio for this purpose, see "Using the Merged Projects View" in Setting up Your Portal Development Environment in the Portal Development Guide.

Retrieving Content

In content management, the two types of repositories are published and versioned. The nodes in a published repository provide only a single version of information; the user of a syndicated feed sees that information every time the content node is updated. The nodes in a versioned repository provide multiple versions that can be searched and managed. When you enable library services, your content is automatically versioned and a new copy of the content is saved whenever you check in content to the repository. Generally, you use versioned repositories in a workflow, where a manager approves the content before it is published. For more information about library services, see Using Versioning.

Retrieving Information from a Published Repository

To call a node in a published repository, you set the search type in the syndication configuration file (wlp-syndication-config.xml) to pubmeta:

<search-type>pubmeta</search-type> 

When the Syndication Producer Servlet calls the JSP to retrieve data from a content node, in the JSP's scriptlet, the request attribute of the node in the JSP's scriptlet is set to not null:

if(request.getAttribute("node") != null){ 

Listing 12-4 shows the entire wlp-syndication-config.xml file and Listing 12-2 shows an example JSP (rss_item.jsp).

Retrieving Information from a Versioned Repository

To call a versioned node, you set the search type in the syndication configuration file (wlp-syndication-config.xml) to vermeta:

<search-type>vermeta</search-type>

When the Syndication Producer Servlet calls the JSP to retrieve data from a versioned node, the request attribute version in the JSP's scriptlet is set to not null:

else if (request.getAttribute("version") != null){ 

Listing 12-4 shows the entire wlp-syndication-config.xml file and Listing 12-2 shows an example JSP (rss_item.jsp).

Example JSP

The following example JSP contains the logic to render the syndication feed. The Syndication Producer servlet uses the content query to retrieve the data from content management. The JSP displays the results returned from the content query.

Listing 12-2 Example of a Syndicated Feed JSP for an Item—rss_item.jsp
<%@page contentType="text/html;charset=UTF-8" language="java"%>
<%@ page import="com.bea.content.Node" %>
<%@ page import="com.bea.content.ContentContext" %>
<%@ page import="com.bea.content.virtual.version.Version" %>
<%@ page import="com.bea.content.federated.ContentManagerFactory"%>
<%@ page import="com.bea.content.federated.INodeManager"%>
<%

String path = request.getRequestURL().toString();
path = path.substring(0, path.indexOf(request.getContextPath()));
request.setAttribute("rootURL", path+"/"+ request.getContextPath());

   if(request.getAttribute("node") != null){
      Node node = (Node)request.getAttribute("node");
      if(node != null){
      String nodePath = node.getPath();
      request.setAttribute("parameters", request.getAttribute("rootURL") +
         "/ShowProperty?nodePath="+nodePath);
      request.setAttribute("path", request.getAttribute("rootURL") +
         "/ShowProperty?nodePath="+nodePath);
      request.setAttribute("title", node.getName());
   }
   else{
      request.setAttribute("parameters", "#");
      request.setAttribute("path", "Node could not be found from path");
      request.setAttribute("title", "Null Node Exception");
   }
}
else if (request.getAttribute("version") != null){
      Version version = (Version)request.getAttribute("version");
      if(version != null){
         INodeManager nodeMgr = ContentManagerFactory.getNodeManager();
         Node node = nodeMgr.getNodeByUUID(new ContentContext(),
            version.getNodeId());
         if(node != null){
            String nodePath = node.getPath();
            request.setAttribute("parameters", request.getAttribute("rootURL") +
               "/ShowProperty/"+nodePath+"||versionId="+version.getVersionName());
            request.setAttribute("path", request.getAttribute("rootURL") +
               "/ShowProperty/"+nodePath+"||versionId="+version.getVersionName());
            request.setAttribute("title", node.getName());
         }
         else{
            request.setAttribute("parameters", "#");
            request.setAttribute("path", "Node could not be found from path");
            request.setAttribute("title", "Null Node Exception");
      }
      else{
         request.setAttribute("fullURL", "Version attribute was null");
         request.setAttribute("title", "Null Version");
         request.setAttribute("description", "Null Node");
      }
}
%>
<item>
   <title>${title}</title>
   <link>${fullURL}</link>
   <description>${description}</description>
</item>
Displaying the Contents of an Item

As previously mentioned, the JSP selects the data from the repository and displays it. The end of Listing 12-2 contains the following HTML, which displays each item in a syndicated list:

<item>
   <title>${title}</title>
   link>${fullURL}</link>
   <description>${description}</description>
</item>

The rss_detailed_view.jsp contains the HTML that displays the contents of the item in the list, that is, the article itself, as shown in Listing 12-3.

Listing 12-3 Example Syndicated Feed JSP for an Article—rss_detailed_view.jsp.
...
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>View Details: ${title}</title>
<style>
   body {background-color:#FFFFFF; font-family:arial, sans-serif;
      font-size: 1em; color:#000000;}
   p td {font-family:arial, sans-serif; font-size: 100%; color:#000000;}
   h1 {font-size:120%; border-bottom: 1px solid #CCCCCC;}
   .notetext {font-size:80%; width: 50%; padding:10px; border: 1px solid
   #FFCC33; background-color: #FFFFCC}
</style>
</head>
<body>
   <h1>View Details: ${title}</h1>
   <div class="notetext">In this view, you can display useful properties for
      the selected feed item, and format them with the display template. By
      default, we display a few system properties.</div>
   <p>Location in Repository: ${nodePath}</p>
   <p>Created on: ${createdDate}</p>
   <p>Created by: ${createdBy}</p>
   <p>Primary Property Details: <a href="${parameters}">View Binary</a></p>
</body>
</html>

Modifying the Syndication Configuration File

The syndication configuration file sets the parameters passed to the Syndication Producer Servlet and maps the Syndication Feed JSPs to a namespace, which allows you to change which display templates are used.

To modify the preconfigured syndicated feeds in WorkSpace Studio, from the Merged Projects View, copy the WEB-INF\wlp-syndication-config.xml file to your web project, and then edit the file. For information on how to use WorkSpace Studio for this purpose, see Working with the Merged Projects View.

Listing 12-4 shows the syndication configuration file (wlp-syndication-config.xml) for the preconfigured syndicated feeds.

Listing 12-4 Example of a Syndication Configuration File (wlp-syndication-config.xml)
<?xml version="1.0"?>
<wlp-syndication-config xmlns="http://www.bea.com/ns/content/102/wlp-syndication-config">
   <syndication-feed>
      <name>LatestContent</name>
      <search-query>cm_nodeName like '*'</search-query>
      <search-type>pubmeta</search-type>
      <search-max-results>20</search-max-results>
      <search-sort-order>cm_createdDate desc</search-sort-order>
   </syndication-feed>
   <syndication-feed>
      <name>NeedToApprove</name>
      <search-query>cm_lifeCycleStatus = 3 &amp;&amp; cm_assignedToUser =
         requestProperty('DefaultRequestPropertySet', 'Remote
         User')</search-query>
      <search-type>vermeta</search-type>
   </syndication-feed>
   <syndication-feed>
      <name>DirectoryContents</name>
      <search-query>cm_path like '/BEA Repository/*'</search-query>
      <search-type>pubmeta</search-type>
      <search-max-results>20</search-max-results>
      <search-sort-order>cm_createdDate desc</search-sort-order>
   </syndication-feed>
   <syndication-style>
      <name>rss</name>
      <name-space>bea-rss</name-space>
      <channel-group-name>ContentRepoRSS</channel-group-name>
      <channel-template>RSSChannel</channel-template>
      <channel-header-view>channelHeader</channel-header-view>
      <channel-footer-view>channelFooter</channel-footer-view>
   </syndication-style>
   <syndication-item-style>
      <name>rss_detailed_view</name>
      <name-space>bea-rss</name-space>
      <item-view>detailedView</item-view>
   </syndication-item-style>
</wlp-syndication-config>
Search Types

There are two search types in the <syndication-feed> element, as shown in Listing 12-4:

These search types direct the Syndication Producer Servlet to query data from either a published (pubmeta) or versioned (vermeta) repository. The default search type is pubmeta.

Depending on the search type, either the node or versioned search property is set in the syndicated feed JSP (Listing 12-2). Specifically, the node or version is set to not null.

The vermeta search type is most often used in a workflow. You can only use this search type in a managed repository, that is, a repository where a library services are enabled. For more information, see Working with BEA Repository Content When Using Library Services.

Syndication Configuration Options

The syndication configuration file for the preconfigured syndicated feeds offer a number of options. For example, you can change the order of results from descending to ascending. The available parameters are based on the XML schema shown in Listing 12-6. The following options are available:

Table 12-2 Available Parameters for Passing into the Syndication Producer Servlet 
Parameter
Description
Content Queries—use these parameters to find the information to be displayed in the syndicated feed.
feedName
The name of an RSS feed stored within wlp-syndication-config.xml.
syndicationStyleName
The name of the format to use, such as RSS, Atom, and so on. Stored within wlp-syndication-config.xml.
searchQuery
The content search expression.
searchType
The type of search to execute:
  • pubmeta—published metadata search (default)
  • vermeta—versioned metadata search
searchSortOrder
Sort order of search results.
searchMaxResults
The maximum number of results to return from a search.
nameSpace
The content template name space, which is used to look up content templates for both <content-name-space> and <template-name-space> within the wlp-template-config.xml. If not provided, defaults to bea-rss.
RSS Channel Related Parameters—use these parameters to find the content template for creating the RSS channel header.
channelGroupName
Content template group name.
channelTemplate
Content template name.
channelView
View name of the content template.
RSS Item Related Parameters—use these parameters to find the content template for creating each RSS item.
itemResourceName
Content template resource name.
itemRepositoryName
Content template repository name.
itemView
Content template view name.

Selecting a Display Template

The wlp-syndication-config.xml file contains entries that map to the display template JSPs in the wlp-template-config.xml file. For example, in the wlp-syndication-config.xml file (Listing 12-4), the syndication-style elements point to corresponding elements (and JSPs) in the wlp-template-config.xml file (Listing 12-5).

From the wlp-syndication-config.xml file:

<syndication-style>
   <name>rss</name>
   <name-space>bea-rss</name-space>
   <channel-group-name>ContentRepoRSS</channel-group-name>
   <channel-template>RSSChannel</channel-template>
   <channel-header-view>channelHeader</channel-header-view>
   <channel-footer-view>channelFooter</channel-footer-view>
</syndication-style>

From the wlp-template-config.xml file:

<view> 
   <name>channelHeader</name>
   <uri>/rss/rss_header.jsp</uri>

</view>

This design allows you to point to your own JSPs by making changes in the wlp-template-config.xml file. For example, to point to your header JSP you could change the URI from /rss/rss_header.jsp to /atom/atom_header.jsp.

To modify the preconfigured display template configuration file in WorkSpace Studio, from the Merged Projects View, copy the WEB-INF\wlp-template-config.xml file to your web project, and then edit the file. For information on how to use WorkSpace Studio for this purpose, see Working with the Merged Projects View.

Listing 12-5 Example of a Display Template Configuration File (wlp-template-config.xml)
<?xml version="1.0" ?> 
<wlp-template-config xmlns="http://www.bea.com/ns/p13n/90/wlp-template-config">
<content-repository>
   <name>*</name>
   <default-template-uri>/rss/rss_item.jsp</default-template-uri>
   <content-name-space>
      <name>bea-rss</name>
      <content-resource>
         <name>*</name>
         <default-template-uri>/rss/rss_item.jsp</default-template-uri>
         <view>
            <name>detailedView</name>
            <uri>/rss/rss_detailed_view.jsp</uri>
         </view>
      </content-resource>
   </content-name-space>
</content-repository>
   <template-group>
      <name>ContentRepoRSS</name>
      <template-name-space>
         <name>bea-rss</name>
         <template>
            <name>RSSChannel</name>
            <default-template-uri>/rss/rss_header.jsp</default-template-uri>
            <view>
               <name>channelHeader</name>
               <uri>/rss/rss_header.jsp</uri>
            </view>
            <view>
               <name>channelFooter</name>
               <uri>/rss/rss_footer.jsp</uri>
            </view>
         </template>
      </template-name-space>
   </template-group>
</wlp-template-config>

 


Creating Custom Syndicated Feeds

It is likely that you want syndicated feeds customized to your organization. For example, you'll need to develop JSPs that display the portions of data in your content repositories that you want to show your users, such as the name of the article and author's name. Additionally, you probably want to present the information in a format consistent with the look-and-feel of your portal. You can either use one of the preconfigured syndicated feed JSPs as a starting point or build one from scratch.

Tip: Be sure to read Using and Modifying the Preconfigured Syndicated Feeds to help you understand how syndicated feeds work.

You can create syndicated feeds that are compatible with different readers, such as Atom. To speed your development process, you can use the same content query to retrieve information from your databases and present that content with different XML formats for different readers.

Because content repositories are connected to WebLogic Portal using the Virtual Content Repository, your JSP display templates can show data in any content repository as long as the repository is connected to the Virtual Content Repository. For more information, see Introduction.

Creating the Syndicated Feed JSPs

Syndicated feed JSPs contain the logic to render the syndicated feed.

Generally, you need to create four JSPs:

For information on using WorkSpace Studio to create JSPs, see Tutorial: Working with JSPs.

After you develop your display templates (JSPs), you map them to a namespace using a display template configuration file (wlp-template-config.xml). Display templates are then referenced from the syndication configuration file (wlp-syndication-config.xml).

Map the Syndicated Feed JSPs to Display Templates

To map your display templates to a namespace, you create a wlp-template-config.xml file. Display templates are then referenced from a syndication configuration file (wlp-syndication-config.xml). For detailed information on how this works, see Selecting a Display Template.

For information about creating a wlp-template-config.xml file, see Creating a wlp-template-config.xml File. When creating a template configuration file in this way, in the Create XML File page, select Create XML file from scratch.

Figure 12-3 Create XML File

Create XML File

For more information about display templates, see Using Display Templates.

Create a Syndication Configuration File

The syndication configuration file sets the parameters passed to the Syndication Producer Servlet and maps the Syndication Feed JSPs to a namespace, which allows you to select which display templates are used. For more information, see Selecting a Display Template.

Listing 12-6 shows the XML schema for wlp-syndication-config.xml. It contains the valid attributes and tags you can use when configuring the wlp-syndication-config.xml file.

Listing 12-6 Schema for the Syndication Configuration File
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://www.bea.com/ns/content/102/wlp-syndication-config"
elementFormDefault="qualified" attributeFormDefault="unqualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:complexType name="syndication-styleType">
   <xs:sequence>
      <xs:element name="name" type="xs:string" minOccurs="0" nillable="true"/>
      <xs:element name="name-space" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="channel-group-name" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="channel-template" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="channel-header-view" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="channel-footer-view" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="item-resource-name" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="item-repository-name" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="item-view" type="xs:string" minOccurs="0"
         nillable="true"/>
   </xs:sequence>
</xs:complexType>
<xs:complexType name="syndication-configType">
   <xs:sequence>
      <xs:element name="syndication-feed" maxOccurs="unbounded"
         type="wlp:syndication-storeType" minOccurs="0" nillable="true"
         xmlns:wlp="http://www.bea.com/ns/content/102
         /wlp-syndication-config"/>
      <xs:element name="syndication-style" maxOccurs="unbounded"
         type="wlp:syndication-styleType" minOccurs="0" nillable="true"
         xmlns:wlp="http://www.bea.com/ns/content/102/
         wlp-syndication-config"/>
      <xs:element name="syndication-item-style" maxOccurs="unbounded"
         type="wlp:syndication-item-styleType" minOccurs="0" nillable="true"
         xmlns:wlp="http://www.bea.com/ns/content/102/
         wlp-syndication-config"/>
   </xs:sequence>
</xs:complexType>
<xs:complexType name="syndication-storeType">
   <xs:sequence>
      <xs:element name="name" type="xs:string" minOccurs="0" nillable="true"/>
      <xs:element name="search-query" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="search-type" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="search-max-results" type="xs:int" minOccurs="0"
         nillable="true"/>
      <xs:element name="search-sort-order" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="name-space" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="channel-group-name" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="channel-template" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="channel-footer-view" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="channel-header-view" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="item-resource-name" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="item-repository-name" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="item-view" type="xs:string" minOccurs="0"
         nillable="true"/>
   </xs:sequence>
</xs:complexType>
<xs:complexType name="syndication-item-styleType">
   <xs:sequence>
      <xs:element name="name" type="xs:string" minOccurs="0" nillable="true"/>
      <xs:element name="name-space" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="item-resource-name" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="item-repository-name" type="xs:string" minOccurs="0"
         nillable="true"/>
      <xs:element name="item-view" type="xs:string" minOccurs="0"
         nillable="true"/>
   </xs:sequence>
</xs:complexType>
<xs:element name="wlp-syndication-config" type="wlp:syndication-configType"
   xmlns:wlp="http://www.bea.com/ns/content/102/wlp-syndication-config"/>
</xs:schema>

 


Securing Syndicated Feeds

Usually, you control visitor access to portal resources by configuring visitor entitlements in the WebLogic Portal Administration Console. However, a malicious user who knows the correct URL can access the syndicated feed directly. If you want to secure your syndicated feeds, you must use Java EE security. Specifically, you use web.xml deployment descriptors to secure access to the Syndication Producer Servlet.

In following example, the web.xml deployment descriptors restrict any HTTP GET or POST requests from a URL in the form /SecureFeedProducer/*. These descriptors allow only users whose role is Administrators, Portal System Administrator, or AppTesters.

Listing 12-7 Security Deployment Descriptors
<security-constraint>
   <web-resource-collection>
      <web-resource-name>Secure Syndication</web-resource-name>
      <description>The Secure Rss Feeds</description>
      <url-pattern>/SecureFeedProducer/*</url-pattern>
      <http-method>GET</http-method>
      <http-method>POST</http-method>
   </web-resource-collection>
   <auth-constraint>
      <description>Administrators</description>
      <role-name>Administrators</role-name>
      <role-name>PortalSystemAdministrator</role-name>
      <role-name>AppTesters</role-name>
   </auth-constraint>
   <user-data-constraint>
      <transport-guarantee>NONE</transport-guarantee>
   </user-data-constraint>
</security-constraint>

For more information about security deployment descriptors, see web.xml Deployment Descriptor Elements in Developing Web Applications, Servlets, and JSPs for WebLogic Server.


  Back to Top       Previous  Next