Oracle9i LDAP: Advanced Configuration of Directory Naming



Oracle9i LDAP: Advanced Configuration of Directory Naming

Daniel T. Liu, Senior DBA

First American Real Estate Solutions

Introduction

Oracle Net enables services and their applications to reside on different computers and communicate as peer applications. Network information is stored in multiple places and in multiple formats. The main function of Oracle Net is to establish network sessions and transfer data between a client machine and a server or between two servers. There are different resolution methods used by Oracle Net to resolve a name and help a client to locate a database. The most common practice is storing net service names in a local naming configuration file called tnsnames.ora. But this method becomes a maintenance nightmare for the network and database administrators in a dynamic and multi-platform environment.

OID (Oracle Internet Directory) provides a new mechanism of resolving net service names by storing database-connecting information in a LDAP (Lightweight Directory Access Protocol) Server. LDAP-based name resolution is considered an industry-standard as compare to the more proprietary Oracle Names Server. The OID also replaces the need for storing connecting information on each individual client machine. This solution reduces the cost of maintenance by 50-95% depending on the number of databases and the topology of the network.

This paper discusses the required steps to install, configure and setup an Oracle Internet Directory Server for name resolution. It offers an introduction to the basic concepts of OID and Oracle Net. It shows how to use Oracle Net administration tools, such as Oracle Directory Manager, Net Configuration Assistant and Net Assistant, to configure ldap.ora, listener.ora, sqlnet.ora and tnsnames.ora files. It also shows how to use command line utilities, such as "oidmon" and “oidctl” to start and stop OID Monitor and OID server instance. This paper also discusses the process of migrating from Local Naming and Oracle Names to LDAP directory.

Net Services Basics

Oracle Net Services provide enterprise wide connectivity solutions in distributed, heterogeneous computing environments. It consists the following major components:

Net Services client

Net Services Client enables client connections to databases across a network. A client-side application sends a request to Oracle Net Services to be transported across the network to the server.

Net Service Server

Net Services Server enables the listener, through a protocol, to accept connections from client application on the network.

Oracle Net

Oracle Net is a software layer that resides on the client and the Oracle database server. It is responsible for establishing and maintaining the connection between the client application and server, as well as exchanging messages between them, using industry-standard protocols. Oracle Net is comprised of two software components:

Oracle Net Foundation Layer

Oracle Net Foundation Layer provides a standard method for a client application to establish and maintain communication with the Oracle database server on top of industry-standard network protocol.

Oracle Protocol Support

Oracle supports the following protocols:

TCP/IP – the de facto standard Ethernet protocol used for client/server communication over a network. This protocol is used in Unix and NT environments.

TCP/IP with SSL – Oracle Advanced Security is required in order to use TCP/IP with Secure Sockets Layer. SSL stores authentication data in an Oracle Wallet. When the client initiates a Oracle Net connection to the server, SSL performs a handshake between the two using the certificate or the private key.

Named Pipes – is a high-level interface providing inter-process communications between clients and server and is specifically designed for PC LAN environments.

LU6.2 – the Logical Unit Type 6.2 protocol is part of the IBM Advanced Program-to-Program Communication architecture.

VI – The Virtual Interface (VI) protocol can be used for application Web server and database server communication. It is the de facto standard protocol for cluster server environment, and is more efficient than TCP/IP.

Listener

The listener is a separate process that resides on the database server. It receives incoming client connection requests and manages the traffic of these requests to the server.

A listener is configured with one or more listening protocol addresses and service information about the destination service. Service information may or may not be configured in the listener.ora file.

Oracle7 or Oracle8 release 8.0 requires service configuration in the listener.ora file. Oracle8i and Oracle9i have a feature called service registration, which automatically registers information with the listener and does not require configuration in the listener.ora file.

The listener has a default name of LISTENER and is configured to listen on the following default protocol addresses:

• TCP/IP protocol on port 1521

• IPC protocol – for external procedures

A listener can listen for one or more databases either on the same database server or on different servers. One listener can also listen for different versions of databases.

In practice, it is always a good idea to have at least one listener for each version of database on each system and name the listener to some meaningful name instead of the default.

Anytime the listener.ora is modified, the listener must be either reloaded or stopped/re-started with the LSNRCTL utility.

If you expect the listener to handle large volumes of connection requests, you may specify a queue for the process. This enables the listener to dynamically handle larger numbers of concurrent connection requests.

Making the Connection

When a user connects to a database service from across the network, a connect descriptor containing network information about the destination service is passed to the listener. The listener, through a protocol, accepts the client connection. It compares the client information with the information it has received from the database, as well as information it has stored in its own configuration file, listener.ora. If the information matches, a connection is granted.

Direct Connecting Method

One method is to create a lengthy connect string as follow:

Connect scott/tiger@(description =

(address = (protocol = tcp)

(host=)

(port=1521))

(connect_data = (service_name=)))

In-Direct Connecting Method

A more common way is through use of a net service name, another name for the service, which maps to a connect descriptor to avoid a lengthy connect string:

connect scott/tiger@db1

Oracle Net uses this simple name, call a connect identifier, to identify a connect descriptor. When a net service name is used, connection processing takes place by first mapping the connect identifier to the connect descriptor. This mapped information is stored in one or more repositories of information that are accessed with naming methods.

Naming Methods

Local Naming

Local naming stores net service names and their connect descriptors in a localized configuration file named tnsnames.ora.

Tnsnames.ora is the configuration file resides on the client’s ORACLE_HOME/network/admin/ directory. This file provides information on the database service name, the network route to the service, including the location of the listener through a protocol address.

Host Naming

Host naming enables users to connect to an Oracle database by using a host name alias. Host names are mapped to the database server’s global database name in an existing names resolution service, such as DNS (Domain Name System), or a centrally maintained set of /etc/hosts files.

External Naming

External naming stores net services names and their connect descriptors in a supported non-Oracle, third-party naming service, such as NIS (Network Information Service) External Naming.

Oracle Names

Oracle Names uses Oracle proprietary software to store the names and addresses of all database services on a network. Clients wishing to connect to a database server direct their connect requests to an Oracle Names Server. Oracle Names Servers resolve the name to a network address and return that information to the client. Oracle9i will be the terminal release of Oracle Names.

Directory Naming

Directory Naming stores net service names and database service names in a centralized LDAP-compliant directory server to access a database service. Today, network information is stored in multiple systems and in multiple formats. With new requirements for Internet computing and new e-business technologies, there is a growing need for a common infrastructure to serve as a foundation for management and configuration of all data and resources in the network. This kind of infrastructure reduces the cost of managing and configuring resources in heterogeneous networks. Oracle strongly recommend storing net service names in the new industry-standard Directory, such as Oracle Internet Directory, to take advantage of superior features in Oracle8i and significant enhancements in Oracle9i.

In order to setup a Directory Naming using Oracle Internet Directory, we first need to understand the basic concept and architecture of Directory, LDAP and Oracle Internet Directory.

Oracle Internet Directory (OID) Basics

Directory

A directory is a specialized database that stores and retrieves collections of information. Such information can represent any resources that require management: employee information, information about shared network resources, or information about database service name. Although a directory is a database, it is not a relational database. A directory has the following characteristics:

• Primarily read-focused

• Designed to handle relatively simple transactions on relatively small units of data

• Designed to be location-independent

• Designed to store information in entries

LDAP

LDAP stands for Lightweight Directory Access Protocol. It is a standard, extensible directory access protocol. LDAP was conceived as an Internet-ready, lightweight implementation of the International Standardization Organization X.500 standard for directory services. The LDAP standard simplifies management of directory information in three ways:

• It provides all users and applications in the enterprise with a single, well-defined, standard interface to a single, extensible directory service.

• It reduces the need to enter and coordinate redundant information in multiple services scattered across the enterprise.

• Its well-defined protocol and interfaces make it more practical to deploy Internet-ready applications that leverage the directory.

OID

OID stands for Oracle Internet Directory. It is a general-purpose directory service that enables fast retrieval and centralized management of information about dispersed users and network resources. OID is a full-featured LDAP Version 3 compliant directory service implemented as an application on the Oracle8i and Oracle9i database. Its top 3 benefits includes:

• Scalability – exploits the strengths of Oracle9i, enabling support for terabytes of directory information.

• High Availability – is designed to meet the needs of a variety of important applications such as multi-master replication between directory servers and fast recover from system failures.

• Security – offers comprehensive and flexible access control.

Oracle Internet Directory’s unique strength makes it an ideal candidate for central name resolution. Its industry-standard protocol provides greater advantage over the more proprietary Oracle Names Server.

OID Terminology

Entries - each collection of information about an object in a directory is called an entry.

DN - each entry in a directory is uniquely identified by a distinguished name.

DIT - the distinguished name tells exactly where the entry resides in the directory's hierarchy. A Directory Information Tree represents this hierarchy.

RDN - the lowest component of a distinguished name is called the relative distinguished name.

Attributes - the information about an entry in the directory is called attributes.

Object Classes - An object class is a group of attributes that define the structure of an entry. At installation, Oracle Internet Directory provides standard LDAP object classes.

Directory Schema - The directory schema contains all information about how data is organized in the DIT (Meta data such as an object class, an attribute, a matching rule, and syntax).

Naming Contexts - A naming context is a subtree that resides entirely on one server. It must be contiguous, begin at an entry that serves as the top of the subtree and extends downward to either leaf entries or references to subordinate name contexts.

The figure below shows an Information Directory Tree of XYZ Company:

To better understand those OID terminologies, let's look at the figure above. It represents a Directory Information Tree for a 'XYZ Company'. Start from the root node, each node in the tree is an entry. Each entry in the directory is identified by a distinguished name, which tells you exactly where the entry resides in the directory's hierarchy. For example: the DN for entry "John" is: cn=John, ou=manufacturing, c=us, o=xyz company (cn for common name, ou for organization unit, c for country, and o or organization). Within a distinguished name, the lowest component is called relative distinguished name. The RDN for John's DN is John. Information about John such as telephone number, email address, job title, salary, employee ID is called attributes. An employee’s object class can present this collection of employee’s information structure. All the information about how data is organized in the DIT is stored in a directory schema. A naming context can represent a subtree of the DIT, such as employee Dan works in Marketing Department.

OID Architecture

An Oracle Internet Directory node consists of the following major components:

Oracle Directory Server Instance - also called either LDAP server instance or directory server instance. An OID instance comprises one OID listener/dispatcher process listening at a specific TCP/IP port, and one or more Oracle directory server processes. Each LDAP server node can contain more than one OID instances.

OID Monitor - it initiates, monitors, and terminates the LDAP server processes. It checks the state of the servers through mechanisms provided by the operating system. The activity logs are stored at $ORACLE_HOME/ldap/log/oidmo.log.

OID Control Utility (OIDCTL) - communicates with OID Monitor by placing message data in OID server tables. This message data includes configuration parameters required to run each OID instance.

Oracle9i Database - stores the directory data.

How Net Services Use a Directory Server?

To comprehend how net services use a directory server, we must first understand how net service names are stored in an Oracle Internet Directory.

As showed in figure 6, directory information is stored in an Oracle database. In order to bring up a LDAP server instance, we must first create an OID repository database. Once the OID database is up and running, we need to create the OID schema. The OID schema includes two database users: 'ods' and 'odscommon'. The 'ods' user contains 47 tables, which holds the meta data information of the Oracle Directory structure; Oracle Directory Server connects to OID database as 'odscommon' user.

In the directory server, information is organized and stored in the format of directory information tree (DIT). To store net service information, we need to create a DIT subtree structure that either match the existing domain structure used with our tnsnames.ora, or an entirely different structure in which a net service client can recognize. The next step is to create an Oracle Context under each DIT location. The Oracle Context has a relative distinguished name (RDN) of (cn=OracleContext). The Oracle Context stores network object entries, as well as other entries for other Oracle components. The net service name is usually the entry under Oracle Context entry. All the net service attributes (such as host name, port number and service name) are stored in the entry below Oracle Context.

When a net services client connect to a database via Directory Naming, it will first connect to OID server. The OID server connects to the OID database. It searches net service connecting information from the directory tree. Net services information is retrieved and returned to the client. The client is now able to contact the proper listener and connects to the right database (see figure 7).

Step-by-Step Setup of Oracle Internet Directory for Names Resollution

The following eight steps show how to setup Oracle Internet Directory Server in the “” network domain:

Step #1: Planning the Network

1. Understanding the different version of Oracle Internet Directory.

• Oracle Internet Directory 2.0.6 is the first release of Oracle LDAP server and it comes with Oracle 8.1.6. Therefore, it would not support name resolution method for client running Oracle release prior to 8.1.6.

• OID store its directory information in an Oracle database. The OID repository database version has to match with its Oracle Internet Directory server as table listed below:

|Oracle Internet Directory |Database Version for OID Repository |

|2.0.6 |8.1.6 |

|2.1.1 |8.1.7 |

|3.0.1 |9.0.1 |

2. Examine company’s existing Oracle network environment.

• List of all the network domains

• Oracle database servers within each domain

• Oracle Instances and listeners running on each server

• Number of Oracle clients

3. Planning the Directory Tree

• Let’s assume that we are working with a single domain called “”.

• Six Oracle instances are registered under “” domain.

Step #2: Installing Oracle Internet Directory Software

For simple illustration, let us assume we are performing a new installation and creating a new OID database on the same server. The complete installation will include step 2, 3 and 4.

1. Read the Install Guide.

2. Prepare the environment.

Make sure the PATH, ORACLE_BASE, ORACLE_HOME, NLS_LANG are set correctly if it is in the Unix Server.

Make sure TCP port 389 is not in use by another process.

3. Mount the CD and bring the Universal Installer up.

4. When the available products window appears. Choose ‘Management and Integration’ option and then ‘Oracle Internet Directory’ option.

5. In the next window, we can choose to install OID schema on an existing database or to install OID schema on new database. It is prefer to have a new independent OID database. We can create an OID database and schema objects either separately or during the installation. If we choose to create a new OID database and its schema objects during installation, the next few installation dialog windows appear requesting for database identification and file location information.

6. Then the "Summary" window will appear. Review the information and ensure that enough disk space is available. Click Install.

7. The "Install" window appears and the file copy process begins. (You may prompt to run root.sh script as root user if you are installing on Unix system)

Step #3: Creating OID Repository Database and OID Schema

1. The Configuration Tools window appears at the end of installation.

2. The Universal Installer will first create and start an OID database instance.

3. Next, it will create the OID schema and schema objects. This step can also be performed manually by running $ORACLE_HOME/ldap/admjn/newldap.sql script from SQL*PLUS as 'system' user.

4. When OID schema creation is completed, the End of Installation window appears. Choose Exit install.

5. Review the Log file for any installation errors.

Step #4: Starting Oracle Internet Directory Server

1. After successfully completed the installation, the default OID Monitor Daemon and LDAP Server Instance will already be running against OID database instance.

2. We can also choose manually start the OID instance, OID monitor and OID server by issuing the following commands:

Oidmon connect= start

Oidctl connect= server=oidldapd instance=1 start

Step #5: Setting up Directory Tree (Adding New Entry for Naming Context)

1. Invoke the Oracle Directory Manager, at the Connect screen, type user name and password. (The default admin username and password: orcladmin/welcome).

2. We can either use the default 'orcladmin' user or create a new admin user. Make sure the new admin user has "Browse, Add, Delete" Access Rights granted.

3. To create the naming context, click on "Entry Management" in the main screen. Click the "Create" (green box) button from the toolbar on the top.

4. A "New Entry" window pops up. In the "Distinguished Name" field, enter "dc=com", then click the "Add" button under "Object Classes". A new window "Super Class Selector" appears. Scroll through, highlight "Domain", and then click the "Select" button. "Domain" name should now appear in the Object Classes Window. Click the "Add" button under "Object Classes". Under "Super Class Selector" window, select "Top" option this time. The "Domain" and "Top" name should appear under "Object Classes". Still within the "New Entry" window, enter "com" in the "Mandatory Properties" field. Click the "Ok" button, you should see "dc=com" appears under the "Entry Management".

5. The next step is to add "company" entry under "com". Repeat the above step, accept put "dc=company,dc=com" in the "Distinguished Name" field, and put "company" in the "Mandatory Properties" field. You should now be able to click on "dc=com" and "dc=company" appears under it.

Step #6: Setting up an oracle Context

Once we have the directory structure setup, we can create an Oracle Context. The Oracle Context has a RND ( Relative Distinguished Name) of cn=OracleContext. The Oracle Context stores network object entries, as well as other entries for other Oracle components. In our case, cn=OracleContext is created under dc=company, dc=com.

1. Start the Net Configuration Assistant.

2. Choose "Directory Service Access Configuration" option.

3. In the next window, Choose "Create a new Oracle Context".

4. In the Directory Type box, select "Oracle Internet Directory".

5. In the Hostname filed, type the host name of the LDAP server.

6. In the next screen, enter an administrative context in which to create the Oracle Context. In our case, we will put "dc=company,dc=com".

7. When asked for username/password, you need to enter "cn=orcladmin" for the User DN and its password.

8. If the Oracle Context is created successfully, the authenticated user is added to the following groups in the directory:

• OracleDBCreators (cn=OracleDBCreators,cn=OracleContext)

• OracleNetAdmins (cn=oracleNetAdmins,cn=OracleContext)

Step #7: Adding Service names to OID

Now Oracle Internet Directory is ready to add Oracle service name.

If you already have a tnsnames.ora file or using Oracle Name Server, see the next section "Migrating from Local Naming and Oracle Names to OID" for details.

To add a Net Service Name to OID, you can either use Net Assistant or "ldapadd" command utility by supplying an LDIF (LDAP Data Interchange Format) file.

Method One:

1. Load Net Assistant. Under Net Configuration node, click "Directory".

2. The "Directory Server Authentication" window appears. Enter username and password (such as, user: cn=orcladmin, password: welcome).

3. Highlight "Service Naming" node. Go to menu "Edit", then "Create", the "Net Service Name Wizard" window appears, enter "Net Service Name", "Protocol", "Host Name", "Port Number" and "Service Name".

4. Click the "Finish" button, a new service name is added to OID.

5. Repeat step 3 and 4 to add more service names.

Method Two:

1. Prepare a LDIF file called example.ldif.

2. Execute the "ldapadd" command.

Syntax for "ldapadd" utility:

ldapadd -D {bind dn} -w {password} -h {ldap_host) -v {verbose mode}

-f {ldif entry file}

In our example:

ldapadd -D cn=orcladmin -w welcome -h server_name -v -f example.ldif

Step #8: Setting up the Client Machine

Once Oracle Internet Directory Server is running and service names are loaded, you need to set up your client machines.

1. Install Oracle Net client software.

2. Start the Net Configuration Assistant

3. Click "Naming Method Configuration" option.

4. Select "Directory" under Naming Methods. Click Finish.

5. This process also create ldap.ora file under $ORACLE_HOME/network/admin directory as follow:

6. If you want to have Oracle Name Server or tnsnames.ora file as backup Naming Methods, you should have a sqlnet.ora file in the above directory with LDAP is listed first in the following entry:

NAMES.DIRECTORY_PATH = (LDAP, ONAME, TNSNAMES)

Migrating from Local Naming and Oracle Names to OID

Migrating from Local Name

If there is already an existing tnsnames.ora file, one can automatically store all the entries on it into Oracle Internet Directory. To export Net Service Names from a tnsnames.ora File, follow the steps below:

1. Start Oracle Net Assistant.

2. Choose Command > Directory > Import Net Service Names.

3. Enter the user and password you used to create the Naming Context in OID. The user name should follow the same format like "cn=orcladmin".

4. The Directory Server Migration Wizard starts. Click Next.

5. The Select Net Service Names window appears. From the list, select the network domain (). Then, select the Net Service Names from the list you want export.

6. The Select Destination Context window appears. Select the Directory Naming Context that contains the Oracle Context from the Directory Naming list. The Directory Naming Context is part of a directory subtree that contains one or more Oracle Contexts. (in our case, we should have "OracleContext, dc=company,dc=com")

7. Click Next. The wizard exports the net service names.

8. Click Finish to complete the Directory Server Migration Wizard. Now OID has all the database connecting information loaded.

Migrating from Oracle names Server

Net Service Names stored in an Oracle Names Server can be exported directly to a directory server or in-directly to an LDIF (LDAP Data Interchange Format) file, which can then be used to load to the directory server:

Direct Export:

1. Go to the Oracle Names Server, dump the service address information to a tnsnames.ora file.

NAMESCTL> dump_tnsnames

2. Transfer the file to the LDAP server.

% ftp

ftp> put tnsnames.ora

3. Load the Net Service information from the tnsnames.ora file to the OID Server follow the step from “Migrating From Local Name”.

In-Direct Export:

1. Run DUMP_LDAP from Oracle Name Server.

NAMESCTL> dump_ldap –f sample.ldif

2. Go to LDAP server, run the "ldapadd" command.

Migrating by Proxy

If you are not ready to upgrade clients to 8.1.6 or later to support directory naming, you can use Oracle Names LDAP proxy Servers. See article “Migration by Proxy” in May 2001 of Oracle Magazine for detailed steps.

Conclusion

Oracle Net supports several categories of naming methods. Oracle Internet Directory (OID) provides a new mechanism of resolving net service names by storing database-connecting information in a LDAP (Lightweight Directory Access Protocol) Server. LDAP-based name resolution is considered an industrial standard as compare to the more proprietary Oracle Names Server. It also provides major benefits over local naming method (tnsnames.ora). The author covers the basic concepts of Oracle Net and Oracle Internet Directory. By following the steps given in this paper, you should have your OID Server running in no time.

About the Author

Daniel Liu is a senior Oracle Database Administrator at First American Real Estate Solutions in Anaheim, CA. He has many years of industry experience in database administration and software development. He has worked with large-scale databases in multi-platform environments. His expertise includes Oracle database administration, performance tuning, Oracle networking, and Oracle Application Server. Prior to First American RES, he has worked at companies such Allant Group (formally EMS), Automatic Data Processing, Commonwealth Edison and CNA Insurance.

As an Oracle Certified Professional, he taught Oracle certified DBA classes at Elite Consulting Group in Chicago. Daniel also taught IOUG University Seminar in Orlando. Daniel has published articles with DBAzine, Oracle Internals, and SELECT Journal. Daniel has received SELECT Editorial Award for Best Article in 2001. He has also given presentations at IOUG-A Live, LAOUG, OCOUG, NoCOUG, Oracle Open World and Oracle World. Daniel has served as panelist on Oracles of Oracle at IOUG-Live and User Expert Session at Oracle World. Daniel holds a Master of Science degree in computer science from Northern Illinois University. Daniel can be reached at (714)-701-3346 or by email at dliu@ or daniel_t_liu@.

References

Oracle9i Net Services. Release 1 (9.0.1);

Oracle Internet Directory, Administrator’s Guide. Release 3.0.1;

Oracle Internet Directory, Administrator’s Guide. Release 2.1.1;

Net8: A Step-by-Step Setup of Oracle Names Server; Oracle Open World 2000, Paper#271;

Oracle Metalink and support papers numbers:

Note: 157892.1, Quick Start Guild: Oracle Internet Directory Installation 3.0.1;

Note: 112763.1, Example of LDAP setup for Net8 Administration;

Note: 120717.1, Net*8 LDAP Naming: Adding TNS Service Names to an OID.

I would also like to acknowledge the assistance of Bob Polak of the Allant Group, Johnny Wedekind of ADP, Ann Collins, Larry Bailey, Husam Tomeh and Archana Sharma of FARES and Elaine Chan of Rational.

All companies and product names are trademarks or registered trademarks of the respective owners. Please report errors in this article to the author. Neither FARES nor the author warrants that this document is error-free.

-----------------------

listener_dallas =

(address_list =

(address =

(protocol = ipc)

(key = db1)

)

(address =

(protocol = tcp)

(host = )

(port = 1521)

(queuesize=20)

)

)

sid_list_listener_dallas=

(sid_list =

(sid_desc =

(global_dbname = )

(sid_name = db1)

(oracle_home = d:\oracle\oracle81)

)

)

Figure 2

=

(description =

(address=(protocol = tcp) (host = ) (port = 1521))

(connect_data = (service_name = ))

)

Figure 4

[pic]

# LDAP.ORA Network Configuration File:D:\oracle\ora81\network\admin\ldap.ora

# Generated by Oracle configuration tools.

DEFAULT_ADMIN_CONTEXT = "dc=company,dc=com"

DIRECTORY_SERVERS= (dliu:389:636)

DIRECTORY_SERVER_TYPE = OID

Figure 10

[pic]

[pic]

[pic]

dn:cn=db1,dc=Oraclecontext,dc=company,dc=com

objectclass: top

objectclass: db1NetServie

cn: db1

db1NetDescString: (description =

(address = (protocol = tcp)

(host = )

(port = 1521))

(connect_data = (service_name = )))

Figure 9

[pic]

[pic]

................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download