PK "+Aoa,mimetypeapplication/epub+zipPK"+AiTunesMetadata.plistD artistName Oracle Corporation book-info cover-image-hash 405280033 cover-image-path OEBPS/dcommon/oracle-logo.jpg package-file-hash 188082350 publisher-unique-id E10777-03 unique-id 476071987 genre Oracle Documentation itemName Oracle® Multimedia User's Guide, 11g Release 2 (11.2) releaseDate 2010-07-30T10:35:11Z year 2010 PKdޅIDPK"+AMETA-INF/container.xml PKYuPK"+AOEBPS/cover.htmO Cover

Oracle Corporation

PK[pTOPK"+AOEBPS/ch_appdev.htm Oracle Multimedia Application Development

2 Oracle Multimedia Application Development

Oracle Multimedia enables you to develop either traditional client/server or two-tier applications, or multitier applications. Either method can then deploy Web applications to run on an application server tier, be tightly integrated with Oracle Database, and enable users to access the application from their desktop through a Web browser.

Using a complete development framework supported by class library interfaces, you can create production quality Oracle Multimedia applications for use in a production environment where users can interact with the application through either the standalone client interface or a Web browser. For Web applications, which are based on standards such as TCP/IP, HTTP, HTML, XML, and XHTML, this capability is facilitated by rapid developments in the underlying technology. As key software components become more tightly integrated, developers' tasks to design, create, and manage Web applications become faster, easier, and simpler to implement.

Using either the object type interface or the relational interface, Oracle Multimedia provides Internet support for Oracle Fusion Middleware and Oracle Database and authoring tools so you can quickly develop Web-based applications to upload to the database, retrieve from it, and manipulate multimedia data for delivery to Web browsers.

This chapter includes these sections:

See these chapters for more sample applications:

ChapterSample Application
Chapter 3
Describes the Oracle Multimedia Photo Album sample Web application, which is implemented using PL/SQL, Java servlets, and JavaServer Pages (JSP). This sample application demonstrates how to apply the steps described in Section 2.3 and Section 2.5 in a real Web application to upload and retrieve media data stored in a database.
Chapter 4
Describes the Oracle Multimedia Code Wizard application, which lets you create PL/SQL stored procedures for the PL/SQL Gateway for uploading and retrieving media data stored in a database using Oracle Multimedia object types.
Chapter 5
Describes the Oracle Multimedia Java API sample application, which is implemented using Java, JDBC, and Oracle Multimedia Java classes. This sample application demonstrates how to apply the steps described in Section 2.4 in a real Java application to upload and retrieve media data stored in a database.

2.1 Overview of the Application Development Environment

Oracle Multimedia supports application development by providing these tools and capabilities, which are briefly described in the following subsections:

2.1.1 Java Class Libraries and Other Packages and Interfaces

Oracle Multimedia provides these Java class libraries, which enable access (insert, update, and retrieve) and manipulation (process) of multimedia data stored in the database:

  • Oracle Multimedia Java API class library

  • Java Advanced Imaging (JAI) classes in the Oracle Multimedia Java API class library

  • Oracle Multimedia Servlets and JSP Java API class library

  • Oracle Multimedia JSP Tag Library

And, Oracle Multimedia provides these specialized Java class libraries:

  • Oracle Multimedia DICOM Java API class library

  • Oracle Multimedia Mid-Tier Java API class library

Oracle Multimedia also integrates with the Oracle Multimedia/Oracle Application Development Framework Business Components (ADF Business Components) integration package, and with C++ and traditional 3GLs through modern class library interfaces. Class libraries provide access to multimedia data stored in the database in several ways.

Oracle Multimedia Java API Class Library

Using the Java database connectivity (JDBC) interface, the Oracle Multimedia Java API class library enables you to use Java proxy classes for Oracle Multimedia database objects to quickly develop Java applications for use on any tier (client, application server, or database) to manipulate and modify audio, image, and video data, or heterogeneous media data stored in a database. Oracle Multimedia Java API makes it possible for JDBC result sets to include both traditional relational data and Oracle Multimedia columns of object type media data, to easily select and operate on the result set, to access object attributes, and to invoke object methods. Section 1.10.1 for general information, and Section 2.4 for a description of how to use Java and JDBC to develop media-rich Java client applications using this Java class library.


See Also:


Java Advanced Imaging Classes

The Oracle Multimedia Java API class library includes several Java Advanced Imaging (JAI) classes. The Oracle Multimedia Java API describes three types of stream objects, which provide interfaces to BLOB and BFILE data, that can be used by JAI. These classes enable a JAI application to read and write image data stored in a database using Oracle Multimedia OrdImage objects, or in BLOBs or BFILEs. See Section 1.10.4 for general information.


See Also:

Oracle Multimedia Java API Reference for reference information about the JAI classes in this Java class library


Oracle Multimedia Servlets and JSP Java API Class Library

The Oracle Multimedia Servlets and JSP Java API class library supports Web technologies, enabling you to quickly develop Java applications using Java servlets and JavaServer Pages (JSP). See Section 1.10.3 for general information. Section 2.5 describes how to develop media-rich Java-based Web applications using this Java class library. Section 3.2 includes an example of a Java servlet application, and Section 3.3 includes an example of a JSP application.


See Also:

Oracle Multimedia Servlets and JSP Java API Reference for reference information about this Java class library


Oracle Multimedia JSP Tag Library

The Oracle Multimedia JSP Tag Library is an extension of the Oracle Multimedia Servlets and JSP Java API class library. This Java class library provides JSP tags that simplify retrieving and uploading media data from and to Oracle Database in multimedia JSP Web applications.


See Also:

Oracle Multimedia JSP Tag Library Guide for complete information about this Java class library

Oracle Multimedia DICOM Java API Class Library

Oracle Multimedia DICOM Java API is a specialized class library that enables users to write Java applications using the Oracle Multimedia object designed to store Digital Imaging and Communications in Medicine (DICOM) data. See Section 1.6.4 for general information.


See Also:


Oracle Multimedia Mid-Tier Java API Class Library

Oracle Multimedia Mid-Tier Java API is a specialized class library that enables users to write Java applications for extracting DICOM metadata outside of Oracle Database before the data is loaded into the database.


See Also:


Oracle Multimedia/Oracle Application Development Framework Business Components Integration Package

The Oracle Multimedia/Oracle Application Development Framework Business Components (ADF Business Components) integration package includes the Oracle Multimedia domain classes and a set of utilities for use with Oracle JDeveloper. Oracle JDeveloper is a Java-integrated development environment (IDE) tool that supports the application framework (ADF Business Components), enabling you to build multitier, component-based Internet applications. See Section 1.10.3 for general information.


See Also:

Oracle Database 2 Day + Java Developer's Guide for more information about Oracle JDeveloper and ADF Business Components


2.1.2 Integration With PL/SQL Gateway and PL/SQL Web Toolkit

Oracle Multimedia uses the PL/SQL Gateway (mod_plsql) feature of the Oracle HTTP Server and the PL/SQL Web Toolkit features of Oracle Fusion Middleware and Oracle Database to listen for browser requests, to execute stored PL/SQL procedures in the database using Oracle Net and Oracle Call Interface (OCI), and to generate an HTML page containing data and code for the response returned to the Web browser for display. As a Web application developer, you can write PL/SQL servlets and PL/SQL server pages (PSP) that invoke PL/SQL procedures stored in the database through an Oracle Net connection and OCI. See Section 2.3 for a description of how to use PL/SQL Gateway and PL/SQL Web Toolkit to develop PL/SQL Web applications. See Section 3.1 for an example of an application that uses the PL/SQL Gateway and PL/SQL Web Toolkit for Oracle Fusion Middleware and Oracle Database.


See Also:

Oracle Database Advanced Application Developer's Guide for more information about developing PL/SQL Web applications


2.1.3 Integration With Components in Other Oracle Development Tools

Oracle Multimedia integrates Oracle development tools with tightly integrated components to enable you to quickly and easily develop applications that provide access to (insert, update, and retrieve) and manipulation (process) of multimedia data stored in the database for delivery to Web browsers and client applications. These development tools include:

  • Oracle Portal

  • Oracle JDeveloper

  • Oracle Designer

  • Oracle Content Management SDK

Oracle Portal

Oracle Portal is a simple browser-based environment for building and deploying enterprise information portlets (EIPs). An enterprise portal provides access to portlets, which are summarized versions of applications and Web content situated in defined regions of the Web page. Oracle Portal portlets execute PL/SQL stored procedures residing in the database, which in turn generate an HTTP response in the form of a generated HTML page. Oracle Portal contains two predefined components: Forms and Reports, which both support rich media content being uploaded or downloaded between the database and the portal framework form or report. See Section 1.10.3 for general information.


See Also:

Oracle Fusion Middleware Developer's Guide for Oracle Portal in the Oracle Fusion Middleware Online Documentation Library for more information about this tool


Oracle JDeveloper

Oracle JDeveloper is an IDE tool, which is written 100% in Java, that supports the application framework (Oracle Application Development Framework Business Components). An Oracle Multimedia/ADF Business Components integration package includes the Oracle Multimedia domain classes and a set of utilities. The domain classes are wrappers of Oracle Multimedia Java API and inherit all the underlying multimedia retrieval, upload, and manipulation methods. The domain classes support the ADF Business Components APIs and provide built-in integrated multimedia capabilities, while the utility classes support the retrieval, rendering, and uploading of multimedia content. See Section 1.10.3 for general information.


See Also:

Oracle Fusion Middleware Extension SDK Reference for Oracle JDeveloper in the Oracle Fusion Middleware Online Documentation Library for more information about this tool


Oracle Designer

Oracle Designer is a tool used to manage software configuration management for controlling the evolution of an application from identification of components, through initiation, evaluation, authorization, development, and implementation. Oracle Designer can generate C++ classes that enable applications running on the client, on Oracle Fusion Middleware, or on Oracle Database to call Oracle Multimedia methods.

Oracle Content Management SDK

Oracle Content Management SDK enables you to create custom file system applications using XML and Java that use the features and capabilities of the database and a variety of Web-based interfaces, such as Java servlets and JSP pages, or executing SQL or calling stored PL/SQL procedures for execution in the transaction context of the database.

2.1.4 Integration With Third-Party Streaming Media Servers

Oracle Multimedia integrates with third-party streaming media servers to enable dynamic and direct delivery of multimedia data stored in the database to a media player client. These third-party streaming servers include:

  • Oracle Multimedia Plug-in for RealNetworks Server

  • Oracle Multimedia Plug-in for Microsoft Windows Media Services

You can download these plug-ins from the Oracle Multimedia Software section of the Oracle Technology Network Web site at

http://www.oracle.com/technology/products/multimedia/

Oracle Multimedia Plug-in for RealNetworks Server

Oracle Multimedia Plug-in for RealNetworks Server is a data source plug-in that enables a RealNetworks server to stream media data directly from Oracle Database to a media player client. The plug-in is installed with RealNetworks Server, and configured and managed using the administration tool of the streaming server. See Oracle Multimedia Plug-in for RealNetworks Streaming Servers Readme.


See Also:

http://www.realnetworks.com/ for more information about streaming servers from RealNetworks


Oracle Multimedia Plug-in for Microsoft Windows Media Services

Oracle Multimedia Plug-in for Microsoft Windows Media Services enables Microsoft Windows Media servers to stream multimedia content to a client directly from Oracle Database. This plug-in is installed on Windows 2003 Server, and configured with Windows Media Services. See Oracle Multimedia Plug-in for Microsoft Windows Media Services Readme.

2.2 Developing PL/SQL Client Applications Using the PL/SQL API

PL/SQL is a completely portable, high-performance transaction processing language that combines the data manipulation power of SQL with the data processing power of procedural languages.

This section briefly describes how to manipulate Oracle Multimedia database objects with the PL/SQL Application Programming Interface (API). The following Oracle Multimedia object types are available for storing media in the database:

The examples in this section use the sample schemas, which may be installed when you install Oracle.

The following subsections describe how to use various components of the PL/SQL development environment:


See Also:


2.2.1 Setting Up Your Environment for PL/SQL

To access files with PL/SQL, you must create a directory object in the database that points to a directory that is accessible by the database server. For example, the following command creates the MEDIA_DIR directory in the sample schema:

CREATE DIRECTORY MEDIA_DIR AS
    'c:\oracle\product\10.2.0\db_1\demo\schema\product_media';

To retrieve media data from the database to a file, you must grant the write permission on the specified directory to the appropriate user. For example:

GRANT WRITE ON DIRECTORY MEDIA_DIR TO SCOTT;

To upload media data from a file to the database, you must grant the read permission on the specified directory to the appropriate user. For example:

GRANT READ ON DIRECTORY MEDIA_DIR TO SCOTT;

Caution:

Performing any of these prohibited actions could cause internal errors and security violations in the database management system.

These users, under which Oracle-supplied Oracle Multimedia data types are installed, are created during database installation, and might change in future releases:

  • ORDSYS

  • ORDPLUGINS

  • SI_INFORMTN_SCHEMA

Do not connect to or modify any of these users or their contents (which are supplied by Oracle Multimedia and reserved by Oracle), with this exception:

  • You can add user-defined packages to the user ORDPLUGINS (see Chapter 7).


2.2.2 Media Query in PL/SQL

You can include media attributes (for example: height, width, and MIME type) in standard SQL queries by using accessor methods (for example: getHeight, getWidth, and getMimeType). Example 2-1, Example 2-2, and Example 2-3 show how to use these accessor methods to query one or more object attributes for image, audio, and video objects, respectively.

Example 2-1 Image Query (Height, Width, and MimeType Attributes)

SELECT t.product_id                  id,
       t.product_photo.getHeight()   height,
       t.product_photo.getWidth()    width,
       t.product_photo.getMimeType() mimetype
  FROM pm.online_media t;

Example 2-2 Audio Query (MimeType Attribute)

SELECT t.product_id                  id,
       t.product_audio.getMimeType() mimetype
  FROM pm.online_media t;

Example 2-3 Video Query (MimeType Attribute)

SELECT t.product_id                  id,
       t.product_video.getMimeType() mimetype
  FROM pm.online_media t;

2.2.3 Media Download in PL/SQL

To download media from the database into a file on the file system, call the export method of the Oracle Multimedia object. The following code example exports the image in the row with product_id 3117 to a file named 3117.jpg in the directory MEDIA_DIR. This code example highlights in bold the PL/SQL statements where this export operation takes place.

DECLARE
  img ORDImage;
  ctx RAW(64) := NULL;
BEGIN
  SELECT  product_photo 
    INTO  img 
    FROM  pm.online_media
    WHERE product_id = 3117;
  img.export(ctx, 'FILE', 'MEDIA_DIR', '3117.jpg');
END;
/

2.2.4 Media Upload in PL/SQL

Media upload means importing media data from the file system into the database tablespaces. The following series of steps is typical:

  1. Insert a new row into the table, creating new objects by using the init method of the Oracle Multimedia object type.

  2. Call the import method of the Oracle Multimedia object to bring the data from the file system into the database.

  3. Call the setProperties method of the Oracle Multimedia object to determine and populate the attributes of the object.

  4. Update the table so that the Oracle Multimedia object in the table contains the attribute values extracted in the previous step.

The PL/SQL code that implements these steps for inserting a new row in the PM.ONLINE_MEDIA table is shown in this example:

DECLARE
  img ORDImage;
  aud ORDAudio;
  vid ORDVideo;
  ctx RAW(64) := NULL;
BEGIN
  -- Insert a new row into the pm.online_media table.
  DELETE FROM pm.online_media WHERE product_id = 3003;
  INSERT INTO pm.online_media 
         (product_id, 
          product_photo, 
          product_audio,
          product_video)
  VALUES (3003, 
          ORDImage.init('FILE', 'MEDIA_DIR', 'laptop.jpg'),
          ORDAudio.init('FILE', 'MEDIA_DIR', 'laptop.mpa'),
          ORDVideo.init('FILE', 'MEDIA_DIR', 'laptop.rm'))
  RETURNING product_photo, product_audio, product_video
  INTO img, aud, vid;
  
  -- Bring the media into the database and populate the attributes.
  img.import(ctx); 
  -- ORDImage.import also calls ORDImage.setProperties.
  
  aud.import(ctx);
  aud.setProperties(ctx);
 
  vid.import(ctx);
  vid.setProperties(ctx);
    
  -- Update the table with the properties we have extracted.
  UPDATE pm.online_media
  SET    product_photo = img,
         product_audio = aud,
         product_video = vid
  WHERE  product_id = 3003;
  
  COMMIT;
END;
/

2.2.5 Handling Oracle Multimedia Exceptions in PL/SQL

Possible errors that can occur during run time should always be handled in your application. This practice enables the program to continue its operation even when it encounters a run-time error. This practice also enables users to know what went wrong during program operation. Proper error handling practices ensure that, whenever possible, you are always able to recover from an error while running an application. In addition, proper error handling provides you with the information you need so you always know what went wrong.

This section demonstrates proper error handling practices using code examples. These examples show how to handle some common Oracle Multimedia errors and other types of errors in PL/SQL programs. These examples are extracted from the PL/SQL sample applications that are described in Chapter 3 and Chapter 4. (See Oracle Multimedia Reference for more examples.)

When handling exceptions, PL/SQL uses exception blocks. For example, in PL/SQL, the exception can appear as:

BEGIN
<some program logic>
EXCEPTION
     WHEN OTHERS THEN
     <some exception logic>
END;

When you design, code, and debug your application, you are aware of the places in your program where processing might stop due to a failure to anticipate an error. Those are the places in your program where you must add exception handling blocks to handle the potential errors.

The examples in this section describe exception handling in the Oracle Multimedia PL/SQL Web Toolkit Photo Album sample application.

The following subsections provide additional details and examples of exception handling in PL/SQL:


See Also:

Oracle Database PL/SQL Language Reference for more information about handling PL/SQL exceptions


2.2.5.1 Handling the Setting of Properties for Unknown Image Formats in PL/SQL

If your program tries to set the properties of an uploaded image (it reads the image data to get the values of the object attributes so it can store them in the appropriate attribute fields) and the image format is not recognized, then the setProperties( ) method fails. To catch this exception and work around this potential problem, the application uses the following exception block:

BEGIN
   new_image.setProperties();
EXCEPTION
   WHEN OTHERS THEN
         new_image.contentLength := upload_size;
         new_image.mimeType := upload_mime_type;
END;

In this example, this exception handler sets the MIME type and length of the image based on the values from the upload table described at the beginning of the insert_new_photo procedure. The browser sets a MIME type header when the file is uploaded. The application reads this header to set the ORDImage field.

2.2.5.2 Handling Image Processing for Unknown Image Formats in PL/SQL

If your program tries to process an image in cases when the image format is unknown, the processCopy( ) method always fails. To work around this potential problem, the application uses the following exception block:

BEGIN
   new_image.processCopy( 'maxScale=50,50', new_thumb);
EXCEPTION
   WHEN OTHERS THEN
      new_thumb.deleteContent();
      new_thumb.contentLength := 0;
END;

In this example from the Oracle Multimedia PL/SQL Web Toolkit Photo Album application, when the image format is unknown and a thumbnail image cannot be created, this exception handler deletes the content of the thumbnail image and sets its length to zero.

2.3 Developing PL/SQL Web Applications

SQL developers who are familiar with the database can develop Web applications that exclusively use Oracle Fusion Middleware and Oracle Database using the PL/SQL development environment. With the PL/SQL development environment, developers can come quickly up to speed to develop PL/SQL-based Web applications.

Developing Web applications using PL/SQL consists of developing one or more PL/SQL packages consisting of sets of stored procedures that interact with Web browsers through HTTP. Stored procedures can be executed in several ways:

Information in the stored procedure, such as tagged HTML text, is displayed in the Web browser as a Web page. These dynamic Web pages are generated by the database and are based on the database contents and the input parameters passed in to the stored procedure. Using PL/SQL stored procedures is especially efficient and powerful for generating dynamic Web page content.

There are two ways of generating HTML output from PL/SQL:

Use Oracle Multimedia when media data such as images, audio, video, or combinations of all three are to be uploaded into and retrieved from database tables using the Oracle Multimedia object types and their respective sets of methods.

Media upload procedures first perform a SQL INSERT operation to insert a row of data in the media table, which also initializes instances of the respective Oracle Multimedia object columns with an empty BLOB. Next, a SQL SELECT FOR UPDATE operation selects the object columns for update. Finally, a SQL UPDATE operation updates the media objects in their respective columns. Oracle Multimedia methods are called to perform these tasks:

Media retrieval operations involve these tasks:

Oracle Multimedia methods are called to get the time that the media object was last updated, to determine if the media is stored locally in the database, in a BFILE, or at a URL location, to get the MIME type of the media object, and finally to retrieve the media data.

The following subsection describes how to use some Web components of the PL/SQL development environment:

2.3.1 Using the PL/SQL Gateway and PL/SQL Web Toolkit

Oracle Fusion Middleware and Oracle Database install Oracle HTTP Server powered by the Apache HTTP server that contains the PL/SQL Gateway to communicate directly with a client Web browser.

Oracle HTTP Server serves mainly the static HTML files, images, and so on, that a Web application uses, and is usually located in the file system where Oracle HTTP Server is installed. Oracle HTTP Server contains modules or plug-ins that extend its functions. One of these modules supplied by Oracle is the mod_plsql module, also known as the PL/SQL Gateway. The PL/SQL Gateway serves data dynamically from the database to Web browsers by calling PL/SQL stored procedures. The PL/SQL Gateway receives requests from a Web browser in the form of PL/SQL servlets or PL/SQL server pages that are mapped to PL/SQL stored procedure calls. PL/SQL stored procedures retrieve data from the database and generate an HTTP response containing the data and code from the PL/SQL Web Toolkit to display the generated Web page in a Web browser. The PL/SQL Web Toolkit contains a set of packages called htp, htf, and owa packages that can be used in the stored procedures to get information about the request, construct HTML tags, and return header information to the client Web browser.

Figure 2-1 shows these main components of the PL/SQL development environment, Oracle HTTP Server (a component of Oracle Fusion Middleware and Oracle Database), the Web browser, and the database. The following information describes how a client Web browser request is turned into a Web page response from the execution of the PL/SQL procedure:

  1. A client Web browser sends a PL/SQL server page or servlet request to Oracle HTTP Server.

  2. Oracle HTTP Server routes the request to the PL/SQL Gateway (mod_plsql).

  3. The PL/SQL Gateway forwards the request to the database using configuration information stored in the database access descriptor (DAD) and connects to the database.

  4. The PL/SQL Gateway prepares the call parameters and invokes the PL/SQL package and the PL/SQL stored procedure in the application.

  5. The PL/SQL procedure generates an HTML page using data from the database and special packages in the PL/SQL Web Toolkit accessed from the database. The PL/SQL Web Toolkit contains a set of packages called htp, htf, and owa packages that are used in the stored procedures to get information about the request, construct HTML tags, and return header information back to the client Web browser as the response returned to the PL/SQL Gateway.

  6. The PL/SQL Gateway sends the response to Oracle HTTP Server.

  7. Oracle HTTP Server sends the response to the client Web browser for display as a formatted Web page.

Figure 2-1 Components of the PL/SQL Development Environment

Description of Figure 2-1 follows
Description of "Figure 2-1 Components of the PL/SQL Development Environment"

Usually, the returned formatted Web page has one or more additional links, and each link, when selected, sends another request to the database through the PL/SQL Gateway to execute one or more stored procedures. The generated response displays data on the client Web page usually with additional links, which, when selected, execute more stored procedures that return the generated response for display as yet another formatted Web page, and so on. This is how the PL/SQL application in the PL/SQL development environment is designed to work.

Web application developers who use the PL/SQL development environment, create a PL/SQL package specification and body that describe procedures and functions that comprise the application. The package specification defines the procedures and functions used by the application, and the package body is the implementation of each procedure and function. All packages are compiled and stored in the database to perform specific operations for accessing data in the database and formatting HTML output for Web page presentation. To invoke these stored PL/SQL procedures, Web application developers use the request/response PL/SQL servlets and PL/SQL server pages (PSP) to enable Web browser clients to send requests and get back responses using HTTP.

Oracle HTTP Server maps a URL entered in a browser to a specific PL/SQL procedure stored in the database. It does this by storing specific configuration information in a DAD for each stored procedure. Thus, each DAD contains the database connection information that the Web server requires to translate the URL entered into a database connection to call the stored procedure.

Oracle HTTP Server listens for a request, routes the request to the PL/SQL Gateway, which forwards it to the database. Configuration information values stored in a DAD determine the database alias to use, the connection string to use for remote access, the procedure to use for uploading or downloading documents, and the user name and password information to enable access to the database. From the Web browser, the user specifies the URL that invokes the PL/SQL Gateway. The URL has a defined format for specifying all the required and optional parameters, including the location of the DAD and the name of the PL/SQL stored procedure to run, as shown in Example 2-4.

Example 2-4 URL Format to Invoke mod_plsql in a Web Browser

protocol://hostname[:port number]/DAD-name/[[!][schema name.]
 [package name.]procedure_name[?query_string]]

See Also:

Oracle Fusion Middleware User's Guide for mod_plsql in the Oracle Fusion Middleware Online Documentation Library for a detailed description of each parameter and the available options


To use the Oracle Multimedia Photo Album sample application and the PL/SQL Web Toolkit described in Section 3.1, the URL can be simplified to the format shown in Example 2-5.

Example 2-5 URL Format to Invoke mod_plsql for the Photo Album Application

protocol://<hostname>[:<port-number>]/DAD-name/]procedure_name

When the URL is entered in the Web browser, it includes the protocol (HTTP or HTTPS), the name of the hosting Web server, and the port number to which it is listening to handle requests. Next, the specified virtual path includes /pls/<DAD-name> to indicate that the Web server is configured to invoke mod_plsql, and the location of the DAD on the Web server.

In Example 2-4, the last five parameters include the exclamation point (!) character, schema name, package name, procedure name, and query string. From the syntax, the exclamation point, schema name, package name, and query string parameters are optional; only the procedure name is required.

The exclamation point indicates that flexible parameter passing is being used. The schema name, if omitted, is resolved based on the user name. The package name, if omitted, means the procedure is standalone. The query string parameters are for the stored procedure and follow a special format. Of these five parameters, the procedure name must be specified in both the DAD and the URL. The other four parameters are specified in either the DAD or the URL, or not at all, depending on the application.

The URL displays the home page for the specified DAD. When the URL is entered in the address field of the Web browser page, it invokes either the specified DAD location only, or the specified DAD location along with the procedure name, or the specified DAD location along with the schema.package.procedure name. The response is returned as an HTML page. The HTML page contains the requested data and any other specified code for display in the client's Web browser. The Code Wizard described in Chapter 4 demonstrates how this operation works. For example, to invoke the Code Wizard administration URL, enter the following URL shown in that chapter:

http://<hostname>:<port-number>/pls/ordcwadmin

The virtual path includes pls to indicate that the Web server is configured to invoke mod_plsql, followed by the name of the DAD used for the Code Wizard administrator, ordcwadmin.

When the HTML page is displayed, it resolves to the following URL for the Code Wizard administrator:

http://<hostname>:<port-number>/pls/ordcwadmin/ORDCWPKG.menu

ORDCWPKG.menu represents the package.procedure name, which is specified as the default home page in the ordcwadmin DAD.

When the PL/SQL Gateway is invoked, it uses the stateless model and does not permit a transaction to span across multiple HTTP requests. In this stateless model, applications typically can create a session to maintain state by using one of these techniques: HTTP cookies, a hidden HTML field as an HTML form element of the HTML Form package, or storage of vital information in database tables for query.


See Also:

Oracle Database Advanced Application Developer's Guide for more information about PL/SQL Web applications


2.4 Developing Java Client Applications Using JDBC

Developers who are familiar with Java and Java database connectivity (JDBC) can write media-rich Java applications using Oracle Multimedia Java API. The classes in Oracle Multimedia Java API are the Java proxy classes for Oracle Multimedia database objects. These Java classes provide access to Oracle Multimedia database objects through JDBC in a Java application.

The Java classes in Oracle Multimedia Java API are included in the oracle.ord.im.* package. These Java classes are named similarly to the Oracle Multimedia database objects, and in compliance with the standard Java naming convention:

Developers who write medical imaging applications can use Oracle Multimedia DICOM Java API and Oracle Multimedia Mid-Tier Java API. In Oracle Multimedia DICOM Java API, the OrdDicom class provides access to Oracle Multimedia DICOM database objects in a Java application. The classes in Oracle Multimedia Mid-Tier Java API enable developers to write Java applications for extracting DICOM metadata outside of Oracle Database.

The examples in this section use the sample schemas, which may be installed when you install Oracle.

The following subsections describe how to use various components of the Java development environment with JDBC:


See Also:


2.4.1 Setting Up Your Environment for Java

Before you can begin using any of the Java APIs provided by Oracle Multimedia, you must set up your environment to compile and run Java programs.

Follow these steps:

  1. Specify the environment variable CLASSPATH, and ensure that this variable includes the appropriate Oracle Java archive (JAR) files for the Oracle Multimedia features and any other features that you intend to use.

    For each Oracle JAR file, Table 2-1 lists the name of the file and its contents, the Oracle Multimedia and other features that require it, and details about the JDK version, the platform, and the path name under the <ORACLE_HOME> directory where you can obtain it.

    Table 2-1 Java Archive Files for Oracle Multimedia

    K~
    Oracle JAR File and ContentsRequired ByJDK Version, Platform, and Location

    Name: ordim.jar

    Description:

    Oracle Multimedia Java proxy classes

    All Oracle Multimedia features

    JDK 5 or later, on Linux and UNIX:

    <ORACLE_HOME>/ord/jlib/ordim.jar

    JDK 5 or later, on Windows:

    <ORACLE_HOME>\ord\jlib\ordim.jar

    Name: ojdbc5.jar

    Description:

    Oracle JDBC library

    All Oracle Multimedia features

    JDK 5 or later, on Linux and UNIX:

    <ORACLE_HOME>/jdbc/lib/ojdbc5.jar

    JDK 5 or later, on Windows:

    <ORACLE_HOME>\jdbc\lib\ojdbc5.jar

    Name: xdb.jar

    Description:

    Oracle XDB Java classes library

    DICOM feature

    Oracle Multimedia metadata extraction

    JDK 5 or later, on Linux and UNIX:

    <ORACLE_HOME>/rdbms/jlib/xdb.jar

    JDK 5 or later, on Windows:

    <ORACLE_HOME>\rdbms\jlib\xdb.jar

    Name: xmlparserv2.jar

    Description:

    Oracle XML Parser library

    DICOM feature

    Oracle Multimedia metadata extraction

    Mid-Tier Java API feature

    JDK 5 or later, on Linux and UNIX:

    <ORACLE_HOME>/lib/xmlparserv2.jar

    JDK 5 or later, on Windows:

    <ORACLE_HOME>\lib\xmlparserv2.jar

    Name: orddcmmt.jar

    Description:

    Oracle Multimedia Mid-Tier Java classes

    Mid-Tier Java API feature

    JDK 5 or later, on Linux and UNIX:

    <ORACLE_HOME>/ord/jlib/orddcmmt.jar

    JDK 5 or later, on Windows:

    <ORACLE_HOME>\ord\jlib\orddcmmt.jar

    Name: ordimdcm.jar

    Description:

    Oracle Multimedia DICOM Java library

    Mid-Tier Java API feature

    JDK 5 or later, on Linux and UNIX:

    <ORACLE_HOME>/ord/jlib/ordimdcm.jar

    JDK 5 or later, on Windows:

    <ORACLE_HOME>\ord\jlib\ordimdcm.jar

    Name: orddicom.jar

    Description:

    Oracle Multimedia DICOM Java proxy classes

    DICOM feature

    JDK 5 or later, on Linux and UNIX:

    <ORACLE_HOME>/ord/jlib/orddicom.jar

    JDK 5 or later, on Windows:

    <ORACLE_HOME>\ord\jlib\orddicom.jar

    Name: ordhttp.jar

    Description:

    Oracle Multimedia Servlets and JSP Java HTTP classes

    Java servlets and JavaServer Pages (JSP) applications

    JDK 5 or later, on Linux and UNIX:

    <ORACLE_HOME>/ord/jlib/ordhttp.jar

    JDK 5 or later, on Windows:

    <ORACLE_HOME>\ord\jlib\ordhttp.jar

    Name: ordjsptag.jar

    Description:

    Oracle Multimedia JSP Tag Library

    (Optional)

    JavaServer Pages (JSP) applications

    JDK 5 or later, on Linux and UNIX:

    <ORACLE_HOME>/ord/jlib/ordjsptag.jar

    JDK 5 or later, on Windows:

    <ORACLE_HOME>\ord\jlib\ordjsptag.jar

    Name: orai18n.jar

    Description:

    NLS Character Set Conversion library

    (Optional)

    NLS character set conversion requiredFoot 1 

    JDK 5 or later, on Linux and UNIX:

    <ORACLE_HOME>/jlib/orai18n.jar

    JDK 5 or later, on Windows:

    <ORACLE_HOME>\jlib\orai18n.jar


    Footnote 1 If NLS character set conversion is required between the client application and the database, you must include the orai18n.jar file in the CLASSPATH variable. If NLS character set conversion is required, but the appropriate library is not specified, character-based attributes of Oracle Multimedia object types may be returned as hexadecimal-encoded strings. See Oracle Database JDBC Developer's Guide for more information about NLS character set conversion.


    Note:

    If you are using the JDBC OCI driver, specify the location of the JDBC OCI shared library in one of these variables:
    • LD_LIBRARY_PATH (for Linux or UNIX)

    • PATH (for Windows)

    Depending on your platform, store the JDBC OCI shared library at one of these locations under the <ORACLE_HOME> directory:


    <ORACLE_HOME>/lib (for libocijdbc11.so on Linux and UNIX)
    <ORACLE_HOME>\bin (for ocijdbc11.dll on Windows)

    Because this library path is shared, it may have been specified previously to enable the use of other client applications, such as SQL*Plus.


  2. Add one or more of the following import statements to the Java program:

    Along with the standard JDBC classes included in the java.sql package, you must also import the Oracle JDBC extension class oracle.jdbc.OracleResultSet, as follows:

    import oracle.jdbc.OracleResultSet;
    

    Based on the type of media to be handled in the Java application, you might also have to add one or more of following import statements:

    import oracle.ord.im.OrdAudio;
    import oracle.ord.im.OrdDoc;
    import oracle.ord.im.OrdImage;
    import oracle.ord.im.OrdVideo;
    

2.4.2 Media Retrieval in Java

Oracle Multimedia objects can be retrieved into Java applications as Java proxy objects to the Oracle Multimedia database objects with the same names: OrdAudio, OrdDoc, OrdImage, and OrdVideo. After the JDBC connection is established, follow these steps to retrieve Oracle Multimedia Java objects:

  1. Create the JDBC statement to select Oracle Multimedia objects from the database:

    String query = "select product_photo, product_audio,"+
      " product_video, product_testimonials from" +   
      " pm.online_media where product_id=3117";
    PreparedStatement pstmt = conn.prepareStatement(query);
    
  2. Execute the query and obtain the result set:

    OracleResultSet rset = (OracleResultSet)pstmt.executeQuery();
    
  3. Retrieve the Oracle Multimedia Java object from the result set:

    if ( rset.next() )
    {
    
      OrdImage imgProxy = (OrdImage)rset.getORAData(
              "product_photo", OrdImage.getORADataFactory());
      OrdAudio audProxy = (OrdAudio)rset.getORAData(
              "product_audio", OrdAudio.getORADataFactory());
      OrdVideo vidProxy = (OrdVideo)rset.getORAData(
              "product_video", OrdVideo.getORADataFactory());
      OrdDoc docProxy = (OrdDoc)rset.getORAData(
              "product_testimonials",
              OrdDoc.getORADataFactory());
    }
    

    Note:

    In Oracle Multimedia release 8i and release 9i, the getCustomDatum method is used to retrieve the Oracle Multimedia Java objects. In Oracle JDBC release 10g, the getCustomDatum method was deprecated and replaced by the getORAData method.

    In your Java program environment, be sure to use the same version for both the Oracle Multimedia Java Client library (ordim.jar) and the Oracle JDBC library.


  4. Retrieve the media attributes. Media attributes can be retrieved directly from Oracle Multimedia Java objects. For example:

    int height = imgProxy.getHeight();
    int width = imgProxy.getWidth();
    String audFormat = audProxy.getFormat();
    String vidMimetype = vidProxy.getMimeType();
    

2.4.3 Media Upload in Java

Follow these steps to upload media data into Oracle Multimedia database objects in a Java application:

  1. Enter this statement to enable the JDBC connection object to set the autocommit flag to false:

    conn.setAutoCommit(false);
    
  2. Retrieve Oracle Multimedia Java objects from the database for updating. You can load media data into existing Oracle Multimedia objects in a table or into nonexisting Oracle Multimedia objects by creating a new row in a table.

    The following example includes a query you can use to load media data into existing Oracle Multimedia objects in a table.

    //"for update" is required in the query string 
    //since we will update the row later.
    String query1 = "select product_photo," +
    " product_audio, product_video," +         
    " product_testimonials from" + 
    " pm.online_media where product_id=3106" +
    " for update";
     
    PreparedStatement pstmt = conn.prepareStatement(query1);
     
    OracleResultSet rset = (OracleResultSet)pstmt.executeQuery();
    
    if ( rset.next() )
    {
     
      OrdImage imgProxy = (OrdImage)rset.getORAData(
              "product_photo", OrdImage.getORADataFactory());
      OrdAudio audProxy = (OrdAudio)rset.getORAData( 
              "product_audio", OrdAudio.getORADataFactory());
      OrdVideo vidProxy = (OrdVideo)rset.getORAData( 
              "product_video", OrdVideo.getORADataFactory());
      OrdDoc docProxy = (OrdDoc)rset.getORAData( 
              "product_testimonials",
              OrdDoc.getORADataFactory());
    }
     
    rset.close();
    pstmt.close();
    

    The following example includes a query you can use to load media data into nonexisting Oracle Multimedia objects by creating a new row.


    Note:

    This code segment assumes that there is no row with product_id=3106 in the pm.online_media table.

    String query2 = 
      "begin insert into pm.online_media " +
      " (product_id, product_photo, product_audio," +
      " product_video, product_testimonials) values" +
      " (3106, ordimage.init()," +
      " ordaudio.init(), ordvideo.init()," +
      " orddoc.init()) returning product_photo," +    
      " product_audio, product_video," +   
      " product_testimonials into ?, ?, ?, ?;end;";
     
    OracleCallableStatement cstmt =
     (OracleCallableStatement) conn.prepareCall(query2);
    cstmt.registerOutParameter(1, OrdImage._SQL_TYPECODE,
                                   OrdImage._SQL_NAME);
    cstmt.registerOutParameter(2, OrdAudio._SQL_TYPECODE,
                                   OrdAudio._SQL_NAME);
    cstmt.registerOutParameter(3, OrdVideo._SQL_TYPECODE,
                                   OrdVideo._SQL_NAME);
    cstmt.registerOutParameter(4, OrdDoc._SQL_TYPECODE,
                                   OrdDoc._SQL_NAME);
     
    cstmt.execute();
     
    OrdImage imgProxy = (OrdImage)cstmt.getORAData(1,
                         OrdImage.getORADataFactory());
    OrdAudio audProxy = (OrdAudio)cstmt.getORAData(2, 
                         OrdAudio.getORADataFactory());
    OrdVideo vidProxy = (OrdVideo)cstmt.getORAData(3, 
                         OrdVideo.getORADataFactory());
    OrdDoc docProxy = (OrdDoc)cstmt.getORAData(4, 
                         OrdDoc.getORADataFactory());
     
    cstmt.close();
    
  3. Load the media data from a file to the Oracle Multimedia Java objects by calling the loadDataFromFile method:

    String imageFileName = "laptop.jpg";
    String audioFileName = "laptop.mpa";
    String videoFileName = "laptop.rm";
    String docFileName = "laptop.jpg";
    imgProxy.loadDataFromFile(imageFileName);
    audProxy.loadDataFromFile(audioFileName);
    vidProxy.loadDataFromFile(videoFileName);
    docProxy.loadDataFromFile(docFileName);
    
  4. Set the properties of the Oracle Multimedia objects by populating the Java object fields with media attributes (optional):

    imgProxy.setProperties();
    audProxy.setProperties(new byte[1][64]);
    vidProxy.setProperties(new byte[1][64]);
    docProxy.setProperties(new byte[1][64], true);
    

    Note:

    The setProperties method tries to recognize the format of the media and populate the objects field with media information such as image height, image width, format, MIME type, and so on. If the media format is not recognized, the java.sql.SQLException error is thrown.

  5. Update the database table with Oracle Multimedia Java objects that have data already loaded:

       String query3 = "update pm.online_media set" +
        " product_photo=?, product_audio=?," + 
        " product_video=?, product_testimonials=?" +
        " where product_id=3106";
        OraclePreparedStatement pstmt = 
     (OraclePreparedStatement)conn.prepareStatement(query3);
        pstmt.setORAData(1, imgProxy);
        pstmt.setORAData(2, audProxy);
        pstmt.setORAData(3, vidProxy);
        pstmt.setORAData(4, docProxy);
     
        pstmt.execute();
        pstmt.close();
    
  6. Commit the transaction:

    conn.commit();
    

2.4.4 Handling Oracle Multimedia Exceptions in Java

Possible errors that can occur during run time should always be handled in your application. This practice enables the program to continue its operation even when it encounters a run-time error. This practice also enables users to know what went wrong during program operation. Proper error handling practices ensure that, whenever possible, you are always able to recover from an error while running an application. In addition, proper error handling provides you with the information you need so you always know what went wrong.

This section demonstrates proper error handling practices using code examples. These examples show how to handle some common Oracle Multimedia errors and other types of errors in Java programs. These examples are extracted from the Java sample applications that are described in Chapter 3 and Chapter 5. (See Oracle Multimedia Reference for more examples.)

When handling exceptions, Java uses the try/catch block. For example, in Java, the exception can appear as:

try {
    //<some program logic>)
}
catch (exceptionName a) {
//Exception logic
}
finally {
//Execute logic if try block is executed even if an exception is caught
}

When you design, code, and debug your application, you are aware of the places in your program where processing might stop due to a failure to anticipate an error. Those are the places in your program where you must add exception handling blocks to handle the potential errors.

The examples in this section describe exception handling using the try/catch block. These examples are included in the Oracle Multimedia Java API sample application, the Oracle Multimedia Java Servlet Photo Album application, and the Oracle Multimedia JavaServer Pages Photo Album application.

The following subsections provide additional details and examples of exception handling in Java:


See Also:

  • Oracle Database Java Developer's Guide for more information about handling Java exceptions

  • Oracle Database JDBC Developer's Guide for more information about handling Java exceptions using JDBC


2.4.4.1 Handling the Setting of Properties for Unknown Image Formats in Java

The IMUtil class of the Oracle Multimedia Java API sample application contains utility methods for common image functions. One of these methods is the setProperties( ) method. The static method takes an OrdImage object as an input parameter and calls the setProperties( ) method on the object.

static boolean setProperties(OrdImage img)
  {
    try
    {
      img.setProperties();
      return true;
    }
    catch (SQLException e)
    {
      return false;
    }
  }

If an exception is thrown, the setProperties( ) method returns false to indicate failure; otherwise it returns true. See Chapter 5 for a full description of the Oracle Multimedia Java API sample application, and for more information about using the setProperties( ) method in a Java application.

2.4.4.2 Handling Image Processing for Unknown Image Formats in Java

In the insertNewPhoto( ) method in both the PhotoAlbumServlet class of the Oracle Multimedia Java Servlet Photo Album application and in the PhotoAlbumBean class of the Oracle Multimedia JavaServer Pages Photo Album application, a new photograph is inserted into the photo album, creating a thumbnail image at the same time. If the application tries to process an image in cases when the image format is unknown, then when the application calls the processCopy( ) method, the application always fails. To work around this potential problem, the application uses the following try block and catch block to catch any SQL exceptions:

        try
        {
            image.processCopy( "maxScale=50,50", thumb );
        }
        catch ( SQLException e )
        {
            thumb.deleteContent();
            thumb.setContentLength( 0 );
        }

In this example, when the image format is unknown and a thumbnail image cannot be created, the application catches the SQL exception and calls the deleteContent( ) method to delete the content of the thumbnail image, and then calls the setContentLength( ) method to set its length to zero.

2.5 Developing Java-Based Web Applications

On the Java platform, a Web application is a dynamic extension of a Web server. A Java-based Web application is composed of Java servlets, JSP pages, or both. Java servlets are Java classes that dynamically process HTTP requests and construct HTTP responses. JSP pages are text-based documents that execute as servlets, but enable a more natural approach to creating static content.

Oracle Multimedia Servlets and JSP Java API is based on Oracle Multimedia Java API. The classes in Oracle Multimedia Servlets and JSP Java API facilitate the retrieval and uploading of media data from and to Oracle Database in a Java-based Web application.

The Java classes in Oracle Multimedia Servlets and JSP Java API are included in the oracle.ord.im.* package. The classes are as follows:

The OrdHttpResponseHandler class facilitates the retrieval of the media data from Oracle Database and its delivery to an HTTP client from a Java servlet. The OrdHttpJspResponseHandler class provides the same features for JSP pages. The OrdHttpUploadFormData, OrdHttpUploadFile, OrdMultipartFilter, and OrdMultipartWrapper classes facilitate the uploading of media data from a Web client to Oracle Database.

Before you can begin using Oracle Multimedia Servlets and JSP Java API, you must set up your environment with the appropriate Java libraries, as described in Step 1, Section 2.4.1.

The following subsections describe how to use various components of the Java development environment for Web applications:


See Also:

Oracle Multimedia Servlets and JSP Java API Reference for details about the available classes and methods in this Java API


2.5.1 Media Retrieval in Java-Based Web Applications

In general, displaying a Web page that contains images in a Web browser requires two HTTP round trips.

In the first trip, the Web browser makes an HTTP request to the URL of the Web page that contains the images. The Web server responds with the Web page text content and the URLs for the media content. The URL is the src attribute of the <img> tag in the Web page.

In the second trip, the Web browser makes another HTTP request to the URL in the <img> tag to get the image binary data, and then displays the image in the browser.

In a Java-based Web application, sending media data from the database to an HTTP client (Web browser) requires the proper media URL (generated in the first HTTP response); and the proper media delivery component (a servlet or JSP for the second HTTP response).

The following subsections provide additional details and examples of this process:

2.5.1.1 Media URL

When media data is stored as static files on the Web server, the media URL is the relative or absolute path to the media files on the file system. When media data is stored in a database, the media URL is generally composed of a media delivery component (a servlet or JSP) and the parameters for the media delivery component. The media delivery component is the target for the second HTTP request to retrieve the media data. The parameters for the media delivery component are used by the media delivery component to query and locate the media data in the database. For example:

<img src="OrdGetMedia.jsp?id=1"/>

where OrdGetMedia.jsp in the media URL "OrdGetMedia.jsp?id=1" is the media delivery component, and id=1 is the parameter to the media delivery component.

2.5.1.2 Media Delivery Component

Because media data is stored in the database as Oracle Multimedia objects, the media delivery component must dynamically retrieve the media data as Java objects (see Section 2.4.2), based on certain query conditions. Then, you can use either the OrdHttpResponseHandler or the OrdHttpJspResponsehandler class in Oracle Multimedia Servlets and JSP Java API to deliver the data to the HTTP client (Web browser).

The following example demonstrates the use of a Java servlet as the media delivery component, and highlights in bold the SQL statements and significant areas in the code where this operation takes place.

import oracle.ord.im.OrdHttpResponseHandler;
 
protected void doGet(HttpServletRequest request,
 HttpServletResponse response)
  throws ServletException, java.io.IOException
{
// obtain oracle.ord.im.OrdImage object 
// imgProxy follows the Section "Media Retrieval in Java"
 . . . 
 
// deliver the image data to the browser
OrdHttpResponseHandler handler = 
new OrdHttpResponseHandler( request, response);
handler.sendImage(imgProxy);
 
 . . . 
 }

The following example demonstrates the use of a JSP page as the media delivery component, and highlights in bold the SQL statements and significant areas in the code where this operation takes place.

<%@ page 
import="oracle.ord.im.OrdHttpJspResponseHandler" 
%>
 
<jsp:useBean id = "handler" scope="page"
     class = "oracle.ord.im.OrdHttpJspResponseHandler" 
/>
 
<%
// obtain oracle.ord.im.OrdImage object 
// imgProxy follows the Section "Media Retrieval in Java"
. . . 
 
// deliver the image data to the browser
   handler.setPageContext( pageContext );
   handler.sendImage(imgProxy);
   return;
%>

2.5.2 Media Upload in Java-Based Web Applications

The HTML form enables you to input and upload data from a Web browser to a Web server for processing. The following HTML code segment is an example of the HTML form that uploads a file. This code example highlights in bold the SQL statements and areas in the code where this operation takes place.

<form action="uploadAction.jsp" method="post" 
enctype="multipart/form-data">
id: <input type="text" name="id"/>
description: <input type="text" name="description"/>
Photo: <input type="file" name="photo"/>
</form>

Referring to the preceding code example, setting the value of the enctype attribute in the <form> tag to "multipart/form-data" specifies multipart/form-data format encoding of the uploaded data. The value of the action attribute in the <form> tag represents the name of the JSP that handles the uploaded data.

To handle the uploaded data in a JSP or servlet, follow these steps:

  1. Decode the uploaded file. Because this file is encoded in multipart/form-data format, the data must be decoded before further processing can proceed. You can use the OrdHttpUploadFormData class to decode the encoded HTTP request data and obtain the uploaded file as an instance of the OrdHttpUploadFile object. You can use this class explicitly or implicitly to get the decoded uploaded file.

    The following example demonstrates how to use the OrdHttpUploadFormData class explicitly to get the uploaded file, and highlights in bold the SQL statements and significant areas in the code where this operation takes place. Use this method within the servlet or JSP that handles the upload HTTP request.

    //
    // Import OrdHttpUploadFormData and OrdHttpUploadFile class:
    // In a servlet:
    // import oracle.ord.im.OrdHttpUploadFormData;
    // import oracle.ord.im.OrdHttpUploadFile;
    // In a JSP:
    // <%@ page import="oracle.ord.im.OrdHttpUploadFormData" %>
    // <%@ page import="oracle.ord.im.OrdHttpUploadFile" %>
    //
     
    //
    // Following code snippets should be within <% %> if in a JSP.
    //
     
    // Create an OrdHttpUploadFormData object and use it to parse 
    // the multipart/form-data message.
    //
    OrdHttpUploadFormData formData = new OrdHttpUploadFormData(
     request );
    formData.parseFormData();
     
    //
    // Get the description, location, and photo.
    //
    String id = formData.getParameter( "id" );
    String description = formData.getParameter( "description" );
    OrdHttpUploadFile photo = formData.getFileParameter( "photo" );
     
    //
    // Process the uploaded file.
    //
     ...
     
    //
    // Release the resources.
    //
    formData.release();
    

    To avoid instantiating and releasing the OrdHttpUploadFormData class explicitly in each JSP or servlet that handles the uploaded data, you can use the OrdHttpUploadFormData class implicitly by configuring the Web application with the OrdMultipartFilter class. Using the OrdMultipartFilter class ensures that any HTTP request that is encoded in multipart/form-data format is decoded and passed along to the JSP or servlet that further processes the request.

    The following substeps and accompanying examples describe how to use the OrdHttpUploadFormData class implicitly to get the uploaded file. These code examples highlight in bold the SQL statements and significant areas in the code where this operation takes place.

    1. Configure the filter by adding this code to the web.xml file in your Web application:

      <filter>
          <filter-name>OrdMultipartFilter</filter-name>
          <filter-class>
      oracle.ord.im.OrdMultipartFilter
          </filter-class>
      </filter>
      <filter-mapping>
          <filter-name>OrdMultipartFilter</filter-name>
          <servlet-name>*.jsp</servlet-name>
      </filter-mapping>
      
    2. Obtain the form data and the uploaded file in the JSP or servlet after the filter is configured:

      //
      // Get the id, description, and photo.
      //
      String id = request.getParameter( "id" );
      String description = request.getParameter( "description" );
       oracle.ord.im.OrdHttpUploadFile photoFile = 
        request.getFileParameter("photo");
      

      where request is the HttpServletRequest object passed to the JSP or servlet.

  2. Save the uploaded file to the database. After the OrdHttpUploadFile object is obtained by explicitly or implicitly using the OrdHttpUploadFormData class, the uploaded file is ready to be loaded into an Oracle Multimedia object in the database, using this statement:

    photoFile.loadImage(imgProxy);
    

    where photoFile is the OrdHttpUploadFile object andimgProxy is an OrdImage object obtained in Step 1 in Section 2.4.3.

    The loadImage method implicitly calls the setProperties method to populate the object fields.

    After the data is loaded into the Oracle Multimedia Java object, you can update the corresponding Oracle Multimedia object in the database table by following Steps 4 and 5 in Section 2.4.3.

PKwpiZ~K~PK"+AOEBPS/im_glossary.htm+ Glossary

Glossary

audio data

Media data produced by an audio recorder, an audio source, or by program algorithms. Audio recording devices take analog or continuous signals and convert them into digital values with specific audio characteristics.

codecs

Digital compression and decompression schemes.

content metadata

Data that describes the content of image media, such as the name of the photographer, and the date and time when a photograph was taken.

DICOM content

Standalone DICOM Information Objects that are encoded according to the data structure and encoding definitions of PS 3.10-2007 of the DICOM standard (commonly referred to as DICOM Part 10 files). For more information about DICOM Information Objects, see the DICOM standard, which is available worldwide from the NEMA Web site at

http://medical.nema.org/

DICOM data

See DICOM content.

embedded metadata

Metadata that is stored with image data in the image file format.

heterogeneous media data

Assorted media data, such as audio data, image data, video data, and other types of media data. The data can have a variety of formats, depending upon the application that generated it.

image data

Media data produced by a document or photograph scanner, a video source, other specialized image capture devices, or by program algorithms. Image capture devices take analog or continuous signals and convert them into digital values on a two-dimensional grid of data points known as pixels. Devices involved in the capture and display of images are under application control.

image interchange format

A well-defined organization and use of image attributes, data, and often compression schemes that enables different applications to create, exchange, and use images. Interchange formats are often stored as disk files.

image metadata format

Standard protocols and techniques used to store image metadata within an image file. Formats include: EXIF, IPTC-IIM, and XMP.

Java servlets

Java classes that dynamically process HTTP requests and construct HTTP responses.

JavaServer Pages (JSP)

See JSP.

JSP

JavaServer Pages, Java text-based documents that execute as Java servlets, but which permit a more natural approach to creating static content than using servlets.

lossless compression schemes

Compression schemes that squeeze an image so that when it is decompressed, the resulting image is bit-for-bit identical with the original.

lossy compression schemes

Compression schemes that do not result in an identical image when decompressed, but rather, one in which the changes may be imperceptible to the human eye. Lossy schemes generally provide higher compression than lossless compression schemes.

media data

Data from audio, image, DICOM format medical images and other objects, video, or other heterogeneous media.

metadata

Information about media data, such as object length, compression type, or format.

methods

Procedures that can be performed on objects, such as getContent( ) or setProperties( ).

Oracle interMedia

In Oracle Database 11g Release 1 (11.1), the name Oracle interMedia was changed to Oracle Multimedia.

ORDAudio

Object relational type for audio data characteristics.

ORDDicom

Object relational type for characteristics of DICOM content produced by medical devices. See Oracle Multimedia DICOM Developer's Guide for more information about this object type.

ORDDoc

Object relational type for heterogeneous data characteristics.

ORDImage

Object relational type for image data characteristics.

ORDSource

Object relational type that stores data source information for audio, heterogeneous, image, and video data characteristics.

ORDVideo

Object relational type for video data characteristics.

portlets

Summarized versions of applications and Web content situated in defined regions of a Web page that are accessible through enterprise portals.

protocols

Image interchange formats exchanged in a sequential fashion over a network.

technical metadata

Data that describes image media in a technical sense, such as the height and width of an image, in pixels, or the type of compression used to store the image.

video data

Media data produced by a video recorder, a video camera, digitized animation video, other specialized video recording devices, or by program algorithms. Some video recording devices take analog or continuous signals and convert them into digital values with specific video characteristics.

PKlo$++PK"+AOEBPS/title.htmY Oracle Multimedia User's Guide, 11g Release 2 (11.2)

Oracle® Multimedia

User's Guide

11g Release 2 (11.2)

E10777-03

August 2010

Oracle Multimedia enables Oracle Database to store, manage, and retrieve images, audio, video, DICOM format medical images and other objects, or other heterogeneous media data in an integrated fashion with other enterprise information. Oracle Multimedia extends Oracle Database reliability, availability, and data management to multimedia content in traditional, Internet, electronic commerce, medical, financial, and other media-rich applications.


Oracle Multimedia User's Guide, 11g Release 2 (11.2)

E10777-03

Copyright © 1999, 2010, Oracle and/or its affiliates. All rights reserved.

Primary Author: Sue Pelski

Contributors: Robert Abbott, Melliyal Annamalai, Fengting Chen, Dongbai Guo, Dong Lin, Susan Mavris, Valarie Moore, David Noblet, James Steiner, Yingmei Sun, Manjari Yalavarthy, Jie Zhang

This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.

The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.

If this software or related documentation is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, the following notice is applicable:

U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are "commercial computer software" or "commercial technical data" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, the use, duplication, disclosure, modification, and adaptation shall be subject to the restrictions and license terms set forth in the applicable Government contract, and, to the extent applicable by the terms of the Government contract, the additional rights set forth in FAR 52.227-19, Commercial Computer Software License (December 2007). Oracle USA, Inc., 500 Oracle Parkway, Redwood City, CA 94065.

This software is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications which may create a risk of personal injury. If you use this software in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure the safe use of this software. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software in dangerous applications.

Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.

This software and documentation may provide access to or information on content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services.

PKPK"+A OEBPS/loe.htmE List of Examples

List of Examples

PK`PK"+AOEBPS/ch_metadata.htmZ# Working with Metadata in Oracle Multimedia Images

6 Working with Metadata in Oracle Multimedia Images

Image files can contain information about the content of the images, the image rasters, and image metadata. In general, data about data is referred to as metadata. In this case, metadata refers to additional information about the actual images, which is stored in the image files along with the images.

This chapter includes these sections:

6.1 Metadata Concepts

Several types of metadata can be stored in an image file, and each type can serve a different purpose. One type, technical metadata, is used to describe an image in a technical sense. For example, technical metadata can include attributes about an image, such as its height and width, in pixels, or the type of compression used to store it. Another type, content metadata, can further describe the content of an image, the name of the photographer, and the date and time when a photograph was taken.

Metadata is stored in image files using a variety of mechanisms. Digital cameras and scanners automatically insert metadata into the images they create. Digital photograph processing applications like Adobe Photoshop enable users to add or edit metadata to be stored with the image. Annotating digital images with additional metadata is a common practice in photographic and news gathering applications, for image archiving usages, and at the consumer level.

Storing metadata with image data in the same containing file provides encapsulation. With encapsulation, both types of data can be shared and exchanged reliably as one unit. Metadata that is stored in the image file format is referred to as embedded metadata.

6.2 Oracle Multimedia Image Metadata Concepts

For a large number of image file formats, Oracle Multimedia can extract and manage a limited set of metadata attributes. These attributes include: height, width, contentLength, fileFormat, contentFormat, compressionFormat, and mimeType. For a limited number of image file formats, Oracle Multimedia can extract a rich set of metadata attributes. This metadata is represented in schema-based XML documents. These XML documents can be stored in a database, indexed, searched, updated, and made available to applications using the standard mechanisms of Oracle Database.

Oracle Multimedia can also write or embed metadata supplied by users into a limited number of image file formats. The application provides the metadata as a schema-based XML document. Oracle Multimedia processes the XML document and writes the metadata into the image file.

6.3 Image File Formats

Oracle Multimedia supports metadata extraction and metadata embedding for the GIF, TIFF, and JPEG file formats.


See Also:

Oracle Multimedia Reference for information about the image file formats supported by Oracle Multimedia


6.4 Image Metadata Formats

The term image metadata format refers to the standard protocols and techniques used to store image metadata within an image file. The following subsections describe the embedded image metadata formats supported by Oracle Multimedia:

6.4.1 EXIF

The Exchangeable Image File Format (EXIF) is the standard for image file storage for digital still cameras. It was developed by the Japan Electronic Industry Development Association (JEIDA) as a standard way of storing images created by digital cameras and metadata about the images. EXIF image metadata can be stored in TIFF and JPEG format images. Oracle Multimedia supports the extraction of EXIF metadata from TIFF and JPEG file formats.

6.4.2 IPTC–IIM

The International Press Telecommunications Council-Information Interchange Model (IPTC-IIM) Version 4 is a standard developed jointly by the International Press Telecommunications Council and the Newspaper Association of America. This metadata standard is designed to capture information that is important to the activities of news gathering, reporting, and publishing. These information records are commonly referred to as IPTC tags.

The use of embedded IPTC tags in image file formats became widespread with the use of the Adobe Photoshop tool for image editing. IPTC metadata can be stored in TIFF and JPEG format images. Oracle Multimedia supports the extraction of IPTC metadata from TIFF and JPEG file formats.

6.4.3 XMP

The Extensible Metadata Platform (XMP) is a standard metadata format, developed by Adobe, for the creation, processing, and interchange of metadata in a variety of applications. XMP uses Resource Description Framework (RDF) technology for data modeling. XMP also defines how the data model is serialized (converted to a byte stream), and embedded within an image file. Oracle Multimedia supports the extraction of XMP metadata from GIF, TIFF, and JPEG file formats. Oracle Multimedia also supports writing XMP data packets into GIF, TIFF, and JPEG file formats.


See Also:


6.5 Representing Metadata Outside Images

After metadata has been extracted from the binary image file, the next step is to represent the metadata in a form that can be easily stored, indexed, queried, updated, and presented. Oracle Multimedia returns image metadata in XML documents. These documents are based on XML schemas that Oracle Multimedia registers with the database. Each type of image metadata has a separate XML schema. These XML schemas are used by the metadata methods of the ORDImage object type.

The XML documents can be stored in XMLType columns within the database. These documents are easily searched and processed using the wide range of standards-based XML technologies provided by Oracle XML DB.


See Also:


6.6 Oracle Multimedia Image Metadata Examples

The following examples of metadata extraction and embedding use the photos table, which is defined by the Photo Album sample application. The implementation of the Photo Album sample application is defined in the PL/SQL package PHOTO_ALBUM. See Section 3.1 for a complete description of the Oracle Multimedia PL/SQL Web Toolkit Photo Album sample application.

The photos table stores two instances of an image: the full-size photograph and a thumbnail image. This table can also store up to four different image metadata documents. These documents are stored in the columns named metaORDImage, metaEXIF, metaIPTC, and metaXMP, and represent image metadata from the ORDImage, EXIF, IPTC, and XMP metadata formats, respectively. The metadata columns are of type XMLType, and they are bound to the corresponding metadata XML schemas that Oracle Multimedia provides.

The following subsections describe some operations you can perform with image metadata:

6.6.1 Creating a Table for Metadata Storage

Before you can extract or embed metadata, you must create the table and columns where the metadata is to be stored. The following PL/SQL code segment creates the photos table with four XMLTYPE columns (metaORDImage, metaEXIF, metaIPTC, and metaXMP) to store each type of image metadata, and two ORDIMAGE columns (image and thumb) for the original image and the thumbnail image, respectively. Each metadata column is bound to its corresponding metadata schema. For example, the metaEXIF column is bound to the XML schema stored at http://xmlns.oracle.com/ord/meta/exif, and is defined as the XML element exifMetadata.

The code statements where the image metadata columns are defined and bound to XML schemas are highlighted in bold.

--
-- Create the PHOTOS table
--
CREATE TABLE photos( id           NUMBER PRIMARY KEY,
                     description  VARCHAR2(40) NOT NULL,
                     metaORDImage XMLTYPE,
                     metaEXIF     XMLTYPE,
                     metaIPTC     XMLTYPE,
                     metaXMP      XMLTYPE,
                     image        ORDSYS.ORDIMAGE,
                     thumb        ORDSYS.ORDIMAGE )
--
-- store full-size images and thumbnail images as SecureFile LOBs
--
LOB(image.source.localdata) STORE AS SECUREFILE
LOB(thumb.source.localdata) STORE AS SECUREFILE
-- and bind the XMLType columns to the Oracle Multimedia metadata schemas
XMLType COLUMN metaORDImage
  XMLSCHEMA "http://xmlns.oracle.com/ord/meta/ordimage"
  ELEMENT "ordImageAttributes"
XMLType COLUMN metaEXIF
  XMLSCHEMA "http://xmlns.oracle.com/ord/meta/exif"
  ELEMENT "exifMetadata"
XMLType COLUMN metaIPTC
  XMLSCHEMA "http://xmlns.oracle.com/ord/meta/iptc"
  ELEMENT "iptcMetadata"
XMLType COLUMN metaXMP
  XMLSCHEMA "http://xmlns.oracle.com/ord/meta/xmp"
  ELEMENT "xmpMetadata";

6.6.2 Extracting Image Metadata

The following PL/SQL procedure extracts metadata from an image and stores it in the specified columns in the photos table you created. This procedure demonstrates the getMetadata( ) method, which returns an array of XML documents. The root element of each document is examined to determine the metadata type. The UPDATE statement stores the documents in the corresponding columns in the photos table.

The code statement where the getMetadata( ) method is called is highlighted in bold.

--
-- fetch the metadata and sort the results
--
PROCEDURE extractMetadata(inID IN INTEGER)
IS
  img ORDSYS.ORDIMAGE;
  metav XMLSequenceType;
  meta_root VARCHAR2(40);
  xmlORD XMLType;
  xmlXMP XMLType;
  xmlEXIF XMLType;
  xmlIPTC XMLType;
 
BEGIN
 
-- select the image
SELECT image
INTO img
FROM PHOTOS
WHERE id = inID;

-- extract all the metadata
metav := img.getMetadata( 'ALL' );
 
-- process the result array to discover what types of metadata were
returned
FOR i IN 1..metav.count() LOOP
  meta_root := metav(i).getRootElement();
  CASE meta_root
    WHEN 'ordImageAttributes' THEN xmlORD := metav(i);
    WHEN 'xmpMetadata' THEN xmlXMP := metav(i);
    WHEN 'iptcMetadata' THEN xmlIPTC := metav(i);
    WHEN 'exifMetadata' THEN xmlEXIF := metav(i);
    ELSE NULL;
  END CASE;
END LOOP;

-- Update metadata columns
--
UPDATE photos
SET metaORDImage = xmlORD,
    metaEXIF = xmlEXIF,
    metaIPTC = xmlIPTC,
    metaXMP = xmlXMP
WHERE id = inID;
 
END extractMetadata;

6.6.3 Embedding Image Metadata

The following PL/SQL procedure demonstrates the putMetadata( ) method. This procedure accepts six arguments. The entry_id argument identifies the image in the photos table to be updated. The remaining arguments (title, creator, date, description, and copyright) are strings to be formatted into an XMP packet and embedded within the target image.

This example creates an XML document instance based on the Oracle Multimedia XML schema for XMP metadata. (This schema is preregistered with Oracle XML DB. See Oracle XML DB Developer's Guide for more information.) The schema for XMP metadata defines a single, global element <xmpMetadata>. The <xmpMetadata> element contains a single, well-formed RDF document. The RDF document contains a single <RDF> element, which is derived from the rdf namespace. This RDF document is constructed using elements defined by the Dublin Core Schema.

The call to the putMetadata( ) method embeds the metadata document into the image file. The UPDATE statement stores the new image and the new metadata back in the photos table.

The code statement where the putMetadata( ) method is called is highlighted in bold.

--
-- write the metadata to the image
--
PROCEDURE write_metadata( entry_id IN VARCHAR2,
                          title IN VARCHAR2,
                          creator IN VARCHAR2,
                          date IN VARCHAR2,
                          description IN VARCHAR2,
                          copyright IN VARCHAR2 )
IS
  img ORDSYS.ORDImage;
  xmp XMLType;
  buf VARCHAR2(5000);
BEGIN
-- select the image
SELECT image
INTO img
FROM PHOTOS
WHERE id = entry_id FOR UPDATE;

-- Create the XMP packet it must be schema valid
-- to "http://xmlns.oracle.com/ord/meta/xmp"
-- and contain an <RDF> element. This example uses
-- the Dublin Core schema.

/* An example XML instance document
 
<xmpMetadata xmlns="http://xmlns.oracle.com/ord/meta/xmp" 
              xsi:schemaLocation="http://xmlns.oracle.com/ord/meta/xmp 
              http://xmlns.oracle.com/ord/meta/xmp" 
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <rdf:Description about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
      <dc:title>A Winter Day</dc:title>
      <dc:creator>Frosty S. Man</dc:creator>
      <dc:date>21-Dec-2004</dc:date>
      <dc:description>a sleigh ride</dc:description>
      <dc:copyright>North Pole Inc.</dc:copyright>
    </rdf:Description>
  </rdf:RDF>
</xmpMetadata>
 
*/
 
buf := '<xmpMetadata xmlns="http://xmlns.oracle.com/ord/meta/xmp"
         xsi:schemaLocation="http://xmlns.oracle.com/ord/meta/xmp
         http://xmlns.oracle.com/ord/meta/xmp"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <rdf:Description about="" xmlns:dc="http://purl.org/dc/elements/1.1/">';
 
IF title IS NOT NULL THEN
  buf := buf || '<dc:title>' || htf.escape_sc(title) || '</dc:title>';
END IF;
 
IF creator IS NOT NULL THEN
  buf := buf || '<dc:creator>' || htf.escape_sc(creator)
             || '</dc:creator>';
END IF;
IF date IS NOT NULL THEN
  buf := buf || '<dc:date>' || htf.escape_sc(date)
             || '</dc:date>';
END IF;
IF description IS NOT NULL THEN
  buf := buf || '<dc:description>' || htf.escape_sc(description)
             || '</dc:description>';
END IF;
IF copyright IS NOT NULL THEN
  buf := buf || '<dc:copyright>' || htf.escape_sc(copyright)
             || '</dc:copyright>';
END IF;
 
buf := buf || '
  </rdf:Description>
  </rdf:RDF>
  </xmpMetadata>';

-- create the XML document
xmp := XMLType.createXML(buf, 'http://xmlns.oracle.com/ord/meta/xmp');
 
-- write the metadata
img.putMetadata( xmp, 'XMP' );
 
-- update the image
UPDATE photos
SET image = img,
    metaXMP = xmp
WHERE id = entry_id;
 
END write_Metadata;

6.7 Metadata References

The following Web sites provide information about standards and technologies related to working with metadata in images.

PKVjZZPK"+AOEBPS/ch_imexapp.htm Oracle Multimedia Java API Sample Application

5 Oracle Multimedia Java API Sample Application

This chapter describes the Oracle Multimedia Java API sample application. The Oracle Multimedia Java API sample application is a Java application that uses Oracle Multimedia Java classes to demonstrate how to upload, download, update, and delete Oracle Multimedia objects, including image, audio, and video. It also demonstrates how to extract attributes from media content, generate thumbnail images, and display media.

This chapter assumes the following:

After installing the Oracle Database Examples media, the sample application files and README.txt file are located at:

<ORACLE_HOME>/ord/im/demo/java (on Linux and UNIX)

<ORACLE_HOME>\ord\im\demo\java (on Windows)

This chapter describes how to run the Oracle Multimedia Java API sample application. See Section 2.4.1 and the README.txt file for additional requirements and instructions on installing, configuring, compiling, and running this sample application.

This chapter includes these sections:

More Sample Applications

See these chapters for more sample applications:

Chapter 3 describes these Photo Album sample Web applications:

These Web applications use PL/SQL scripts, Java servlet files, and JSP files to demonstrate various ways to upload and retrieve media using Oracle Multimedia object types.

Chapter 4 describes the Oracle Multimedia Code Wizard sample application, a media upload and retrieval Web application for the PL/SQL Gateway.

5.1 Running the Oracle Multimedia Java API Sample Application

To use the Oracle Multimedia Java API sample application to retrieve, save, play, and delete multimedia data from the Oracle Database sample schemas, you must perform these steps:

  1. Install Oracle Database with Oracle Multimedia.

  2. Grant the appropriate permissions to the user who is connecting to the database.

  3. Compile and start the sample application.

  4. Log in and run the sample application.

The following section describes the Java class files, and shows code examples that demonstrate how to use Oracle Multimedia object types and methods and other Oracle objects in a Java application.

5.2 Description of the Oracle Multimedia Java API Sample Application

The Oracle Multimedia Java API sample application lets you retrieve multimedia data from the Oracle Database sample schemas, save to a file, play, and delete from the sample schema image, audio, video, and testimonial data using these Oracle Multimedia object types:

This sample application uses the PRODUCT_INFORMATION table in the Order Entry (OE) sample schema, and the ONLINE_MEDIA table in the Product Media (PM) sample schema.


Note:

After installing Oracle Multimedia, if the OE and PM sample schemas do not exist, you must install them manually before compiling and running the sample application.


See Also:

Oracle Database Sample Schemas for more information about the OE and PM schemas


The Oracle Multimedia Java API sample application, when compiled, creates the class files shown in Table 5-1:

Table 5-1 Java Class Files in the Compiled Sample Application

NameDescription

IMExample

Creates the sample application frame and maintains the only connection to the database. This class is the entry point of this sample application.

IMExampleFrame

Extends the JFrame class and displays the main frame.

IMLoginDialog

Extends the JDialog class, displays the login dialog box, and creates the connection to the database.

IMExampleQuery

Performs the SQL SELECT statement to retrieve rows of the OE.PRODUCT_INFORMATION table and displays the content of the table by product ID.

IMProductDialog

Extends the JDialog class, shows a dialog box to display detailed information for a particular product, including the product ID, product name, and product description. The IMProductDialog class also retrieves and displays the product photo, audio, video, and testimonial data within the appropriate panel. It supports retrieving, saving, deleting, and playing the media data. And, it allows for applying changes or rolling back changes to the media objects.

IMImagePanel

Extends the IMMediaPanel class, displays the product photo and its attributes: MIME type, image height, image width, and content length, and if it applies, generates and displays the thumbnail image and displays lists for reading and writing metadata.

IMAudioPanel

Extends the IMMediaPanel class and displays the product audio and its attributes: MIME type, duration of the audio, and content length.

IMVideoPanel

Extends the IMMediaPanel class and displays the product video and its attributes: MIME type, frame height, frame width, duration of the video, and content length.

IMDocPanel

Extends the IMMediaPanel class and displays the product testimonials and its attributes: MIME type and content length.

IMLoadFile

Loads a media stream (photo, video, audio, and testimonials), from a file to the PM.ONLINE_MEDIA table in the database, and if necessary, inserts a row and initializes the media objects, then updates the media data, sets the media attributes, and generates and updates the thumbnail image if loading a photo.

IMSaveFile

Saves a media stream from the database to a target file.

IMMediaPanel

Extends the JPanel class, lays out the common components for the photo, audio, video, and doc panel with load, save, delete, and play check boxes, initializes the MIME configuration file for each operating system that lists plug-in players and media and their associated MIME types, plays the data stream associated with the MIME type of the media, and enables users to specify their own player to play the media data stream.


The major flow among these class files is: IMExample to IMExampleFrame to IMLoginDialog (login) to IMExampleFrame.showDefaultTable( ) to IMExampleQuery to IMProductDialog to one group of classes (IMImagePanel, IMAudioPanel, IMVideoPanel, IMDocPanel), and finally to the last group of classes (IMLoadFile, IMSaveFile, IMMediaPanel).

Table 5-2 lists and describes the remaining Java class files in this sample application:

Table 5-2 Additional Java Class Files in the Sample Application

NameDescription

IMUtil

Includes common utilities such as a method to generate and update thumbnail images, wrapper methods for each setProperties( ) method of each media object type to separate the exceptions caused by unrecognizable formats, and cleanup methods to close the following: resultSet, Statement, input stream and its reader, and output stream and its writer.

IMMIME

Loads and stores the mapping between plug-in players and the MIME type.

IMResultSetTableModel

Extends the AbstractTableModel class and controls the display of the OE.PRODUCT_INFORMATION table.

IMMessage

Displays various messages for the sample application and classifies the message level as error, warning, or suggestion.

IMMessageResource

Extends the java.util.ListResourceBundle class and contains the actual message text for all messages.

IMJOptionPane

Extends and puts into subclasses the JOptionPane class to add an accessible description message to the displayed dialog box.

IMGetMetadataDialog

Extends the JDialog class, and retrieves the metadata from an image into an XML document and then displays the XML document in a JTree form.

IMPutMetadataDialog

Extends the JDialog class, and constructs an XMP packet to write into an image from user inputs.

XMLTreeNode

Extends the DefaultMutableTreeNode class, and creates a tree representation of an XML node.

XMLTreeView

Extends the JPanel class, and displays an XML document as a tree.

IMFileChooser

Extends the JFileChooser class, and inherits from the JFileChooser class to add the button mnemonic and accessible description.

IMConstants

Describes the IMConstants interface, which contains all the constants for column names, media types, message types, and message dialog titles.

IMAttrTableModel

Extends and puts into subclasses the DefaultTableModel class to provide the table model for displaying media attributes, and overwrites the isCellEditable( ) method to make the cells uneditable.

FocusedJTextField

Extends and puts into subclasses the JTextField class and overwrites the isFocusTraversable( ) method to enable it to gain focus when it is set to uneditable.

FocusedJTextArea

Extends and puts into subclasses the JTextArea class and overwrites the isFocusTraversable( ) method to enable it to gain focus when it is set to uneditable; also overrides the isManagingFocus( ) method to force the JTextArea class not to handle a TAB key operation.

FocusedJPanel

Extends and puts into subclasses the JPanel class and overwrites the isFocusTraversable( ) method to enable it to gain focus.

FocusedJLabel

Extends and puts into subclasses the JLabel class, overwrites the isFocusTraversable( ) method, and adds a focus listener to enable it to gain focus.

BooleanRenderer

Extends the JCheckBox class and renders Boolean objects as JCheckBox (a check box) in a JTable (two-dimensional table format). This class also sets the AccessibleName and AccessibleDescription properties by setting the tooltip to support accessibility.

IMStreamAbsorber

Extends the Thread class and runs as a separate thread to consume an input stream. This is useful when a plug-in application is loaded and it writes something out to, for example, a standard error, without consuming the application's output, the application may be unable to continue.

IMTable

Extends and puts into subclasses the JTable class and overwrites the isManagingFocus( ) method to avoid letting the table handle a TAB key operation.

IMTableRenderer

Extends the DefaultTableCellRenderer class and renders the PRODUCT_ID, PRODUCT_NAME, and PRODUCT_DESCRIPTION columns to add accessibility information, and sets the customized display.

IMUIUtil

Includes common GUI utilities.


The following subsections describe the main operations that are performed within specific classes in the Oracle Multimedia Java API sample application:

5.2.1 Operations in the IMProductDialog Class

This class defines the following methods followed by a description of what each method does:

  • The loadMedia( ) method to retrieve the media objects from the database. This method performs a SQL SELECT...FOR UPDATE statement on the PM.ONLINE_MEDIA table where the PRODUCT_ID column is a parameter marker; then this class uses the getORAData and getORADataFactory interfaces to get the media data objects from the result set.

  • The displayMedia( ) method to display the media data, which in turn calls the corresponding media display methods displayImage( ), displayAudio( ), displayVideo( ), and displayDoc ( ).

  • The displayImage( ) method calls the IMImagePanel.display( ) method to display the image data attributes, display the thumbnail image, and display the full sized image using a media player that supports this MIME type.

  • The displayAudio( ) method calls the IMAudioPanel.display( ) method to display the audio data attributes and play the audio stream using a media player that supports this MIME type.

  • The displayVideo( ) method calls the IMVideoPanel.display( ) method to display the video data attributes and play the video stream using a media player that supports this MIME type.

  • The displayDoc( ) method calls the IMDocPanel.display( ) method to display the testimonial data attributes and play the testimonial data using a media player that supports this MIME type.

The following code example shows the loadMedia( ), displayMedia( ), displayImage( ), displayAudio( ), displayVideo( ), and displayDoc( ) methods, and highlights in bold the SQL query statements and areas in the code where Oracle Multimedia and other Oracle object types and methods are used.

  private void loadMedia() throws SQLException, IOException
  {
    String sQuery = 
      "select product_photo, product_thumbnail, product_audio, product_video, " + 
      "product_testimonials from pm.online_media where product_id = ? for update";

    OracleConnection conn = null;
    OracleResultSet rs = null;
    OraclePreparedStatement pstmt = null;
    boolean isInsertNeeded = false;
    byte[] ctx[] = new byte[1][64];

    try
    {
      conn = IMExample.getDBConnection();

      pstmt = (OraclePreparedStatement)conn.prepareStatement(sQuery);
      pstmt.setInt(1, m_iProdId);
      rs = (OracleResultSet)pstmt.executeQuery();
      if (rs.next() == true)
      {
        m_img = (OrdImage)rs.getORAData(1, OrdImage.getORADataFactory());
        m_imgThumb = (OrdImage)rs.getORAData(2, OrdImage.getORADataFactory());
        m_aud = (OrdAudio)rs.getORAData(3, OrdAudio.getORADataFactory());
        m_vid = (OrdVideo)rs.getORAData(4, OrdVideo.getORADataFactory());
        m_doc = (OrdDoc)rs.getORAData(5, OrdDoc.getORADataFactory());
      }

      displayMedia();

      rs.close();
      pstmt.close();
    }
    finally
    {
      IMUtil.cleanup(rs, pstmt);
    }
  }

  private void displayMedia() throws SQLException, IOException
  {
    displayImage();
    displayAudio();
    displayVideo();
    displayDoc();
  }

  /**   * Add the product photo panel.
   */
  private void displayImage() throws SQLException, IOException
  {
    m_jImgPanel = new IMImagePanel(this, 
        m_img, m_imgThumb, m_iProdId, m_colorFieldBg);
    m_jImgPanel.display();
    m_jImgPanel.getAccessibleContext().setAccessibleName
      ("Product photo panel");
    m_jImgPanel.getAccessibleContext().setAccessibleDescription
      ("Product photo panel with an image icon on the left, " + 
       "image attribute panel in the middle and image control" +
        "panel on the right.");

    m_jMediaPanel.add(m_jImgPanel);

    Component jImgFocus = m_jImgPanel.getFirstFocusComponent();
  }

  /**
   * Add the product audio panel.
   */
  private void displayAudio() throws SQLException, IOException
  {
    m_jAudPanel = new IMAudioPanel(this, m_aud, m_iProdId, m_colorFieldBg);
    m_jAudPanel.display();
    m_jAudPanel.getAccessibleContext().setAccessibleName
      ("Product audio panel");
    m_jAudPanel.getAccessibleContext().setAccessibleDescription(
        "Product audio panel with an audio icon at the left, " + 
        "audio attribute panel in the middle and audio control" +
        "panel at the right.");
    m_jMediaPanel.add(m_jAudPanel);
  }

  /**
   * Add the product video panel.
   */
  private void displayVideo() throws SQLException, IOException
  {
    m_jVidPanel = new IMVideoPanel(this, m_vid, m_iProdId, m_colorFieldBg); 
    m_jVidPanel.display();
    m_jVidPanel.getAccessibleContext().setAccessibleName
      ("Product audio panel");
    m_jVidPanel.getAccessibleContext().setAccessibleDescription(
        "Product audio panel with an video icon at the left, " + 
        "video attribute panel in the middle and video control" +
        "panel at the right.");
    m_jMediaPanel.add(m_jVidPanel);
  }

  /**
   * Add the product testimonials panel.
   */
  private void displayDoc() throws SQLException, IOException
  {
    m_jDocPanel = new IMDocPanel(this, m _doc, m_iProdId, m_colorFieldBg);
    m_jDocPanel.display();
    m_jDocPanel.getAccessibleContext().setAccessibleName
      ("Product testimonials panel");
    m_jDocPanel.getAccessibleContext().setAccessibleDescription(
        "Product testimonials panel with an document icon at the left, " + 
        "testimonials attribute panel in the middle and testimonials control" +
        "panel at the right.");
    m_jMediaPanel.add(m_jDocPanel);
  }

See Operations in the IMImagePanel Class, Operations in the IMAudioPanel Class, Operations in the IMVideoPanel Class, and Operations in the IMDocPanel Class for code examples of the corresponding m_jXxxPanel.display( ) methods, where Xxx represents the particular media data type, Img, Aud, Vid, or Doc.

5.2.2 Operations in the IMImagePanel Class

This class displays the image panel, the product photo and its attributes, and the thumbnail image, and lists for reading and writing metadata. What follows is a more detailed description of each of the methods that are defined and what each method does:

  • The display( ) method, which first calls the insertProperty( ) method, which calls the Oracle Multimedia image object type methods getMimeType( ), getHeight( ), getWidth( ), and getContentlength( ) to get the attributes of the image to display in a table, and lays out the user interface components for reading and writing image metadata.

  • For supported formats, the class displays the product photo thumbnail image, which is generated by calling the IMUtil.generateThumbnail( )method to create the thumbnail image from the product photo.

  • The addThumbnail( ) method to show the new thumbnail image.

  • The changeThumbnail( ) method to change the thumbnail image.

  • The saveToFile( ) method to save the photo to a file.

  • The deleteMedia( ) method to delete the product photo image and its thumbnail image from the database by setting the image object type columns to empty using the OrdImage.init( ) method.

  • The play( ) media method to show the image using a media player.

  • The setMedia( ) method to set the photo and thumbnail object.

  • The notExist( ) method checks whether the image data exists and returns true if the BLOB is empty or is not associated with an existing BFILE; otherwise, it returns false.

  • The getDataInByteArray( ) method retrieves image data into a byte array by calling the Oracle Multimedia importData( ) method first for the BFILE and returns the results of calling the Oracle Multimedia getDataInByteArray( ) method.

  • The refreshPanel( ) method refreshes the display when updating the photo image, attributes, and thumbnail image.

  • The getFirstFocusComponent( ) method enforces the correct focus order.

  • The emptyPanel( ) method clears the icon and attribute panel.

  • The showMetadata( ) method to pop up a window for displaying metadata for the selected type.

  • The writeMetadata( ) method to display the write metadata dialog.

The following code example includes the display( ), insertProperty( ), notExist( ), getDataInByteArray( ), and refreshPanel( ) methods, and highlights in bold any SQL query statements and areas in the code where Oracle Multimedia and other Oracle object types and methods are used:

  void display() throws IOException, SQLException
  {
    addControlPane();

    if (notExist(m_img))
    {
      // The image does not exist.
      m_hasMedia = false; 
      layoutEmpty(s_sNotExist);
    }
    else
    {
      m_hasMedia = true; 
      // If image exists, try to show the attributes.
      if (insertProperty())
      {
        // Show the thumbnail image.
        // If the thumbnail image does not exist, generate it first.
        if (m_imgThumb != null)
        {
          String sFormat = m_imgThumb.getFormat();

          if (notExist(m_imgThumb) ||
              ( !("JFIF".equalsIgnoreCase(sFormat)) &&
                !("GIFF".equalsIgnoreCase(sFormat))
              ))
          {
            m_imgThumb = IMUtil.generateThumbnail(m_iProdId, m_img, m_imgThumb);
          }

          byte[] thumbnail = getDataInByteArray(m_imgThumb);
          addThumbnail(thumbnail);
        }
        else
        {
          m_imgThumb = IMUtil.generateThumbnail(m_iProdId, m_img, m_imgThumb);
          byte[] thumbnail = getDataInByteArray(m_imgThumb);
          addThumbnail(thumbnail);
        }
      }
    }
  }
.
.
.
  boolean insertProperty() throws SQLException
  {
    boolean isFormatSupported = false;
    String sMimeType = m_img.getMimeType();

    if (sMimeType == null)
      isFormatSupported = IMUtil.setProperties(m_img);
    else
      isFormatSupported = true;

    if (!isFormatSupported)
    {
      layoutEmpty(s_sNotSupported);
    }
    else
    {
      Object[][] data = 
      {
        {"MIME Type",  m_img.getMimeType()},
        {"Height", new Integer(m_img.getHeight()).toString()},
        {"Width",  new Integer(m_img.getWidth()).toString()},
        {"Content Length", new Integer(m_img.getContentLength()).toString()}
      };

      .
      .
      .
    }

    return isFormatSupported;  }
.
.
.
  static boolean notExist(OrdImage img) throws SQLException, IOException
  {
    if (img == null)
      return true;
    else
    {
      if (img.isLocal() && (img.getDataInByteArray() == null))
        return true;
      else if (!img.isLocal() && (":///".equals(img.getSource())))
        return true;
      else
      {
        if (!img.isLocal())
        {
          BFILE bfile = img.getBFILE();
          if (!bfile.fileExists())
            return true;
          else 
            return false;
        }
        else
          return false;
      }
    }
  }
.
.
.
  static byte[] getDataInByteArray(OrdImage img) throws SQLException, IOException
  {
    if (notExist(img))
      return null;
    else
    {
      if (!img.isLocal())
      {
        byte[] ctx[] = new byte[1][4000];
        try
        {
          img.importData(ctx);
        }
        catch (SQLException e)
        {
          new IMMessage(IMConstants.ERROR, "MEDIA_SOURCE_ERR", e);
          return null;
        }
      }
      return img.getDataInByteArray();
    }
  }
.
.
.
  void refreshPanel(boolean isFormatSupported) throws SQLException, IOException
  {
    m_hasMedia = true;
    if (isFormatSupported)
    {
      if (m_jAttrTbl == null)
      {
        m_jAttrPane.remove(m_jEmpty);
        m_jIconPane.remove(m_jIcon);

        byte[] thumbnail = getDataInByteArray(m_imgThumb);
        addThumbnail(thumbnail);

        insertProperty();
      }
      else
      {
        byte[] thumbnail = getDataInByteArray(m_imgThumb);
        changThumbnail(thumbnail);

        m_jAttrTbl.setValueAt(m_img.getMimeType(), 0, 1);
        m_jAttrTbl.setValueAt(new Integer(m_img.getHeight()).toString(), 1, 1);
        m_jAttrTbl.setValueAt(new Integer(m_img.getWidth()).toString(), 2, 1);
        m_jAttrTbl.setValueAt(new Integer(m_img.getContentLength()).toString(),3, 1);
      }
    }
   .
   .
   .
  }

5.2.3 Operations in the IMGetMetadataDialog Class

This class shows a dialog to display detailed information for metadata in a product photograph. This class also defines the displayMetadata( ) method and describes what it does.

The displayMetadata( ) method retrieves metadata from the image by using the Oracle Multimedia OrdImage getMetadata( ) method, and then displays the metadata.

The following code example includes the displayMetadata( ) method, and highlights in bold any SQL query statements and areas in the code where Oracle Multimedia and other Oracle object types and methods are used:

  private void displayMetadata(String sMetaType) 
  {
    XMLDocument doc = null;
    try
    {
      //
      // Retrieves the metadata into an XMLType array
      //
      XMLType xmlList[] = m_img.getMetadata(sMetaType);
 
      if (xmlList.length == 1)
      {
        DOMParser parser = new DOMParser();
        parser.setValidationMode(XMLConstants.NONVALIDATING);
        parser.setPreserveWhitespace(false);
        parser.parse(new StringReader(XMLType.createXML(xmlList[0]).getStringVal()));
        doc = parser.getDocument();
      }
    }
    .
    .
    .
  }

5.2.4 Operations in the IMPutMetadataDialog Class

This class shows a dialog to write metadata into a product photograph. This class also defines the writeMetadata( ) method and describes what it does.

The writeMetadata( ) method writes XMP metadata into the image metadata by using the Oracle Multimedia OrdImage putMetadata( ) method.

The following code example includes the writeMetadata( ) method, and highlights in bold any SQL query statements and areas in the code where Oracle Multimedia and other Oracle object types and methods are used:

  void writeMetadata()
  {
    try
    {
      //
      // Let the StringBuffer to hold the XMP packet
      //
      StringBuffer sb = new StringBuffer(
          "<xmpMetadata xmlns=\"http://xmlns.oracle.com/ord/meta/xmp\" "
          + " xsi:schemaLocation=\"http://xmlns.oracle.com/ord/meta/xmp "
          + " http://xmlns.oracle.com/ord/meta/xmp\" "
          + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" > "
          + " <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"> "
          + " <rdf:Description about=\"\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\"> "
          );
 
      String str = null;
      if ( (str=m_jTitleField.getText()) != null)
        sb.append("<dc:title>" + str + "</dc:title>");
      if ( (str=m_jCreatorField.getText()) !=null)
        sb.append("<dc:creator>" + str + "</dc:creator>");
      if ( (str=m_jDateField.getText()) !=null)
        sb.append("<dc:date>" + str + "</dc:date>");
      if ( (str=m_jDescriptionField.getText()) !=null)
        sb.append("<dc:description>" + str + "</dc:description>");
      if ( (str=m_jCopyrightField.getText()) !=null)
        sb.append("<dc:rights>" + str + "</dc:rights>");
 
      sb.append("</rdf:Description></rdf:RDF></xmpMetadata>");
 
      XMLType xmp = XMLType.createXML(IMExample.getDBConnection(), sb.toString(),
                "http://xmlns.oracle.com/ord/meta/xmp", true, true);
 
      //
      // Make sure the image data is local
      //
      if (!m_img.isLocal())
      {
        byte[] ctx[] = new byte[1][4000];
        m_img.importData(ctx);
      }
 
      //
      // Call Ordimage.putMetadata
      //
      m_img.putMetadata(xmp, "XMP", "utf-8");
 
      this.dispose();
    }
    .
    .
    .
  }

5.2.5 Operations in the IMVideoPanel Class

This class displays the video panel, the product video, and its attributes. This class is identical in structure and functions similarly to the IMImagePanel class. See Operations in the IMImagePanel Class for descriptions of methods.

The following code example includes the display( ), insertProperty( ), notExist( ), getDataInByteArray( ), and refreshPanel( ) methods, and highlights in bold any SQL query statements and areas in the code where Oracle Multimedia and other Oracle object types and methods are used:

  void display() throws IOException, SQLException
  {
    addControlPane();

    // Set the video icon.
    m_jIcon = new JLabel(new ImageIcon(IMExampleFrame.class.getResource("OrdVideo.gif")));
    m_jIcon.setLabelFor(m_jAttrPane);

      m_jIconPane.add(m_jIcon, BorderLayout.CENTER);

    if (notExist())
    {
      // The video does not exist.
      m_hasMedia = false; 
      layoutEmpty(s_sNotExist);
    }
    else
    {
      m_hasMedia = true; 
      // If the video exists, try to show the attributes.
      insertProperty();
    }
  }
.
.
.
  boolean insertProperty() throws SQLException
  {
    boolean isFormatSupported = false;
    String sMimeType = m_vid.getMimeType();

    if (sMimeType == null)
      isFormatSupported = IMUtil.setProperties(m_vid);
    else
      isFormatSupported = true;

    if (!isFormatSupported)
    {
      layoutEmpty(s_sNotSupported);
    }
    else
    {
      Object[][] data = 
      {
        {"MIME Type",  m_vid.getMimeType()},
        {"Height", new Integer(m_vid.getHeight()).toString()},
        {"Width",  new Integer(m_vid.getWidth()).toString()},
        {"Duration", new Integer(m_vid.getVideoDuration()).toString()},
        {"Content Length", new Integer(m_vid.getContentLength()).toString()}
      };
      .
      .
      .
    }

    return isFormatSupported;  }
.
.
.
  boolean notExist() throws SQLException, IOException
  {
    if (m_vid == null)
      return true;
    else
    {
      if (m_vid.isLocal() && (m_vid.getDataInByteArray() == null))
        return true;
      else if (!m_vid.isLocal() && (":///".equals(m_vid.getSource())))
        return true;
      else
      {
        if (!m_vid.isLocal())
        {
          BFILE bfile = m_vid.getBFILE();
          if (!bfile.fileExists())
            return true;
          else 
            return false;
        }
        else
          return false;
      }
    }
  }
.
.
.
  byte[] getDataInByteArray(OrdVideo vid) throws SQLException, IOException
  {
    if (!m_hasMedia)
      return null;
    else
    {
      if (!vid.isLocal())
      {
        byte[] ctx[] = new byte[1][4000];
        try
        {
          vid.importData(ctx);
        }
        catch (SQLException e)
        {
          new IMMessage(IMConstants.ERROR, "MEDIA_SOURCE_ERR", e);
          return null;
        }
      }
      return vid.getDataInByteArray();
    }
  }
.
.
.
  void refreshPanel(boolean isFormatSupported) throws SQLException, IOException
  {
    m_hasMedia = true;

    if (isFormatSupported)
    {
      if (m_jAttrTbl == null)
      {
        m_jAttrPane.remove(m_jEmpty);
        insertProperty();
      }
      else
      {
        m_jAttrTbl.setValueAt(m_vid.getMimeType(), 0, 1);
        m_jAttrTbl.setValueAt(new Integer(m_vid.getHeight()).toString(), 1, 1);
        m_jAttrTbl.setValueAt(new Integer(m_vid.getWidth()).toString(), 2, 1);
        m_jAttrTbl.setValueAt(new Integer(m_vid.getVideoDuration()).toString(), 3, 1);
        m_jAttrTbl.setValueAt(new Integer(m_vid.getContentLength()).toString(), 4, 1);
      }
    }
        .
        .
        .
  }

5.2.6 Operations in the IMAudioPanel Class

This class displays the audio panel, the product audio, and its attributes. This class is identical in structure and functions similarly to the IMImagePanel class. See Operations in the IMImagePanel Class for descriptions of methods.

The following code example includes the display( ), insertProperty( ), notExist( ), getDataInByteArray( ), and refreshPanel( ) methods, and highlights in bold any SQL query statements and areas in the code where Oracle Multimedia and other Oracle object types and methods are used:

  void display() throws IOException, SQLException
  {
    addControlPane();

    // Set the audio icon.
    m_jIcon = new JLabel(new ImageIcon(IMExampleFrame.class.getResource("OrdAudio.gif")));
    m_jIcon.setLabelFor(m_jAttrPane);

      m_jIconPane.add(m_jIcon, BorderLayout.CENTER);

    if (notExist())
    {
      // The audio does not exist.
      m_hasMedia = false; 
      layoutEmpty(s_sNotExist);
    }
    else
    {
      m_hasMedia = true;

      // If the audio exists, try to show the attributes.
      insertProperty();
    }
  }
.
.
.
  boolean insertProperty() throws SQLException
  {
    boolean isFormatSupported = false;
    String sMimeType = m_aud.getMimeType();

    if (sMimeType == null)
      isFormatSupported = IMUtil.setProperties(m_aud);
    else
      isFormatSupported = true;

    if (!isFormatSupported)
    {
      layoutEmpty(s_sNotSupported);
    }
    else
    {
      Object[][] data = 
      {
        {"MIME Type",  m_aud.getMimeType()},
        {"Duration", new Integer(m_aud.getAudioDuration()).toString()},
        {"Content Length", new Integer(m_aud.getContentLength()).toString()}
      };

      .
      .
      .
    }

    return isFormatSupported;
  }
.
.
.
  boolean notExist() throws SQLException, IOException
  {
    if (m_aud == null)
      return true;
    else
    {
      if (m_aud.isLocal() && (m_aud.getDataInByteArray() == null))
        return true;
      else if (!m_aud.isLocal() && (":///".equals(m_aud.getSource())))
        return true;
      else
      {
        if (!m_aud.isLocal())
        {
          BFILE bfile = m_aud.getBFILE();
          if (!bfile.fileExists())
            return true;
          else 
            return false;
        }
        else
          return false;
      }
    }
  }
.
.
.
  byte[] getDataInByteArray(OrdAudio aud) throws SQLException, IOException
  {
    if (!m_hasMedia)
      return null;
    else
    {
      if (!aud.isLocal())
      {
        byte[] ctx[] = new byte[1][4000];
        try
        {
          aud.importData(ctx);
        }
        catch (SQLException e)
        {
          new IMMessage(IMConstants.ERROR, "MEDIA_SOURCE_ERR", e);
          return null;
        }
      }
      return aud.getDataInByteArray();
    }
  }
.
.
.
  void refreshPanel(boolean isFormatSupported) throws SQLException, IOException
  {
    m_hasMedia = true;
    if (isFormatSupported)
    {
      if (m_jAttrTbl == null)
      {
        m_jAttrPane.remove(m_jEmpty);
        insertProperty();
      }
      else
      {
        m_jAttrTbl.setValueAt(m_aud.getMimeType(), 0, 1);
        m_jAttrTbl.setValueAt(new Integer(m_aud.getAudioDuration()).toString(), 1, 1);
        m_jAttrTbl.setValueAt(new Integer(m_aud.getContentLength()).toString(), 2, 1);
      }
    }
    .
    .
    .
  }

5.2.7 Operations in the IMDocPanel Class

This class displays the doc panel, the product testimonials, and its attributes. This class is identical in structure and functions similarly to the IMImagePanel class. See Operations in the IMImagePanel Class for descriptions of methods.

The following code example includes the display( ), insertProperty( ), notExist( ), getDataInByteArray( ), and refreshPanel( ) methods, and highlights in bold any SQL query statements and areas in the code where Oracle Multimedia and other Oracle object types and methods are used:

  void display() throws IOException, SQLException
  {
    addControlPane();

    // Set the icon.
    m_jIcon = new JLabel(new ImageIcon(
          IMExampleFrame.class.getResource("OrdDoc.gif")
          ));
    m_jIcon.setLabelFor(m_jAttrPane);
      m_jIconPane.add(m_jIcon, BorderLayout.CENTER);

    if (notExist())
    {
      // The doc does not exist.
      m_hasMedia = false; 
      layoutEmpty(s_sNotExist);
    }
    else
    {
      // If the doc exists, show the attribute table.
      m_hasMedia = true; 
      insertProperty();
    }
  }
.
.
.
  boolean insertProperty() throws SQLException
  {
    boolean isFormatSupported = false;
    String sMimeType = m_doc.getMimeType();

    if (sMimeType == null)
      isFormatSupported = IMUtil.setProperties(m_doc);
    else
      isFormatSupported = true;

    if (!isFormatSupported)
    {
      layoutEmpty(s_sNotSupported);
    }
    else
    {
      Object[][] data = 
      {
        {"MIME Type",  m_doc.getMimeType()},
        {"Content Length", new Integer(m_doc.getContentLength()).toString()}
      };

     .
     .
     .
    }

    return isFormatSupported;
  }
.
.
.
  boolean notExist() throws SQLException, IOException
  {
    if (m_doc == null)
      return true;
    else
    {
      if (m_doc.isLocal() && (m_doc.getDataInByteArray() == null))
        return true;
      else if (!m_doc.isLocal() && (":///".equals(m_doc.getSource())))
        return true;
      else
      {
        if (!m_doc.isLocal())
        {
          BFILE bfile = m_doc.getBFILE();
          if (!bfile.fileExists())
            return true;
          else 
            return false;
        }
        else
          return false;
      }
    }
  }
.
.
.
  byte[] getDataInByteArray(OrdDoc doc) throws SQLException, IOException
  {
    if (!m_hasMedia)
      return null;
    else
    {
      if (!doc.isLocal())
      {
        byte[] ctx[] = new byte[1][4000];
        try
        {
          doc.importData(ctx, false);
        }
        catch (SQLException e)
        {
          new IMMessage(IMConstants.ERROR, "MEDIA_SOURCE_ERR", e);
          return null;
        }
      }
      return doc.getDataInByteArray();
    }
  }
.
.
.
  void refreshPanel(boolean isFormatSupported) throws SQLException, IOException
  {
    m_hasMedia = true;
    if (isFormatSupported)
    {
      if (m_jAttrTbl == null)
      {
        m_jAttrPane.remove(m_jEmpty);
        insertProperty();
      }
      else
      {
        m_jAttrTbl.setValueAt(m_doc.getMimeType(), 0, 1);
        m_jAttrTbl.setValueAt(new Integer(m_doc.getContentLength()).toString(), 1, 1);
      }
    }
.
.
.
  }

5.2.8 Operations in the IMLoadFile Class

This class loads a media stream from a file to a database for each of the media object types. First, it checks whether this PRODUCT_ID column exists in the PM.ONLINE_MEDIA table and if not, it inserts a new row into the table. Then, it creates and initializes a new media object for each media object type, updates the media data, that is, loads it into the database if it is not already stored there, and finally, sets the media attributes for each media data object.

In this class, the IMFileLoad( ) method calls the initFileChooser( ) method, then the initFileChooser( ) method calls the loadNewMedia( ) method, which does the row insertion and initializing of the media object type columns, and then calls the updateMedia( ) method to update the media and to set the media attributes.

The following code example includes the loadNewMedia( ) and UpdateMedia( ) methods, and highlights in bold any SQL query statements and areas in the code where Oracle Multimedia and other Oracle object types and methods are used as previously described:

  private void loadNewMedia() 
    throws SQLException, FileNotFoundException, SecurityException, IOException
  {
    boolean isInsertNeeded = false;
    String sQuery = null;
    OracleConnection conn = null;
    OracleResultSet rs = null;
    OraclePreparedStatement pstmt = null;

    try
    {
      conn = IMExample.getDBConnection();

      if (m_obj == null)
      {
        // First, check whether or not this product exists in the 
        // pm.online_media table. If it exists, isInsertNeeded is set to false;
        // or else, isInsertNeeded is set to true.
        sQuery = new String(
            "select product_id from pm.online_media where product_id = ?");
        pstmt = (OraclePreparedStatement) conn.prepareStatement(sQuery);
        pstmt.setInt(1, m_iProdId);
        rs = (OracleResultSet)pstmt.executeQuery();
        if (rs.next() == false)
          isInsertNeeded = true;
        else
          isInsertNeeded = false;
        rs.close();
        pstmt.close();

        if (isInsertNeeded)
        {
          // If this product is not in the pm.online_media table, 
          // insert a row in pm.online_media for this product,
          // and initialize the media object at the same time.
          sQuery = new String(
              "insert into pm.online_media (product_id, product_photo, " + 
              "product_photo_signature, product_thumbnail, product_video, " + 
              "product_audio, product_text, product_testimonials) values (" + 
              "?, ORDSYS.ORDImage.init(), ORDSYS.ORDImageSignature.init(), " +
              "ORDSYS.ORDImage.init(),  ORDSYS.ORDVideo.init(), " +
              "ORDSYS.ORDAudio.init(), null, ORDSYS.ORDDoc.init())");

          pstmt = (OraclePreparedStatement) conn.prepareCall(sQuery);
          pstmt.setInt(1, m_iProdId);
          pstmt.execute();
          pstmt.close();
        }
      }

    if (!isInsertNeeded)
    {
      // Create a new media object.
      switch (m_iTypeIdentifier)
      {
        case IMG_TYPE:
          sQuery = new String(
              "update pm.online_media set " + m_sColName + 
              " = ORDSYS.ORDImage.init() where product_id = ?");
          break;
        case AUD_TYPE:
          sQuery = new String(
              "update pm.online_media set " + m_sColName +
              " = ORDSYS.ORDAudio.init() where product_id = ?");
          break;
        case VID_TYPE:
          sQuery = new String(
              "update pm.online_media set " + m_sColName + 
              " = ORDSYS.ORDVideo.init() where product_id = ?");
          break;
        case DOC_TYPE:
          sQuery = new String(
              "update pm.online_media set " + m_sColName +  
              " = ORDSYS.ORDDoc.init() where product_id = ?"); 
          break;
        default:
          new IMMessage(IMConstants.ERROR, "UNKNOWN_TYPE");
          break;
      }

      pstmt = (OraclePreparedStatement) conn.prepareCall(sQuery);
      pstmt.setInt(1, m_iProdId);
      pstmt.execute();
      pstmt.close();
    }

      // At this point, there is a row in the online_media table
      // for this product and the desired media object is initialized.
      // In the following, we update the media object pointer and 
      // acquire the right to modify it by selecting again from the
      // database.
      //
      sQuery = new String(
          "select " + m_sColName + 
          " from pm.online_media where product_id = ? for update");
      pstmt = (OraclePreparedStatement) conn.prepareStatement(sQuery);
      pstmt.setInt(1, m_iProdId);
      rs = (OracleResultSet)pstmt.executeQuery();
      if (rs.next() == false)
        throw new SQLException();
      else
      {
        switch (m_iTypeIdentifier)
        {
          case IMG_TYPE:
            m_img = (OrdImage)rs.getORAData(1, OrdImage.getORADataFactory());
            break;
          case AUD_TYPE:
            m_aud = (OrdAudio)rs.getORAData(1, OrdAudio.getORADataFactory());
            break;
          case VID_TYPE:
            m_vid = (OrdVideo)rs.getORAData(1, OrdVideo.getORADataFactory());
            break;
          case DOC_TYPE:
            m_doc = (OrdDoc)rs.getORAData(1, OrdDoc.getORADataFactory());
            break;
          default:
            new IMMessage(IMConstants.ERROR, "UNKNOWN_TYPE");
            break;
        }

        // Update the media object.
        updateMedia();
      }

      rs.close();
      pstmt.close();
    }
    finally
    {
      IMUtil.cleanup(rs, pstmt);
    }
  }

  /**
   * Update the media and also set the media properties.
   */
  private void updateMedia()
    throws SQLException, FileNotFoundException, SecurityException, IOException
  {
    String sQuery = null;
    OracleConnection conn = null;
    byte[] ctx[] = new byte[1][64];
    OraclePreparedStatement pstmt = null;

    boolean isFormatSupported = false;

    try
    {
      conn = IMExample.getDBConnection();
      sQuery = new String(
          "update pm.online_media set " + m_sColName + 
          " = ? where product_id = ?");
      pstmt = (OraclePreparedStatement) conn.prepareCall(sQuery);
      pstmt.setInt(2, m_iProdId);

      switch (m_iTypeIdentifier)
      {
        case IMG_TYPE:
          m_img.loadDataFromFile(m_jFileChooser.getText());
          isFormatSupported = IMUtil.setProperties(m_img);
          m_img.setLocal();
          pstmt.setORAData(1, m_img);
          break;
        case AUD_TYPE:
          m_aud.loadDataFromFile(m_jFileChooser.getText());
          isFormatSupported = IMUtil.setProperties(m_aud);
          m_aud.setLocal();
          pstmt.setORAData(1, m_aud);

          // We need to update thee media pointer for display,
          // because the input media pointer may be null.
          ((IMAudioPanel)m_parent).setMedia(m_aud);
          ((IMAudioPanel)m_parent).refreshPanel(isFormatSupported);
          break;
        case VID_TYPE:
          m_vid.loadDataFromFile(m_jFileChooser.getText());
          isFormatSupported = IMUtil.setProperties(m_vid);
          m_vid.setLocal();
          pstmt.setORAData(1, m_vid);

          ((IMVideoPanel)m_parent).setMedia(m_vid);
          ((IMVideoPanel)m_parent).refreshPanel(isFormatSupported);
          break;
        case DOC_TYPE:
          m_doc.loadDataFromFile(m_jFileChooser.getText());
          isFormatSupported = IMUtil.setProperties(m_doc);
          m_doc.setLocal();
          pstmt.setORAData(1, m_doc);

          ((IMDocPanel)m_parent).setMedia(m_doc);
          ((IMDocPanel)m_parent).refreshPanel(isFormatSupported);
          break;
        default:
          new IMMessage(IMConstants.ERROR, "UNKNOWN_TYPE");
          break;
      }

      pstmt.execute();
      pstmt.close();

      // Update the thumbnail image.
      if (m_iTypeIdentifier == IMG_TYPE)
      {
        if (isFormatSupported)
          m_imgThumb = IMUtil.generateThumbnail(m_iProdId, m_img, m_imgThumb);

        ((IMImagePanel)m_parent).setMedia(m_img, m_imgThumb);
        ((IMImagePanel)m_parent).refreshPanel(isFormatSupported);
      }
    }
    finally
    {
      IMUtil.cleanup(pstmt);
    }
  }

5.2.9 Operations in the IMUtil Class

This class contains common utilities, such as a generateThumbnail( ) static method, wrapper methods for the setProperties( ) methods for each media object type to separate the exceptions caused by unrecognizable formats, and finally, several cleanup methods.

The following code example includes the generateThumbnail( ) method, and highlights in bold any SQL query statements and areas in the code where Oracle Multimedia and other Oracle object types and methods are used:

static OrdImage generateThumbnail(int iProdId, OrdImage img, OrdImage imgThumb)
  throws SQLException
  {
    String sQuery = null;
    OracleConnection conn = null;
    OracleResultSet rs = null;
    OraclePreparedStatement pstmt = null;

    try
    {
      conn = IMExample.getDBConnection();

      if (imgThumb == null)
      {
        // The thumbnail media pointer is not initialized.
        // Initialize it first.
        sQuery = new String(
            "update pm.online_media set product_thumbnail = " + 
            "ORDSYS.ORDImage.init() where product_id = ?");
        pstmt = (OraclePreparedStatement) conn.prepareCall(sQuery);
        pstmt.setInt(1, iProdId);
        pstmt.execute();
        pstmt.close();

        // Acquire the new pointer and the permission to update.
        sQuery = new String("select product_thumbnail from pm.online_media " +
            "where product_id = ? for update");
        pstmt = (OraclePreparedStatement) conn.prepareStatement(sQuery);
        pstmt.setInt(1, iProdId);
        rs = (OracleResultSet)pstmt.executeQuery();
        if (rs.next() == false)
          throw new SQLException();
        else
          imgThumb = (OrdImage)rs.getORAData(1, OrdImage.getORADataFactory());

        rs.close();
        pstmt.close();
      }

      // Generate the thumbnail image.
      img.processCopy("maxScale=64 64, fileFormat=GIFF", imgThumb);

      // Update the thumbnail image in the database.
      sQuery = new String(
          "update pm.online_media set product_thumbnail = ? where product_id = ?");
      pstmt = (OraclePreparedStatement) conn.prepareCall(sQuery);
      pstmt.setORAData(1, imgThumb);
      pstmt.setInt(2, iProdId);
      pstmt.execute();
      pstmt.close();

      return imgThumb;
    }
    finally
    {
      IMUtil.cleanup(rs, pstmt);
    }
  }
PK-X^tePK"+AOEBPS/preface.htmr. Preface

Preface

This guide describes how to use Oracle Multimedia, which ships with Oracle Database. It describes the management and integration of audio, image, and video, or other heterogeneous media data with other Oracle tools and software, and with third-party tools and software.

In Oracle Database 11g Release 1 (11.1), the name Oracle interMedia was changed to Oracle Multimedia. The feature remains the same, only the name has changed. References to Oracle interMedia were replaced with Oracle Multimedia although, some references to Oracle interMedia or interMedia might still appear in graphical user interfaces, code examples, and related documents in the Documentation Library for Oracle Database 11g Release 2 (11.2).

The sample code in this guide might not match the code shipped with Oracle Database Examples media. To run examples that are shipped with Oracle Database Examples media on your system, use the files provided with Oracle Database Examples media. Do not attempt to compile and run the code in this guide.

See Oracle Database New Features Guide for information about Oracle Database and the features and options that are available to you.

Audience

This guide is for application developers and database administrators who are interested in storing, retrieving, and manipulating audio, image, video, and heterogeneous media data in a database, including developers of audio, heterogeneous media data, image, and video specialization options. After familiarizing yourself with the concepts presented in this guide, consult Oracle Multimedia Reference for API information.

Documentation Accessibility

Our goal is to make Oracle products, services, and supporting documentation accessible to all users, including users that are disabled. To that end, our documentation includes features that make information available to users of assistive technology. This documentation is available in HTML format, and contains markup to facilitate access by the disabled community. Accessibility standards will continue to evolve over time, and Oracle is actively engaged with other market-leading technology vendors to address technical obstacles so that our documentation can be accessible to all of our customers. For more information, visit the Oracle Accessibility Program Web site at http://www.oracle.com/accessibility/.

Accessibility of Code Examples in Documentation

Screen readers may not always correctly read the code examples in this document. The conventions for writing code require that closing braces should appear on an otherwise empty line; however, some screen readers may not always read a line of text that consists solely of a bracket or brace.

Accessibility of Links to External Web Sites in Documentation

This documentation may contain links to Web sites of other companies or organizations that Oracle does not own or control. Oracle neither evaluates nor makes any representations regarding the accessibility of these Web sites.

Access to Oracle Support

Oracle customers have access to electronic support through My Oracle Support. For information, visit http://www.oracle.com/support/contact.html or visit http://www.oracle.com/accessibility/support.html if you are hearing impaired.

Related Documents


Note:

For information added after the release of this guide, see the online README.txt file under your <ORACLE_HOME> directory. Depending on your operating system, this file may be in

<ORACLE_HOME>/ord/im/admin/README.txt

See your operating system-specific installation guide for more information.


For more information about using Oracle Multimedia in a development environment, see the following documents in the Oracle Database Online Documentation Library:

For more information about using JDBC, see Oracle Database JDBC Developer's Guide.

For more information about using XML, see Oracle XML DB Developer's Guide.

For reference information about Oracle Multimedia Java classes in Javadoc format, see the following Oracle API documentation (also known as Javadoc) in the Oracle Database Online Documentation Library:

For information about using the Oracle Multimedia JSP Tag Library, see Oracle Multimedia JSP Tag Library Guide in the Oracle Multimedia Software section of the Oracle Technology Network Web site.

For more information about Java, including information about Java Advanced Imaging (JAI), see the API documentation provided by Oracle.

Many of the examples in this guide use the sample schemas. See Oracle Database Sample Schemas for information about how these schemas were created and how you can use them.

Conventions

Although Boolean is a proper noun, it is presented as boolean in this guide when its use in Java code requires case-sensitivity.

The following text conventions are also used in this guide:

ConventionMeaning
boldfaceBoldface type indicates graphical user interface elements associated with an action, or terms defined in text or the glossary.
italicItalic type indicates book titles, emphasis, or placeholder variables for which you supply particular values.
monospaceMonospace type indicates commands within a paragraph, URLs, code in examples, text that appears on the screen, or text that you enter.

PKet/w.r.PK"+AOEBPS/ap_instl_upgrd.htm0Lϳ Managing Oracle Multimedia Installations

B Managing Oracle Multimedia Installations

This appendix describes the management of Oracle Multimedia.

This appendix includes these sections:


Note:

See the Oracle Multimedia README.txt file located in <ORACLE_HOME>/ord/im/admin for the latest information.

B.1 Oracle Multimedia Installed Users and Privileges

The Oracle Multimedia installation procedure performs these functions:

B.2 Installing and Configuring Oracle Multimedia

Oracle Multimedia is automatically installed and configured with Oracle Database.

The following subsections describe the steps to perform before manual installation and configuration of Oracle Multimedia, and the steps for manually installing and configuring it:


Caution:

Performing any of these prohibited actions could cause internal errors and security violations in the database management system.

These users are created during database installation, and might change in future releases:

  • Users in which Oracle-supplied Oracle Multimedia is installed: ORDSYS, ORDPLUGINS, SI_INFORMTN_SCHEMA, and ORDDATA

  • User in which Oracle Multimedia Locator is installed if Oracle Spatial is not installed: MDSYS

Do not delete any of these users.

Do not connect to or modify any of these users or their contents (which are supplied by Oracle Multimedia and reserved by Oracle), with these exceptions:

  • You can add user-defined packages to the user ORDPLUGINS (see Chapter 7).

  • DICOM administrators store user-defined DICOM data model configuration documents in the user ORDDATA, using the DICOM data model repository API. See Oracle Multimedia DICOM Developer's Guide for more information about inserting documents into the data model repository.


B.2.1 Preinstallation Steps

Before installing and configuring Oracle Multimedia manually, perform these steps:

  1. Install Oracle Database, including PL/SQL, Oracle JVM, Oracle XML Database, and Oracle XDK.

  2. Create the database.

  3. Start the database.

  4. Verify that the required software is correctly installed and valid, as follows:

    1. Run SQL*Plus, connect as SYSDBA, and enter these queries:

      SQL> select version, status from dba_registry where comp_id='JAVAVM';
      SQL> select version, status from dba_registry where comp_id='XDB';
      SQL> select version, status from dba_registry where comp_id='XML';
      
    2. Examine the results of the queries to ensure that each version value is identical to the version of Oracle Multimedia that you are installing and each status value is VALID.


See Also:

Oracle Database Installation Guide for your operating system for more detailed information


B.2.2 Installation and Configuration Steps

These steps are not required if you use the Database Configuration Assistant.

To install and configure Oracle Multimedia manually, perform these steps (<ORACLE_HOME> represents the Oracle home directory):

  1. Use Oracle Universal Installer to install the files that comprise Oracle Multimedia on your system.

  2. Decide which tablespace to use for the Oracle Multimedia users, and which tablespace to use for the Oracle Spatial/Oracle Multimedia Location Services user (see Table B-1). Oracle recommends using the SYSAUX tablespace for all of these users.

  3. Create the users and grant the appropriate privileges, as follows:

    1. Start SQL*Plus and connect as SYSDBA:

      % sqlplus
      
      SQL> CONNECT sys as sysdba
      
    2. Call the script ordinst.sql, with two parameters for the Oracle Multimedia tablespace and the Oracle Spatial/Oracle Multimedia Location Services tablespace:

      On Linux and UNIX:

      SQL> @<ORACLE_HOME>/ord/admin/ordinst.sql SYSAUX SYSAUX
      

      On Windows:

      SQL> @<ORACLE_HOME>\ord\admin\ordinst.sql SYSAUX SYSAUX 
      
  4. Install the Oracle Multimedia types and packages, as follows:

    Call the script catim.sql, while you are connected as SYSDBA:

    On Linux and UNIX:

    SQL> @<ORACLE_HOME>/ord/im/admin/catim.sql
    

    On Windows:

    SQL> @<ORACLE_HOME>\ord\im\admin\catim.sql
    

Now Oracle Multimedia is ready for use.

B.3 Verifying an Installed Version of Oracle Multimedia

After installing or upgrading Oracle Multimedia, you can verify the Oracle Multimedia installation by calling the Oracle Multimedia validation procedure.

To run the Oracle Multimedia validation procedure, perform these steps:

  1. Start SQL*Plus and connect as SYSDBA:

    % sqlplus
    
    SQL> CONNECT sys as sysdba
    
  2. Execute the procedure sys.validate_ordim:

    SQL> execute sys.validate_ordim;
    

    If the validation procedure detects invalid objects, it lists the first few invalid objects and sets the registry entry to INVALID; otherwise, it silently sets the Oracle Multimedia registry entry to VALID.

  3. Verify that the registry entry for Oracle Multimedia is correct, as follows:

    1. Enter this query from SQL*Plus, while you are connected as SYSDBA:

      SQL> select version, status from dba_registry where comp_id='ORDIM';
      
    2. Examine the result of the query to ensure that the version value is correct and the status value is VALID.

B.4 Upgrading an Installed Version of Oracle Multimedia

If you upgrade a database from an earlier release of Oracle Database, Oracle Multimedia is upgraded automatically if it is detected in the source database.


See Also:

Oracle Database Upgrade Guide for detailed upgrading instructions


B.5 Downgrading an Installed Version of Oracle Multimedia

Oracle Multimedia is automatically downgraded when you downgrade a database with the Oracle Multimedia feature installed.


Caution:

Do not modify your DICOM data model repository until you are sure that you are not going to downgrade from Oracle Database 11g Release 2 (11.2) back to the source release.

Changes to the Oracle Multimedia DICOM data model repository (such as document insertions or deletions) that you make after a database upgrade are lost after a database downgrade.



See Also:

Oracle Database Upgrade Guide for detailed downgrading instructions


B.6 Removing Oracle Multimedia

To remove Oracle Multimedia manually, perform these steps:

  1. Start SQL*Plus, and connect as SYSDBA:

    % sqlplus
    
    SQL> CONNECT sys as sysdba
    
  2. Call the script catcmprm.sql, with the parameter ORDIM:

    On Linux and UNIX:

    SQL> @<ORACLE_HOME>/rdbms/admin/catcmprm.sql ORDIM
    

    On Windows:

    SQL> @<ORACLE_HOME>\rdbms\admin\catcmprm.sql ORDIM
    

    If one or more components that depend on Oracle Multimedia (such as Oracle Spatial) are installed, this message appears:

    ORDIM cannot be removed as it has the following dependencies:
        Component: SDO Namespace: SERVER
    

    If no dependent components are installed, a message appears, indicating either that Oracle Multimedia is or is not in use.

    Then, a prompt asks if you really want to remove Oracle Multimedia.

  3. Reply to the prompt with Y or y to remove Oracle Multimedia.

    Oracle Multimedia is removed with force (regardless of whether it is in use).

PKo95L0LPK"+AOEBPS/ch_phtalbapps.htm Oracle Multimedia Photo Album Sample Applications

3 Oracle Multimedia Photo Album Sample Applications

This chapter describes media upload and retrieval Web applications using Oracle Multimedia object types, using these distinct Oracle Multimedia Photo Album sample Web applications:

This chapter assumes the following:

See the README.txt file for each respective sample application for installation and configuration information.

More Sample Applications

See these chapters for more sample applications:

Chapter 4 describes the Oracle Multimedia Code Wizard sample application, a media upload and retrieval Web application for the PL/SQL Gateway.

Chapter 5 describes the Oracle Multimedia Java API sample application. This sample application lets you retrieve, save, play, and delete multimedia data from the Oracle Database sample schemas using Oracle Multimedia Java classes and Oracle Multimedia object types.

3.1 Oracle Multimedia PL/SQL Photo Album Sample Application

The Oracle Multimedia PL/SQL Web Toolkit Photo Album sample application demonstrates how to perform the following operations:

When installed, this photo album application creates several schema objects that are important to the following discussion. These objects include the photos table, which is defined by the following CREATE TABLE statement:

CREATE TABLE photos( id           NUMBER PRIMARY KEY,
                     description  VARCHAR2(40) NOT NULL,
                     metaORDImage XMLTYPE,
                     metaEXIF     XMLTYPE,
                     metaIPTC     XMLTYPE,
                     metaXMP      XMLTYPE,
                     image        ORDSYS.ORDIMAGE,
                     thumb        ORDSYS.ORDIMAGE )
--
-- store full-size and thumbnail images as SecureFile LOBS
--
LOB(image.source.localdata)  STORE AS SECUREFILE
LOB(thumb.source.localdata)  STORE AS SECUREFILE
--
-- and bind the XMLType columns to the Oracle Multimedia metadata schemas
XMLType COLUMN metaORDImage
  STORE AS SecureFile CLOB
  XMLSCHEMA "http://xmlns.oracle.com/ord/meta/ordimage"
  ELEMENT "ordImageAttributes"
XMLType COLUMN metaEXIF
  STORE AS SecureFile CLOB
  XMLSCHEMA "http://xmlns.oracle.com/ord/meta/exif"
  ELEMENT "exifMetadata"
XMLType COLUMN metaIPTC
  STORE AS SecureFile CLOB
  XMLSCHEMA "http://xmlns.oracle.com/ord/meta/iptc"
  ELEMENT "iptcMetadata"
XMLType COLUMN metaXMP
  STORE AS SecureFile CLOB
  XMLSCHEMA "http://xmlns.oracle.com/ord/meta/xmp"
  ELEMENT "xmpMetadata";

The data types for the image and thumb columns are defined as Oracle Multimedia image object types. These columns are used to store the full-size images and the generated thumbnail images, respectively. The LOB storage clauses direct the database to store the full-size and thumbnail images in SecureFile LOBs, which are the highest performing storage option for binary data.

The table also defines four columns of type XMLType to store XML documents that contain four different kinds of image metadata. Each column is bound to a specific Oracle Multimedia metadata schema. Each metadata schema defines precisely the data model of the metadata document. These schemas are registered with Oracle XML DB when the database is created. The column definitions specify that the database uses unstructured storage to manage the XML metadata documents. Some advantages of using unstructured storage to manage XML include fast retrieval of the complete document and the ability to use XMLIndex indexes to improve the performance of XPath-based queries.

When installed, this photo album application also creates other schema objects. These schema objects include two types of indexes that accelerate metadata searches: a CONTEXT text index and an XMLIndex index.

The CONTEXT type is a text index over all columns that contain descriptive information about the image. These columns include PHOTOS.DESCRIPTION, which is a VARCHAR2 data type, and these four XMLType columns: PHOTOS.METAIPTC, PHOTOS.METAEXIF, PHOTOS.METAXMP, and PHOTOS.METAORDIMAGE. The CONTEXT text index is used to accelerate metadata searches by implementing the photo album search feature that enables users to search for photographs by keyword or phrase.

The CONTEXT text index is created by the following statements. (This example assumes that this photo album application has been installed in the SCOTT schema.)

-- Create preference PA_CTXIDX.
ctx_ddl.create_preference('SCOTT.PA_CTXIDX', 'MULTI_COLUMN_DATASTORE');
 
-- Create a multicolumn datastore.
ctxcols := 'description, '                   ||
            'SCOTT.photo_album.getClob(METAIPTC), ' ||
            'SCOTT.photo_album.getClob(METAEXIF), ' ||
            'SCOTT.photo_album.getClob(METAXMP), '  ||
            'SCOTT.photo_album.getClob(METAORDIMAGE)';
ctx_ddl.set_attribute( ctxpref, 'COLUMNS', ctxcols );
 
 
-- Create the CONTEXT text index.
create  index pa_ctx_idx on photos(description)
indextype is ctxsys.context
parameters ( 'DATASTORE SCOTT.PA_CTXIDX' );

The XMLIndex index is used to accelerate metadata searches by permitting users to search only certain types of image metadata and limiting the search to specific portions of an XML document. For example, the following statements create three indexes of type XMLIndex to speed up existsNode( ) queries on columns of type XMLType:

create index pa_path_iptc_idx  on photos( metaIptc )
 indextype is XDB.XMLIndex;
 
create index pa_path_exif_idx  on photos( metaExif )
 indextype is XDB.XMLIndex;
 
create index pa_path_xmp_idx  on photos( metaXMP )
 indextype is XDB.XMLIndex;

During the installation, as prescribed by the PL/SQL Gateway, a document upload table is defined by the following CREATE TABLE statement:

CREATE TABLE PHOTOS_UPLOAD( name           VARCHAR2(256) UNIQUE NOT NULL,
                            mime_type      VARCHAR2(128),
                            doc_size       NUMBER,
                            dad_charset    VARCHAR2(128),
                            last_updated   DATE,
                            content_type   VARCHAR2(128),
                            blob_content   BLOB )
-- 
-- store BLOBs as SecureFile LOBs
-- 
LOB(blob_content)  STORE AS SECUREFILE;

Each image uploaded using the PL/SQL Gateway is stored in the PHOTOS_UPLOAD table. An upload procedure (insert_new_photo) automatically moves the uploaded image from the specified PHOTOS_UPLOAD table to the photo album applications table called photos.

After installing the Oracle Database Examples media, the sample application files and README.txt file are located at:

<ORACLE_HOME>/ord/http/demo/plsqlwtk (on Linux and UNIX)

<ORACLE_HOME>\ord\http\demo\plsqlwtk (on Windows)

See the README.txt file for additional requirements and instructions on installing and using this sample application.

The following subsections provide more information about the PL/SQL Photo Album application:


See Also:


3.1.1 Running the PL/SQL Photo Album Application

After you have completed the setup tasks and have built the PL/SQL Photo Album application, including creating a database access descriptor (DAD) entry (as described in the README.txt file), you are ready to run this application.

In the address field of your Web browser, enter the following URL:

<protocol><hostname:port-number>/photoalbum
  1. In the <protocol> field, enter http://.

  2. In the <hostname:port-number> field, enter the host name and port number of the system where your HTTP server is running.

When first invoked, this photo album application displays any images that are currently stored in the album. By default, the photo album is empty when first installed. To upload a new photograph, select Upload photo. Enter a description of the photograph and the name of the image file, or browse to its directory location. Then, click Upload photo.

The contents of the photo album are displayed, along with a picture of the new photograph. Click the thumbnail image to view the full-size version of the photograph. When this photo album application displays the text view image instead of its thumbnail image, the image format that was uploaded was not recognized by Oracle Multimedia. Click view image to display the full-size image.

You can now begin to load your photo album application with your favorite photographs.

3.1.2 Description of the PL/SQL Photo Album Application

The PL/SQL Photo Album application is implemented as a set of PL/SQL procedures and functions, organized in a single PL/SQL package. These procedures combine several database features to create the application. Oracle Multimedia is used to store and process image data. It is also used to extract metadata from images and embed new metadata into images. The XMLType feature is used to store and process the XML metadata documents. Oracle Text indexes are used to accelerate two kinds of metadata searches. Finally, the PL/SQL Web Toolkit is used to create HTML pages and deliver media content.

The user interface for the PL/SQL Photo Album application consists of a set of Web pages. You can use these Web pages to perform the tasks shown in Table 3-1. The tasks and the Web pages are introduced in this section and described in further detail in the following sections.

Table 3-1 PL/SQL Photo Album Sample Application Overview

User TaskWeb PagePL/SQL Procedures

Browsing the photo album
Section 3.1.2.1

View album
Figure 3-1

view_album
Example 3-1

print_album
Example 3-2

print_image_link
Example 3-3

deliver_media
Example 3-4

Adding images to the photo album
Section 3.1.2.2

Upload photo
Figure 3-2

view_upload_form

print_upload_form
Example 3-5

insert_new_photo
Example 3-6

Searching for images by keyword or phrase
Section 3.1.2.3

Search album
Figure 3-3

view_album
Example 3-1

print_album
Example 3-2

Viewing full-size images
Section 3.1.2.4

View entry
Figure 3-4

view_entry
Example 3-7

print_image_link
Example 3-3

deliver_media
Example 3-4

Examining image metadata
Section 3.1.2.5

View metadata
Figure 3-5

view_metadata
Example 3-8

print_metadata
Example 3-9

Writing new XMP metadata to images
Section 3.1.2.6

Write XMP metadata
Figure 3-6

write_metadata
Example 3-10

Searching for images that contain specific metadata attributes
Section 3.1.2.7

Search metadata
Figure 3-7

search_metadata
Example 3-11

You can explore this photo album application using the navigation bar near the top of each Web task page. The leftmost entry of the navigation bar displays the name of the current Web page. On the right, there are links to other Web pages you can access from the current page. Each Web task page contains a link to the View album page, which is the home page for the application.

Pages in the PL/SQL Photo Album Sample Application

The following subsections,which are summarized here, describe each page in the PL/SQL Photo Album application:

  • Browsing the Photo Album

    Use the View album page to display thumbnail-size versions of all the images in the photo album and a description link positioned under each thumbnail image. When you select a thumbnail image, the full-size image is displayed. When you select the description link for an image, all the metadata for that image is displayed. The View album page is the home page for the application.

  • Adding Images to the Photo Album

    Use the Upload photo page to display a simple form to collect a description for a new image, and the directory path to the location of the image on the local computer. When you click the Upload photo button, the browser sends the image to the Web server and the image is stored in the database.

  • Searching for Images by Keyword or Phrase

    Use the Search album page to display a search album form to collect keywords or phrases to initiate full-text searches through all image metadata. The application queries the database for all images with metadata that contains the specified keywords or phrases. The search results are displayed as a set of thumbnail images. The search album form is also available from the View album page.

  • Viewing Full-Size Images

    Use the View entry page to display the full-size image of a specified photograph, including any description text that was entered for that image when it was uploaded.

  • Examining Image Metadata

    Use the View metadata page to display all the metadata that was extracted from the image when it was uploaded. Up to four types of metadata can be displayed.

  • Writing New XMP Metadata to Images

    Use the Write XMP metadata page to display a form to collect input for five metadata attributes. These attributes are formatted into an XML document that is embedded within the binary image. The new XMP metadata overwrites any existing XMP metadata.

  • Searching for Images That Contain Specific Metadata Attributes

    Use the Search metadata page to collect input and perform advanced metadata searches. You can specify the type of metadata to be searched. Optionally, you can also limit the search to a specific XML tag within the specified document. The search results are displayed as a set of thumbnail images.

3.1.2.1 Browsing the Photo Album

The home page for this photo album application, View album, displays the contents of the photo album as thumbnail images in four-column format. Each thumbnail image is also a link to the View entry page. When you click a thumbnail image link, the application displays the full-size image on a View entry page. Included under each thumbnail image on the View album page is the image description that was entered when the image was uploaded to the album. The description is also a link to the View metadata page where all the metadata for this photograph can be examined.

Near the top of the View album page, there is a text entry field (in the shape of a rectangular box) that accepts user input for a full-text search through all the photo album metadata. The Search button to the right of the text field initiates the search. The search results are displayed on the Search album page, which is discussed in Section 3.1.2.3.

At the top of the View album page, there is a navigation bar, which includes links to other photo album pages. From the View album page, you can navigate to the Search metadata page or the Upload photo page. These pages are described in Section 3.1.2.7 and Section 3.1.2.2, respectively.

Figure 3-1 shows the View album page for an album that contains several images.

Figure 3-1 View album Page with Uploaded Images

Description of Figure 3-1 follows
Description of "Figure 3-1 View album Page with Uploaded Images"

The PL/SQL procedures view_album, print_album, print_image_link, and deliver_media are the primary application components that implement the View album page. The view_album procedure is a public procedure that takes a single optional argument. By default, the argument has a NULL value. Or, it can have the value of the string entered in the text entry field on the Search album page. When the search argument is NULL, the SELECT statement retrieves the id,description, and thumb columns for all entries in the photos table. When the search string is not NULL, the SELECT statement uses the CONTAINS operator to restrict the result set to only images with metadata that matches the search string. (Section 3.1 describes how the application creates a multicolumn text index over the four XMLType columns PHOTOS.METAIPTC, PHOTOS.METAEXIF, PHOTOS.METAXMP, and PHOTOS.METAORDIMAGE as well as the PHOTOS.DESCRIPTION column.)

Example 3-1 contains some relevant lines of code in the view_album procedure.

Example 3-1 Procedure view_album

   --
   -- no search criteria so fetch all entries
   --
   IF search IS NULL THEN
     OPEN album_cur FOR
       SELECT id, description, thumb
       FROM photos
       ORDER BY id;
     print_album( album_cur, 'The photo album is empty.' );
     CLOSE album_cur;
   ELSE
   --    -- use the full-text index to select entries matching the search criteria
   --
     OPEN album_cur FOR
       SELECT id, description, thumb
       FROM photos
       WHERE CONTAINS( description, trim(search) ) > 0
       ORDER BY id;
     print_album( album_cur, 'No photos were found.' );
     CLOSE album_cur;
   END IF; 

The SELECT statement is bound to the cursor variable album_cur and passed to the procedure print_album, which creates the HTML output.

The print_album procedure uses the HTP and HTF packages from the PL/SQL Web Toolkit to create the HTML tags that format the output into a four-column table. Each cell in the table contains two links or anchor tags. The first link is to the View entry page, which displays the full-size version of the image. This anchor is implemented by PHOTO_ALBUM.VIEW_ENTRY, and passes entry_id as a query string input argument. If the thumbnail image has a nonzero length, then procedure print_image_link is called to create an HTML <img> tag that is the content (the thumbnail image) of the anchor link. The string thumb and the entry_id are passed to procedure print_image_link, along with the image description, and the height and width of the thumbnail image. These values are used to create the <img> tag.

If an image is in a format that Oracle Multimedia does not support, the application cannot create a thumbnail version of the image. In this case, the content of the anchor link is the text view image.

Example 3-2 contains some relevant lines of code in the print_album procedure.

Example 3-2 Procedure print_album

       -- escape the description text
       sc_description := htf.escape_sc( entry.description );
 
       --
       -- Display the thumbnail image as an anchor tag which can be used
       -- to display the full-size image. If the image format is not
       -- supported by Oracle Multimedia, then a thumbnail would not have been
       -- produced when the image was uploaded, so use the text '[view
       -- image]' instead of the thumbnail.
       --
 
       htp.print( '<td headers="c' || colIdx || '" align="center" >
                   <a href="PHOTO_ALBUM.VIEW_ENTRY?entry_id=' ||
                   entry.id || '">' );
       IF entry.thumb.contentLength > 0
       THEN
           print_image_link( 'thumb', entry.id, sc_description,
                             entry.thumb.height, entry.thumb.width );
       ELSE
           htp.prn( '[view image]' );
       END IF;
       htp.print( '</a>' );
 
       -- Create link to the metadata
       htp.prn('<br>');
       htp.anchor( curl=>'PHOTO_ALBUM.VIEW_METADATA?entry_id=' || entry.id,
                   ctext=>sc_description );
       htp.prn('</td>');

The procedure print_image_link uses the height and width arguments to populate the height and width attributes of the <img> tag. The description argument is used to create text for the alt attribute. If the description argument is empty, a default string is constructed. Finally, the src attribute is set to the URL PHOTO_ALBUM.DELIVER_MEDIA with two query string arguments, media and entry_id. The media argument controls whether the thumbnail or full-size version of the image is delivered. The entry_id argument identifies the image to be delivered.

Example 3-3 contains some relevant lines of code in the print_image_link procedure.

Example 3-3 Procedure print_image_link

 -- add height and width to tag if non zero
 IF height > 0 AND width > 0 THEN
   attributes := attributes || ' height=' || height || ' width=' || width;
 END IF;
 
 -- create an alt text if none given
 IF alt IS NULL THEN
   IF type = 'thumb' THEN
     alt2 := 'thumb-nail image ';
   ELSE
     alt2 := 'full-size image ';
   END IF;
   alt2 := alt2 || 'for album entry ' || entry_id;
 ELSE
   alt2 := alt;
 END IF;
 
 htp.img( curl=>'PHOTO_ALBUM.DELIVER_MEDIA?media=' || type ||
                  ampersand || 'entry_id=' || entry_id,
            calt=>alt2, cattributes=>attributes ); 

The procedure deliver_media fetches the image content from the database. The If-Modified-Since HTTP request header is compared to the last modification time of the image. If the image has not been modified, a response is sent that the browser can display the image from its cache. Otherwise, the image MIME type and last modified time are sent to the Web server, along with the image content.

Example 3-4 contains some relevant lines of code in the deliver_media procedure.

Example 3-4 Procedure deliver_media

   --
   -- Fetch the thumbnail or full-size image from the database.
   --
   IF media = 'thumb'
   THEN
       SELECT thumb INTO local_image FROM photos WHERE id = entry_id;
   ELSE
       SELECT image INTO local_image FROM photos WHERE id = entry_id;
   END IF;
 
   --
   -- Check update time if browser sent If-Modified-Since header
   --
   IF ordplsgwyutil.cache_is_valid( local_image.getUpdateTime() )
   THEN
     owa_util.status_line( ordplsgwyutil.http_status_not_modified );
     RETURN;
   END IF;
 
   --
   -- Set the MIME type and deliver the image to the browser.
   --
   owa_util.mime_header( local_image.mimeType, FALSE );
   ordplsgwyutil.set_last_modified( local_image.getUpdateTime() );
   owa_util.http_header_close();
 
   IF owa_util.get_cgi_env( 'REQUEST_METHOD' ) <> 'HEAD' THEN
     wpg_docload.download_file( local_image.source.localData );
   END IF; 

3.1.2.2 Adding Images to the Photo Album

The Upload photo page is used to add new images to the photo album. The page displays a form with two text entry fields. In the Description: field, you can optionally enter a word or short phrase that describes the image. In the File name: field, enter the name of the image file or click Browse... to locate the image file to be uploaded. The Upload photo button under the File name: field starts the upload operation. When the image is successfully uploaded, the View album page appears. From that page, you can display the contents of the photo album, as described in Section 3.1.2.1.

At the top of the Upload photo page, there is a navigation bar, which includes links to other photo album pages. From the Upload photo page, you can return to the View album page or select the Search metadata page. These pages are described in Section 3.1.2.1 and Section 3.1.2.7, respectively.

Figure 3-2 shows an Upload photo page with all the entry fields completed.

Figure 3-2 Completed Upload photo Page

Description of Figure 3-2 follows
Description of "Figure 3-2 Completed Upload photo Page"

The PL/SQL procedures view_upload_form, print_upload_form, and insert_new_photo are the primary application components that implement the Upload photo page. Together, view_upload_form and print_upload_form create the HTML page that is displayed. The page contains a form tag, a portion of which is shown in Example 3-5. The target of the form is PHOTO_ALBUM.INSERT_NEW_PHOTO.

Example 3-5 contains some relevant lines of code in the print_upload_form procedure.

Example 3-5 Procedure print_upload_form

<form action="PHOTO_ALBUM.INSERT_NEW_PHOTO"
method="post"
enctype="multipart/form-data">
database. 

Procedure insert_new_photo receives the form, processes the inputs, and stores the new image in the database.

First, the insert_new_photo procedure checks that a file name was entered into the upload form. The image size, MIME type, and BLOB locator for the image content are selected from the document upload table, and the size is checked to ensure that the image is not of zero length. If the description field is blank, a description is created using the file name.

Next, the ORDSYS.ORDIMAGE.INIT( ) function is called to initialize the thumb and image ORDImage object type columns with an empty BLOB for the new row to be stored in the photos table. A SQL SELECT FOR UPDATE statement fetches the newly initialized thumbnail image and full-size image object type columns for updating. A DBMS_LOB.COPY operation loads the image from the upload table into the image ORDImage object type column.

The ORDImage object method setProperties( ) reads the image and sets the image object attributes. Because some browsers cannot display some image formats inline, in this sample application, BMP formatted images are converted to a JPEG image format (for images with more than 8 bits of color), or a GIFF image format (for images with less than 9 bits of color) by calling the get_preferred_format function. A processCopy( ) operation is performed on the full-size image to create the thumbnail image.

The ORDImage object getMetadata( ) method is called to extract all supported types of image metadata. The root element of each XML document in the return vector is examined to discover the metadata type so that the documents can be stored in the correct columns.

Then, a SQL UPDATE statement stores the full-size image, the thumbnail image, and the image metadata documents in the database. Procedure sync_indexes is called to force an update of the text indexes. Finally, the form data input is deleted from the document upload table. A success message is returned to the browser, and the browser is redirected to the View album page.

Example 3-6 contains some relevant lines of code in the insert_new_photo procedure.

Example 3-6 Procedure insert_new_photo

   --
   -- Make sure a file name has been provided. If not, display an error
   -- message, then re-display the form.
   --
   IF new_photo IS NULL OR LENGTH( new_photo ) = 0
   THEN
       print_page_header;
       print_error( 'Please supply a file name.' );
       print_upload_form;
       print_page_trailer( TRUE );
       return;
   END IF;
 
   --
   -- Get the length, MIME type and the BLOB of the new photo from the
   -- upload table.
   --
   SELECT doc_size,
          mime_type,
          blob_content
   INTO   upload_size,
          upload_mime_type,
          upload_blob
   FROM photos_upload
   WHERE name = new_photo;
 
   --
   -- Make sure we have a valid file. 
   --
   IF upload_size = 0
   THEN
       print_page_header;
       print_heading( 'Error message' );
       htp.print( '<hr size="-1"><p>Please supply a valid image file.</p>' );
       print_upload_form;
       print_page_trailer( TRUE );
       return;
   END IF;
 
   --
   -- If the description is blank, then use the file name.
   --
   IF c_description IS NULL
   THEN
       c_description := new_photo;
       pos := INSTR( c_description, '/', -1 );
       IF pos > 0
       THEN
           c_description := SUBSTR( c_description, pos + 1 );
       END IF;
       c_description := SUBSTR( 'Image from file: ' ||
                        c_description || '.', 1, 40 );
   END IF;
   --
   -- Insert a new row into the table, returning the newly allocated sequence
   -- number.
   INSERT INTO photos ( id, description, metaExif, metaIPTC, metaXMP,
                        image, thumb )
   VALUES ( photos_sequence.nextval, c_description, NULL, NULL, NULL,
                ORDSYS.ORDIMAGE.INIT(), ORDSYS.ORDIMAGE.INIT() )
   RETURN id
   INTO new_id;
 
   --
   -- Fetch the newly initialized full-size and thumbnail image objects.
   --
   SELECT image,
          thumb
   INTO new_image,
        new_thumb
   FROM photos
   WHERE id = new_id
   FOR UPDATE;
 
   --
   -- Load the photo from the upload table into the image object.
   --
   DBMS_LOB.COPY( new_image.source.localData, upload_blob, upload_size );
   new_image.setLocal(); 
   --
   -- Set the properties. If the image format is not recognized, then
   -- the exception handler will set the MIME type and length from the
   -- upload table.
   --
   BEGIN
       new_image.setProperties();
   EXCEPTION
       WHEN OTHERS THEN
            new_image.contentLength := upload_size;
            new_image.mimeType := upload_mime_type;
   END;
 
   --
   -- Some image formats are supported by Oracle Multimedia but cannot be 
   -- displayed inline by a browser. The BMP format is one example.
   -- Convert the image to a GIF or JPEG based on number of colors in the
   -- image.
   --
   IF new_image.contentFormat IS NOT NULL AND
      ( new_image.mimeType = 'image/bmp' OR
        new_image.mimeType = 'image/x-bmp' )
   THEN
       BEGIN
           new_image.process(
                        'fileFormat=' ||
                        get_preferred_format( new_image.contentFormat ) ); 
       EXCEPTION
           WHEN OTHERS THEN
               NULL;
       END;
   END IF;
 
   --
   -- Try to copy the full-size image and process it to create the thumbnail.
   -- This may not be possible if the image format is not recognized.
   --
   BEGIN
       new_image.processCopy( thumb_scale, new_thumb );
   EXCEPTION
       WHEN OTHERS THEN
           new_thumb.deleteContent();
           new_thumb.contentLength := 0;
   END;
  --
   -- fetch the metadata and sort the results
   --
   BEGIN
     metav := new_image.getMetadata( 'ALL' );
     FOR i IN 1..metav.count() LOOP
       meta_root := metav(i).getRootElement();
       CASE meta_root
         WHEN 'ordImageAttributes' THEN xmlORD := metav(i);
         WHEN 'xmpMetadata'  THEN xmlXMP  := metav(i);
         WHEN 'iptcMetadata' THEN xmlIPTC := metav(i);
         WHEN 'exifMetadata' THEN xmlEXIF := metav(i);
         ELSE NULL;
       END CASE;
     END LOOP;
   EXCEPTION
     WHEN OTHERS THEN
       NULL;
   END;
 
   --
   -- Update the full-size and thumbnail images in the database.
   -- Update metadata columns 
   --
   UPDATE photos
   SET image = new_image,
       thumb = new_thumb,
       metaORDImage = xmlORD,
       metaEXIF = xmlEXIF,
       metaIPTC = xmlIPTC,
       metaXMP = xmlXMP
   WHERE id = new_id;
 
   --    -- update the text indexes
   --    sync_indexes;
 
   --
   -- Delete the row from the upload table.
   --
   DELETE FROM photos_upload WHERE name = new_photo;
   COMMIT;
 
   --
   -- Redirect browser to display full album.
   --    print_page_header(
       '<meta http-equiv="refresh" content="2;url=PHOTO_ALBUM.VIEW_ALBUM">' );
   print_heading( 'Photo successfully uploaded into photo album' );

3.1.2.3 Searching for Images by Keyword or Phrase

You can use the View album and Search album pages to perform a keyword or phrase search of the metadata stored in the photo album. On either of these pages, enter the keyword or phrase in the Full text search: text entry field and click Search. This photo album application uses the CONTEXT text index to locate images that have metadata containing the text you entered. If the search is successful, the thumbnail versions of the matching images are displayed in a four-column table. Select the thumbnail image to view the full-size version, or select the description link below the thumbnail image to view the metadata for the image. If the search fails, the message "No photos were found" is displayed.

At the top of the Search album page, there is a navigation bar, which includes links to other photo album pages. From the Search album page, you can return to the View album page or select the Search metadata or Upload photo pages. These pages are described in Section 3.1.2.1, Section 3.1.2.7, and Section 3.1.2.2, respectively.

Figure 3-3 shows a Search album page that contains the results of a successful search operation.

Figure 3-3 Search album Page Showing Results

Description of Figure 3-3 follows
Description of "Figure 3-3 Search album Page Showing Results"

Full-text searching of the photo album is implemented by the view_album procedure. See Section 3.1.2.1 for a discussion of this procedure.

3.1.2.4 Viewing Full-Size Images

When you select a thumbnail image, the application directs you to the View entry page. This page displays the description of the image and the full-size version of the image.

At the top of the View entry page, there is a navigation bar, which includes links to other photo album pages. From the View entry page, you can return to the View album page, or select any of the View metadata, Write metadata, Search metadata, or Upload photo pages. These pages are described in Section 3.1.2.1, Section 3.1.2.5, Section 3.1.2.6, Section 3.1.2.7, and Section 3.1.2.2, respectively.

Figure 3-4 shows a View entry page that contains the description and the full-size version of an image.

Figure 3-4 View entry Page with a Full-Size Image

Description of Figure 3-4 follows
Description of "Figure 3-4 View entry Page with a Full-Size Image"

The PL/SQL procedures view_entry, print_image_link, and deliver_media are the primary application components that implement the View entry page. The procedure view_entry takes a single parameter, entry_id, which uniquely locates the image in the photos table. The description and image object are fetched from the photos table. The procedure print_image_link creates the HTML <img> tag, and then calls procedure deliver_media to fetch the image content. See Section 3.1.2.1 for more information about the print_image_link and deliver_media procedures.

Example 3-7 contains some relevant lines of code in the view_entry procedure.

Example 3-7 Procedure view_entry

   --
   -- Fetch the row.
   --
   BEGIN
     SELECT htf.escape_sc(description), image
     INTO sc_description, photo
     FROM photos
     WHERE id = entry_id;
     EXCEPTION
     WHEN no_data_found THEN
       print_error( 'Image <b>' || htf.escape_sc(entry_id) ||
                    '</b> was not found.</p>' );
       print_page_trailer( TRUE );
       return;
   END;
 
   print_image_link( 'image', entry_id, sc_description,
                      photo.height, photo.width );

3.1.2.5 Examining Image Metadata

You can use the View metadata page to examine all the metadata for a specific image. Typically, you access this page from the View album page by selecting the description link below a thumbnail image. You can also access this page by selecting the View metadata link from the navigation bar. The View metadata page displays the thumbnail version of the image. To the right of the thumbnail image, there is a list of the metadata documents for this image. Each entry in the list is a link that takes you to the metadata document on the View metadata page.

At the top of the View metadata page, there is a navigation bar, which includes links to other photo album pages. From the View metadata page, you can return to the View album page, or select any of the View entry, Write metadata, Search metadata, or Upload photo pages. These pages are described in Section 3.1.2.1, Section 3.1.2.4, Section 3.1.2.6, Section 3.1.2.7, and Section 3.1.2.2, respectively.

Figure 3-5 shows a View metadata page that contains two types of metadata (XMP and ORDIMAGE) for an image.

Figure 3-5 View metadata Page with Metadata for an Uploaded Image

Description of Figure 3-5 follows
Description of "Figure 3-5 View metadata Page with Metadata for an Uploaded Image"

The PL/SQL procedures view_metadata and print_metadata are the primary application components that implement the View metadata page. The procedure view_metadata is passed the argument entry_id, which uniquely identifies the image in the photos table. A SELECT statement retrieves all the XMLtype metadata columns for the specified entry. If the metadata column is not NULL, procedure print_metadata is called to display the XML document inside an HTML <pre> tag.

Example 3-8 contains some relevant lines of code in the view_metadata procedure.

Example 3-8 Procedure view_metadata

   --
   -- Fetch the row.
   --
   SELECT metaOrdImage, metaEXIF, metaIPTC, metaXMP
   INTO   metaO, metaE, metaI, metaX
   FROM   photos
   WHERE  id = entry_id;
 
   -- display the EXIF metadata
   IF metaE IS NOT NULL THEN
     htp.print( '<span class="bigBlue" id="exifMetadata">EXIF</span>' );
     htp.print( '<br><pre>' );
     print_metadata( metaE );      htp.print( '</pre>' );
   END IF;

The print_metadata procedure accepts an XMLType document as an argument. It uses the getClobVal( ) method to access the document as a CLOB. The content of the CLOB is read in a loop and formatted in the HTML page using the htp.prints procedure. The htp.prints procedure escapes the '<' and '>' characters so that they are rendered properly by the Web browser.

Example 3-9 contains some relevant lines of code in the print_metadata procedure.

Example 3-9 Procedure print_metadata

   metaClob := meta.getClobVal();
   len := dbms_lob.getLength( metaClob );
   IF bufSize > len THEN
     bufSize := len;
   END IF;
   WHILE len > 0 LOOP
     dbms_lob.read( metaClob, bufSize, pos, buf );
     htp.prints( buf );
     pos := pos + bufSize;
     len := len - bufSize;
   END LOOP;

3.1.2.6 Writing New XMP Metadata to Images

You can use the Write XMP metadata page to write new or replace existing XMP metadata in an image. Oracle Multimedia provides support for writing XMP metadata only. You can access the Write XMP metadata page by selecting the Write metadata link in the navigation bar from either the View entry page or the View metadata page.

The Write XMP metadata page displays the thumbnail version of the image to be modified. The page also displays an input form to collect metadata attributes in these five text entry fields:

  • Title: Specify a title for the photograph.

  • Creator: Enter the name of the person who took the photograph. This field is optional.

  • Date: Enter the date the photograph was taken. This field is optional.

  • Description: Enter a description, such as the subject of the photograph. This field is optional.

  • Copyright: Enter the month and year when the photograph was taken. This field is optional.

Click Write it! to send the form to the application and embed the metadata in XMP format in the image.

At the top of the Write XMP metadata page, there is a navigation bar, which includes links to other photo album pages. From the Write XMP metadata page, you can return to the View album page, or select any of the View entry, View metadata, Search metadata, or Upload photo pages. These pages are described in Section 3.1.2.1, Section 3.1.2.4, Section 3.1.2.5, Section 3.1.2.7, and Section 3.1.2.2, respectively.

Figure 3-6 shows a Write XMP metadata page with completed entries for an image.

Figure 3-6 Completed Write XMP metadata Page with XMP Metadata for an Uploaded Image

Description of Figure 3-6 follows
Description of "Figure 3-6 Completed Write XMP metadata Page with XMP Metadata for an Uploaded Image"

The PL/SQL procedure write_metadata receives the form input fields from the browser. The procedure creates an XML document (as a string buffer) that is valid to the Oracle Multimedia XMP schema http://xmlns.oracle.com/ord/meta/xmp. The string buffer is used to create an XMLType object.

A SELECT FOR UPDATE statement retrieves the image to be modified. The Oracle Multimedia method putMetadata( ) is called to embed the XML document into the image. The modified image is stored back to the photos table. Finally, procedure sync_indexes is called to update the text indexes.

Example 3-10 contains some relevant lines of code in the write_metadata procedure.

Example 3-10 Procedure write_metadata

   -- Create the XMP packet it must be schema valid
   -- to "http://xmlns.oracle.com/ord/meta/xmp"
   -- and contain an <RDF> element. This example uses
   -- the Dublin Core schema as implemented by Adobe XMP
   buf := '<xmpMetadata xmlns="http://xmlns.oracle.com/ord/meta/xmp"
            xsi:schemaLocation="http://xmlns.oracle.com/ord/meta/xmp
            http://xmlns.oracle.com/ord/meta/xmp"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
     <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
     <rdf:Description about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
     <dc:title>' || htf.escape_sc(title) || '</dc:title>';

   IF c_creator IS NOT NULL THEN
     buf := buf || '<dc:creator>' || htf.escape_sc(c_creator)
                || '</dc:creator>';
   END IF;
   IF c_date IS NOT NULL THEN
     buf := buf || '<dc:date>' || htf.escape_sc(c_date)
                || '</dc:date>';
   END IF;
   IF c_description IS NOT NULL THEN
     buf := buf || '<dc:description>' || htf.escape_sc(c_description)
                || '</dc:description>';
   END IF;
   IF c_copyright IS NOT NULL THEN
     buf := buf || '<dc:copyright>' || htf.escape_sc(c_copyright)
                || '</dc:copyright>';
   END IF;
   buf := buf || '
     </rdf:Description>
     </rdf:RDF>
     </xmpMetadata>';
 
   xmp := XMLType.createXML(buf, 'http://xmlns.oracle.com/ord/meta/xmp'); 

   --    -- select image for update
   -- description is selected to force update of CTX index
   --
   SELECT image, description
   INTO img, des
   FROM photos
   WHERE id = entry_id
   FOR UPDATE;
 
   --
   -- write the metadata
   --
   img.putMetadata( xmp, 'XMP' );
 
   --
   -- save updated image and new metadata to table
   -- description updated to force update of CTX index
   --
   UPDATE photos
   SET image = img,
       metaXMP = xmp,
       description = des
   WHERE id = entry_id;
 
   -- update the text indexes
   sync_indexes;

The input data shown in Example 3-10 would result in the storage of the following metadata in the image:

<xmpMetadata xmlns="http://xmlns.oracle.com/ord/meta/xmp"
            xsi:schemaLocation="http://xmlns.oracle.com/ord/meta/xmp
            http://xmlns.oracle.com/ord/meta/xmp"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
   <rdf:Description about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
     <dc:title>Story time</dc:title>
     <dc:creator>father</dc:creator>
     <dc:date>July 4, 2001</dc:date>
     <dc:description>family reading</dc:description>
     <dc:copyright>mother</dc:copyright>
   </rdf:Description>
 </rdf:RDF>
</xmpMetadata> 

3.1.2.7 Searching for Images That Contain Specific Metadata Attributes

You can use the Search metadata page to search a specific metadata type and to limit your search to a specific tag within a metadata document. You can access the Search metadata page by selecting the Search metadata link in the navigation bar of any photo album application Web page.

The Search metadata page displays a form with four fields to define how the search is to be performed. Use the menu in the Search in metadata: field to select the type of metadata (EXIF, IPTC, or XMP) to be searched. When this field is changed, the fields Search in tag: and Search method: are initialized with values that are appropriate to the type of metadata search.

Use the drop-down list in the Search in tag: field to limit the search to a specific XML element within a metadata document. The list is populated with element names that are appropriate for the selected metadata type. When the value --Any tag-- is showing, the search looks at all elements within the document type. When the XMP metadata type is selected, searches are limited to Description elements within the parent RDF element. If the metadata document is properly constructed, selecting RDF/Description in this field searches all relevant metadata within XMP documents.

In the Search method: field, select Contains to specify a search where an element contains the search string. Select Equals to specify a search where element values are matched exactly to the search string. For searches in XMP metadata, only the Contains search method is available.

Finally, enter a keyword or phrase in the Search string: field and click Search. If the search is successful, the thumbnail versions of the matching images are displayed in a four-column table. Select the thumbnail image to view the full-size version of an image. Or, select the description link below the thumbnail image to view the metadata for the image. If the search fails, the message "No photos matched the search criteria." is displayed.

At the top of the Search metadata page, there is a navigation bar, which includes links to other photo album pages. From the Search metadata page, you can return to the View album page or select the Upload photo page. These pages are described in Section 3.1.2.1 and Section 3.1.2.2, respectively.

Figure 3-7 shows a Search metadata page that contains sample search criteria and results from a successful search operation.

Figure 3-7 Completed Search metadata Page for an Uploaded Image

Description of Figure 3-7 follows
Description of "Figure 3-7 Completed Search metadata Page for an Uploaded Image"

The PL/SQL procedure search_metadata receives the form input fields from the Web browser. The search parameters are used to build a query to find images that contain the desired metadata. The search is accomplished using the SQL function XMLExists. The XMLExists function is used to search an XML document for content that matches a given XQuery expression. The function returns TRUE if the document matched the search, and FALSE otherwise.

For example, assume that the search_metadata procedure receives input that specifies to search the caption tag in IPTC metadata for an exact match of the word "farm". The query to accomplish this search is as follows:

 SELECT id, description, thumb
 FROM photos
 WHERE xmlexists('declare default element namespace ' ||
                 ' "http://xmlns.oracle.com/ord/meta/iptc"; $x' ||
                 '/iptcMetadata[//caption="farm"]' passing metaIptc as "x");

The XPath component of the XQuery expression, '/iptcMetadata[//caption="farm"]', specifies a search for all <caption> elements under the root element <iptcMetadata> where the <caption> content is "farm".


See Also:

Oracle XML DB Developer's Guide for more information about the XMLExists function


Example 3-11 contains some relevant lines of code in the search_metadata procedure.

Example 3-11 Procedure search_metadata

    -- Set up search variables for EXIF documents.
    IF mtype = 'exif' THEN
      IF op = 'equals' THEN
        xpath  := '/exifMetadata[//' || tag || '="' || c_search || '"]';
      ELSE  -- default to contains
        xpath  := '/exifMetadata//' || tag ||
                  '[contains(., "' || c_search || '")]';
      END IF;
 
      xquery := 'declare default element namespace ' ||
                ' "http://xmlns.oracle.com/ord/meta/exif"; $x' || xpath;
 
      OPEN album_cur FOR
        SELECT id, description, thumb
        FROM photos
        WHERE xmlexists(xquery passing metaExif as "x");
 
    -- Set up search variables for IPTC documents.
    ELSIF mtype = 'iptc' THEN
      IF op = 'equals' THEN
        xpath  := '/iptcMetadata[//' || tag || '="' || c_search || '"]';
      ELSE  -- default to contains
        xpath  := '/iptcMetadata//' || tag ||
                  '[contains(., "' || c_search || '")]';
      END IF;
 
      xquery := 'declare default element namespace ' ||
            ' "http://xmlns.oracle.com/ord/meta/iptc"; $x' || xpath;
 
      OPEN album_cur FOR
        SELECT id, description, thumb
        FROM photos
        WHERE xmlexists(xquery passing metaIptc as "x");
 
    -- Set up search variables for XMP documents.
    ELSIF mtype = 'xmp' THEN
      -- default to contains
      xpath  := '//rdf:Description//*[contains(., "'
                || c_search || '")]';
 
      -- Add rdf namespace prefix.
      xquery := 'declare namespace rdf = ' ||
             ' "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; ' ||
             'declare default element namespace ' ||
             ' "http://xmlns.oracle.com/ord/meta/xmp"; $x' || xpath;
 
      OPEN album_cur FOR
        SELECT id, description, thumb
        FROM photos
        WHERE xmlexists(xquery passing metaXMP as "x");
 
    ELSE
      errorMsg := 'Search domain is invalid: ' || htf.escape_sc(mtype);
    END IF;
 
    print_search_form( mtype, tag, op, c_search );
    htp.print('<hr size="-1">');
    print_album( album_cur, 'No photos matched the search criteria.' );

3.2 Oracle Multimedia Java Servlet Photo Album Sample Application

The Oracle Multimedia Java Servlet Photo Album sample application demonstrates the use of the Oracle Multimedia Servlets and JSP Java API to upload and retrieve multimedia data to and from the database. Users access this photo album application to view the contents of the photo album, including thumbnail versions of each photograph, to view the full-size version of any photograph, and to upload new photographs into the album.

This photo album application demonstrates the use of the Oracle Multimedia image object type to upload and retrieve media data stored in Oracle Database.

When installed, this photo album application creates a table named photos and a sequence named photos_sequence.

The photos table is described by the following CREATE TABLE statement:

CREATE TABLE photos( id          NUMBER PRIMARY KEY,
                    description VARCHAR2(40) NOT NULL,
                    location    VARCHAR2(40),
                    image       ORDSYS.ORDIMAGE,
                    thumb       ORDSYS.ORDIMAGE )
--
-- store full-size images and thumbnail images as SecureFile LOBs
--
LOB(image.source.localdata)  STORE AS SECUREFILE
LOB(thumb.source.localdata)  STORE AS SECUREFILE;

The data type for the image and thumb columns are defined as Oracle Multimedia image object types to store the full-size images and the generated thumbnail images.

The photos_sequence sequence is defined by the following CREATE SEQUENCE statement:

CREATE SEQUENCE photos_sequence;

After installing the Oracle Database Examples media, the sample application files and README.txt file are located at:

<ORACLE_HOME>/ord/http/demo/servlet (on Linux and UNIX)

<ORACLE_HOME>\ord\http\demo\servlet (on Windows)

See the README.txt file for additional requirements and instructions on installing and using this sample application.

The following subsections provide more information about the Java Servlet Photo Album application:

3.2.1 Running the Java Servlet Photo Album Application

After you have completed the setup tasks and have built the Java Servlet Photo Album application, you are ready to run it.

In the address field of your Web browser, enter the URL for the default installation of Oracle Fusion Middleware or Oracle Containers for Java EE (OC4J) standalone, as follows:

<protocol><hostname:port-number>/servlet/PhotoAlbumServlet
  1. In the <protocol> field, enter http://.

  2. In the <hostname:port-number> field, enter the host name and port number of the system where your HTTP server is running.

When first invoked, this photo album application displays any images that are currently stored in the album. By default, the photo album is empty when first installed. To upload a new photograph, select Upload new photo. Enter a description of the photograph, the location where the photograph was taken, and the name of the image file (or browse to its directory location), then click Upload photo. The contents of the photo album are displayed along with a picture of the new photograph. Click the thumbnail image to view the full-size version of the photograph.

When this photo album application displays the text view image instead of its thumbnail image, the image format that was uploaded was not recognized by Oracle Multimedia. Click view image to display the full-size image.

You can now begin to load your photo album application with your favorite photographs.

3.2.2 Description of the Java Servlet Photo Album Application

The Java Servlet Photo Album application combines both business logic and the presentation into a single servlet, which when compiled, creates two class files, PhotoAlbumServlet.class and PhotoAlbumRequest.class.

To follow along with the description of tasks, refer to a copy of the PhotoAlbumServlet.java file, which is available in:

<ORACLE_HOME>/ord/http/demo/servlet (on Linux and UNIX)

<ORACLE_HOME>\ord\http\demo\servlet (on Windows)

PhotoAlbumServlet Class

The PhotoAlbumServlet class performs these tasks:

  • Extends the HttpServlet and contains the user-entered connection information.

    public class PhotoAlbumServlet extends HttpServlet
    
  • Instantiates a Java stack used to implement a simple connection-pooling mechanism.

    private static Stack connStack = new Stack();
    
  • Defines a flag to indicate whether the JDBC Thin driver has been loaded.

    private static boolean driverLoaded = false;
    
  • Defines a servlet initialization method.

    public void init( ServletConfig config ) throws ServletException
    {
        super.init(config);
    }
    
  • Defines a doGet( ) method to process an HTTP GET request containing an HttpServletRequest object and HttpServletResponse object, and instantiates a PhotoAlbumRequest object to process the request to deliver either a full-size or thumbnail image to the browser, or to display an upload form or the contents of the photo album as thumbnail images.

    public void doGet( HttpServletRequest request,
                       HttpServletResponse response )
        throws ServletException, IOException
    {
        Connection conn = null;
    
        //
        // Use a try-block to ensure that JDBC connections are always returned
        // to the pool.
        //
        try
        {
            //
            // Get a JDBC connection from the pool.
            //
            conn = getConnection();
    
            //
            // Instantiate a PhotoAlbumRequest object to process the request.
            //
            PhotoAlbumRequest albumRequest =
                new PhotoAlbumRequest( conn, request, response );
    
            //
            // Figure out what to do based on query string parameters.
            //
            String view_media = request.getParameter( "view_media" );
            if ( view_media != null )
            {
                //
                // Deliver a full-size or thumbnail image to the browser.
                //
                albumRequest.viewMedia( view_media );
                return;
            }
            else if ( request.getParameter( "view_form" ) != null )
            {
                //
                // Display the HTML upload form.
                //
                albumRequest.viewUploadForm();
            }
            else if ( request.getParameter( "view_entry" ) != null )
            {
                //
                // Display full-size photo image.
                //
                albumRequest.viewPhoto();
            }
            else
            {
                //
                // Display album contents with thumbnail images by default.
                //
                albumRequest.viewAlbum();
            }
        }
        catch ( SQLException e )
        {
            //
            // Log what went wrong.
            //
            e.printStackTrace( System.out );
    
            //
            // Turn SQL exceptions into ServletExceptions.
            //
            throw new ServletException( e.toString() );
        }
        finally
        {
            //
            // If we have a JDBC connection, then return it to the pool.
            //
            freeConnection( conn );
        }
    }
    
  • Defines a doPost( ) method to process an HTTP POST request used to upload a new photograph into the album by instantiating a PhotoAlbumRequest object to process the request and then calling the insertNewPhoto( ) method.

    public void doPost( HttpServletRequest request,
                        HttpServletResponse response )
        throws ServletException, IOException
    {
        Connection conn = null;
    
        //
        // Use a try-block to ensure that JDBC connections are always returned
        // to the pool.
        //
        try
        {
            //
            // Get a JDBC connection from the pool.
            //
            conn = getConnection();
    
            //        // Instantiate a PhotoAlbumRequest object to process the request.
            //
            PhotoAlbumRequest albumRequest =
                new PhotoAlbumRequest( conn, request, response );
    
            //
            // Insert the photo into the album.
            //
            albumRequest.insertNewPhoto();
        }
        catch ( SQLException e )
        {
            //
            // Log what went wrong.
            //        e.printStackTrace( System.out );
    
            //
            // Turn SQL exceptions into ServletExceptions.
            //
            throw new ServletException( e.toString() );
        }
        finally
        {
            //
            // If we have a JDBC connection, then return it to the pool.
            //
            freeConnection( conn );
        }
    }
    

In summary, the PhotoAlbumServlet class responds to the HTTP GET and POST requests by allocating a JDBC connection from a connection pool. Each HTTP GET or POST request is assigned its own JDBC connection from the pool to ensure that multiple requests can be serviced concurrently. An HTTP GET request is used to retrieve image data from the photo album, and an HTTP POST request is used to upload image data into the photo album. Then, an instance of the PhotoAlbumRequest class is created to execute the request, it executes the request, then it releases the JDBC connection back to the pool after completing the request.


See Also:

Oracle Database JDBC Developer's Guide and Reference for detailed information about using JDBC connections


PhotoAlbumRequest Class

The PhotoAlbumRequest class does the actual processing of an HTTP GET or POST request, and defines the getPreferredFormat( ) function and these methods:


viewAlbum( )
viewPhoto( )
viewMedia( )
viewUploadForm( )
insertNewPhoto( )
printPageHeader( )
printPageTrailer( )
printMessage( )
printHeading( )
printLink( )

In the viewMedia( ) and insertNewPhoto( ) methods, three objects, OrdHttpResponseHandler, OrdHttpUploadFormData, and OrdHttpUploadFile, are instantiated. These objects are used to call the methods of the respective OrdHttpResponseHandler, OrdHttpUploadFormData, OrdHttpUploadFile classes of Oracle Multimedia Servlets and JSP Java API. For example, in the viewMedia( ) method, the OrdHttpResponseHandler object is instantiated and used to call the sendImage( ) method as shown in this code:

OrdHttpResponseHandler handler =
    new OrdHttpResponseHandler( request, response );
handler.sendImage( img );

The viewAlbum( ), viewPhoto( ), viewMedia( ), and insertNewPhoto( ) methods use the ORAData (formerly getCustomDatum) and ORADataFactory (formerly getFactory) interfaces supplied by Oracle to get the image or thumbnail OrdImage object from the result set to obtain height and width information, to retrieve an image from an OrdImage Java object and deliver it to the browser, and to upload an image in an OrdImage Java object and to also update it in the photos table. For example, the following code segment is from the viewAlbum( ) method:

OrdImage img =
    (OrdImage)rset.getORAData( 4, OrdImage.getORADataFactory() );
.
.
.
out.print( "<td headers=\"image\"><a href=\"" + servletUri +
           "?view_entry=yes&id=" + id + "\">" );
if ( img.getContentLength() > 0 )
{
    if (img.getMimeType().startsWith("image/"))
    {
     out.print( "<img src=\"" + servletUri +
                           "?view_media=thumb&id=" + id + "\"" +
                           " height=" + img.getHeight() +
                           " width=" + img.getWidth() +
                           " alt=\"" + description + "\"" +
         " border=1>" );
    }
}
else
{
    out.print( "[view image]" );
}
out.println( "</a></td>" );
out.println( "</tr>" );

What follows is a more detailed description of each method and what it does:

  • The viewAlbum( ) method does the following:

    • Initializes the row count to zero.

    • Writes a common page header on the HTML page using the function printPageHeader( ).

    • Executes a SELECT statement to fetch all the thumbnail images in the photo album, order them by description, and display the description and location information for each along with the thumbnail image if it exists, and returns the results in a result set.

    • Displays the thumbnail images in an HTML table with column headers labeled Description, Location, and Image.

    • Within a while block, reads the contents of the result set by reading the first row's contents beginning with the id value, displays the description and location values, then gets the thumbnail OrdImage object and builds the height and width attributes for each thumbnail image.

    • Displays the thumbnail image using an HTML anchor tag that can be used to display the full-size image. When a user clicks the thumbnail image or view image, the full-size image is displayed.

    • Displays the contents of the photo album within an HTML anchor tag using the tag <IMG SRC="<servlet-path>?view_media=thumb&id=..."> to display the thumbnail images, where <servlet-path> is the value of servletUri. If the thumbnail image was not created because the image format was not supported by Oracle Multimedia, the text view image is displayed instead.

    • Increments the row count to see if the photo album is empty; if so, it displays the message "The photo album is empty".

    • Displays an HTML anchor tag near the bottom of the HTML page using the printLink( ) function with the text Upload new photo.

    • Writes a common trailer at the bottom of the HTML page by calling the printPageHeader( ) function, however, in this case, sets the Boolean argument to false to not display the common page trailer.

    • Closes the result set and the statement.

  • The viewPhoto( ) method displays the full-size version of a photograph and does the following:

    • Writes a common page header on the HTML page using the function printPageHeader( ).

    • Gets the value of the id column for the entry being viewed.

    • Executes a SQL SELECT statement to fetch the entry's description, location, and full-size image where the value of id in the where clause is a parameter marker and returns the results in a result set.

    • Gets the image OrdImage object from the result set so it can later build the image height and width attributes within the <IMG SRC=...> image tag.

    • Displays the full-size image in an HTML table beginning with the column names Description and Location, and displays the entry's values for these two columns.

    • Builds the URL to fetch a full-size image for this entry by using an image tag <IMG SRC="<servlet-path>?view_media=image&id=..."> to display an image in the column labeled Photo, where <servlet-path> is the value of servletUri.

    • Displays the full-size images height and width by calling the getHeight( ) and getWidth( ) Oracle Multimedia object methods. If the image format is not recognized by Oracle Multimedia, height and width values are zero and are not displayed.

    • Writes a common page trailer at the bottom of the HTML page by calling the printPageHeader( ) function and setting its Boolean argument to true to display the common page trailer.

    • Closes the result set and the statement.

  • The viewMedia( ) method is invoked by both thumbnail and full-size image URLs to retrieve a thumbnail or full-size image from the photos table and deliver it to the browser using the OrdHttpResponseHandler class. This method does the following:

    • Executes a SQL SELECT statement to fetch either the thumbnail or full-size image where the value of id in the where clause is a parameter marker and returns the results in a result set. The SQL SELECT statement is built dynamically with the string media equating to either the thumbnail image column or the full-size image column.

    • Fetches a row from the result set.

    • Gets the OrdImage object from the result set.

    • Uses the OrdHttpResponseHandler class to create an OrdHttpResponseHandler object to retrieve the image from the OrdImage object and deliver it to the browser using the sendImage( ) method. The sendImage( ) method supports browser content caching by supporting the If-Modified-Since and Last-Modified headers.

    • Closes the result set and the statement.

  • The viewUploadForm( ) method displays an HTML form that enables users to upload new photographs and does the following:

    • Calls the printPageHeader( ) function to produce the common page header.

    • Defines the form action as a multipart/form-data POST request.

    • Calls the upload_form_fields static string containing the contents of the upload form. The upload form is defined as a table with rows labeled Description and Location, with an input type of text and named description and location respectively, followed by a row labeled File name:, with an input type of file and named photo, and finally a row with no label, an input type of submit, and a value of Upload photo.

    • Calls the printPageTrailer( ) function to produce the common page trailer.

  • The insertNewPhoto( ) method does the following:

    • Uses the OrdHttpUploadFormData class to parse a multipart/form-data POST request containing an uploaded photograph.

    • Uses the OrdHttpUploadFile class to upload the new photograph into the database.

    • Executes a SQL SELECT photos_sequence.nextval statement to get the next value of the id column for the new row to be inserted into the photos table.

    • Executes a SQL INSERT statement to insert a new row in the photos table.

    • Executes a SQL SELECT...FOR UPDATE statement to fetch the initialized full-size and thumbnail image objects from the photos table.

    • Calls the loadImage( ) method in the OrdHttpUploadFile class to populate an OrdImage object named image with the full-size image and sets the properties or attribute values of the image object based on the image contents.

    • Checks to see what the image format is and if it is an image format that cannot be displayed inline by a browser, such as a BMP image format, then calls the getPreferredFormat( ) method to convert a BMP image format and return the preferred image format.

    • Calls the ProcessCopy( ) method in the OrdImage class to process the full-size image, create a thumbnail image, and populate an OrdImage object named thumb.

    • Executes a SQL UPDATE statement to update the full-size and thumbnail images in the database.

    • Displays a photo upload success message and then directs the browser to refresh the page.

  • A getPreferredFormat( ) private function, in this sample application, converts a BMP image format and returns the preferred image file format based on the number of colors in the image; returns a MONOCHROME image format if there are no colors, or a JPEG if there are more than 8 colors, or a GIF if there are greater than 0 and fewer than 8 colors.

  • A printPageHeader( ) private function displays an HTML header that is common to all HTML responses.

  • A printPageTrailer( ) private function displays an HTML trailer that is common to all HTML responses.

  • A printMessage( ) private function prints a message on the HTML page.

  • A printHeading( ) private function prints a header on the HTML page.

  • A printLink( ) function produces an HTML anchor tag in a standard format.

3.3 Oracle Multimedia JSP Photo Album Sample Application

The Oracle Multimedia JSP Photo Album sample application is a JavaServer Pages (JSP) application that demonstrates the use of the Oracle Multimedia Servlets and JSP Java API to upload and retrieve multimedia data to and from a database. Users access the JSP files that constitute the application to view the contents of the photo album, including thumbnail versions of each photograph, to view the full-size version of any photograph, and to upload new photographs into the album.

This photo album application demonstrates the use of the Oracle Multimedia image object type to upload and retrieve media data stored in Oracle Database.

This photo album application, when installed, creates a table named photos and a sequence named photos_sequence.

The photos table is described by the following CREATE TABLE statement:

CREATE TABLE photos( id          NUMBER PRIMARY KEY,
                    description VARCHAR2(40) NOT NULL,
                    location    VARCHAR2(40),
                    image       ORDSYS.ORDIMAGE,
                    thumb       ORDSYS.ORDIMAGE )
--
-- store full-size images and thumbnail images as SecureFile LOBs
--
LOB(image.source.localdata)  STORE AS SECUREFILE
LOB(thumb.source.localdata)  STORE AS SECUREFILE;

The data type for the image and thumb columns are defined as Oracle Multimedia image object types to store the full-size images and the generated thumbnail images.

The photos_sequence sequence is defined by the following CREATE SEQUENCE statement:

CREATE SEQUENCE photos_sequence;

After installing the Oracle Database Examples media, the sample application files and README.txt file are located at:

<ORACLE_HOME>/ord/http/demo/jsp (on Linux and UNIX)

<ORACLE_HOME>\ord\http\demo\jsp (on Windows)

See the README.txt file for additional requirements and instructions on installing and using this sample application.

The following subsections provide more information about the JSP Photo Album application:

3.3.1 Running the JSP Photo Album Application

After you have completed the setup tasks and have built the JSP Photo Album application, you are ready to run it.

In the address field of your Web browser, enter the URL for the default installation of Oracle Fusion Middleware or Oracle Containers for Java EE (OC4J) standalone, as follows:

<protocol><hostname:port-number>/demo/PhotoAlbum.jsp
  1. In the <protocol> field, enter http://.

  2. In the <hostname:port-number> field, enter the host name and port number of the system where your HTTP server is running.

When first invoked, this photo album application displays any images that are currently stored in the album. By default, the photo album is empty when first installed. To upload a new photograph, select Upload new photo. Enter a description of the photograph, the location where the photograph was taken, and the name of the image file or browse to its directory location, then click Upload photo. The contents of the photo album are displayed along with a picture of the new photograph. Click the thumbnail image to view the full-size version of the photograph.

When this photo album application displays the text view image instead of its thumbnail image, the image format that was uploaded was not recognized by Oracle Multimedia. Click view image to display the full-size image.

You can now begin to load your photo album application with your favorite photographs.

3.3.2 Description of the JSP Photo Album Application

The JSP Photo Album application separates the business logic from the presentation by having a JavaBean containing methods that are accessed from each of five JSP files. When compiled, the application creates the PhotoAlbumBean.class file, which contains the user-entered connection information and defines the functions: getId( ), getDescription( ), getLocation( ), and getPreferredFormat( ) and the following methods:


selectTable( )
selectRowById( )
fetch( )
insertNewPhoto( )
release( )
getConnection( )
freeConnection( )
setId( )
setDescription( )
setLocation( )
getImage( )
getThumb( )

To follow along with the description of tasks, refer to a copy of each JSP file, which is available in:

<ORACLE_HOME>/ord/http/demo/jsp (on Linux and UNIX)

<ORACLE_HOME>\ord\http\demo\jsp (on Windows)

In the PhotoAlbumEntryViewer, PhotoAlbumMediaViewer, PhotoAlbum, and PhotoAlbumInsertPhoto JSP files, the jsp:useBean action tag is used to establish an ID and association with the PhotoAlbumBean class and the OrdHttpJspResponseHandler and OrdHttpUploadFormData classes of Oracle Multimedia Servlets and JSP Java API. For example, the following code appears in the PhotoAlbumInsertPhoto JSP file:

<jsp:useBean id="album" scope="page" class="PhotoAlbumBean"/>
<jsp:useBean id="handler" scope="page"
             class="oracle.ord.im.OrdHttpJspResponseHandler"/>
<jsp:useBean id="formData" scope="page"
             class="oracle.ord.im.OrdHttpUploadFormData"/>

This jsp:useBean action tag is used so these objects can be referenced by their respective ID values (album, handler, and formData) to call the methods of these classes.

The OrdHttpUploadFile class of Oracle Multimedia Servlets and JSP Java API is defined as an object with the name uploadPhoto in the insertNewPhoto( ) method in the PhotoAlbumBean.java file and then used to call its loadImage( ) method to load the photograph into the photos table as shown in the following code segments:

public void insertNewPhoto( OrdHttpUploadFile uploadPhoto )
        throws SQLException, ServletException, IOException
.
.
.
uploadPhoto.loadImage( image );
.
.
.

The insertNewPhoto( ) method defined in the PhotoAlbumBean.java file, uses the ORAData (formerly getCustomDatum) and ORADataFactory (formerly getFactory) interfaces supplied by Oracle to upload an image and a thumbnail image in an OrdImage Java object. First, the method executes a SQL SELECT...FOR UPDATE statement to select the row for update, and then, executes a SQL UPDATE statement to update the image and thumb columns for that row in the photos table as shown in the following code segments:

stmt = (OraclePreparedStatement)conn.prepareStatement(
            "select image,thumb from photos where id = ? for update" );
stmt.setString( 1, id );
rset = (OracleResultSet)stmt.executeQuery();
if ( !rset.next() )
{
    throw new ServletException( "new row not found in table" );
}
image = (OrdImage)rset.getORAData( 1, OrdImage.getORADataFactory());
thumb = (OrdImage)rset.getORAData( 2, OrdImage.getORADataFactory());

rset.close();
stmt.close();
.
.
.
    //
    // Prepare and execute a SQL statement to update the full-size and
    // thumbnail images in the database.
    //
    stmt = (OraclePreparedStatement)conn.prepareStatement(
               "update photos set image = ?, thumb = ? where id = ?" );
    stmt.setORAData( 1, image );
    stmt.setORAData( 2, thumb );
    stmt.setString( 3, id );
    stmt.execute();
    stmt.close();

    //
    // Commit the changes.
    //
    conn.commit();
}

The fetch( ) method defined in the PhotoAlbumBean.java file or the PhotoAlbumBean JavaBean, fetches the next row from the result set using the ORAData and ORADataFactory interfaces to retrieve the image and the thumbnail image from an OrdImage Java object, and delivers each to the browser, as shown in the following example:

public boolean fetch()
    throws SQLException
{
    if ( rset.next() )
    {
        id = rset.getString( 1 );
        description = rset.getString( 2 );
        location = rset.getString( 3 );
        image = (OrdImage)rset.getORAData( 4, OrdImage.getORADataFactory() );
        thumb = (OrdImage)rset.getORAData( 5, OrdImage.getORADataFactory() );
        return true;
    }
    else
    {
        rset.close();
        stmt.close();
        return false;
    }
}

What follows is a more detailed description of each JSP file.

PhotoAlbum.jsp

This JSP file is the entry point to the JSP Photo Album application and does the following:

  • Uses the PhotoAlbumBean JavaBean to access the contents of the photos table.

  • Uses the OrdHttpJspResponseHandler class to facilitate the retrieval of image data from the photos table and its delivery to a browser or other HTTP client from a Java servlet.

  • Displays the title of the page in the HTML header and in the common page header.

  • Displays the thumbnail images in a table using column headers labeled, Description, Location, and Image.

  • Uses a try/catch block to ensure the JDBC connection is released.

  • Calls the selectTable( ) method to select all the rows in the photos table.

  • Initializes the row count to zero.

  • Displays an entry in the photo album by calling the getDescription( ) method, then the getLocation( ) method, and then printing the values in the appropriate columns. If the location information is blank, print a space in the Location column.

  • Displays the contents of the photo album as thumbnail images using an HTML anchor tag to call the PhotoAlbumEntryViewer.jsp file to get the ID value by calling the getID( ) function.

  • Calls the getThumb( ) method to get the thumbnail image and calls the getContentLength( ) method to determine the image length.

  • Tests to see if the value returned for the image length is greater than 0, and if so uses an image tag of the form <IMG SRC="PhotoAlbumMediaViewer.jsp?media=thumb&...> to display the thumbnail image; otherwise, prints the link view image in the column header labeled Image, which, when clicked, retrieves the full-size image.

  • Displays a message "The photo album is empty" if the photo album is empty. If the photo album is not empty, this message is displayed "Select the thumbnail to view the full-sized image".

  • Ends the try/catch block with a finally clause and releases the JDBC connection by calling the release( ) method.

  • Displays a link to the upload form with the text Upload new photo at the bottom of the page that calls the PhotoAlbumUploadForm.jsp file.

PhotoAlbumEntryViewer.jsp

This JSP file is called by the PhotoAlbum.jsp file that displays one full-size version of a photograph in the album. This JSP file does the following:

  • Uses the PhotoAlbumBean JavaBean to access the contents of the photos table.

  • Uses the OrdHttpJspResponseHandler class to facilitate the retrieval of image data from the photos table and its delivery to a browser or other HTTP client from a Java servlet.

  • Displays the title of the page in the HTML header and in the common page header.

  • Defines a string named id that calls the getParameter( ) method to get the id value.

  • Displays a message "Malformed URL, no id parameter" in the event the value of the id string is null.

  • Uses a try/catch block to ensure the JDBC connection is released.

  • Calls the selectRowById( ) method with the value of id to select the entry to be displayed. If the next row to be fetched for that id value is not found, display a message "Entry not found: <id value>".

  • Displays the entry in the album by calling the getDescription( ) method and displaying its value under the header Description, calling the getLocation( ) method and displaying its value under the Location header.

  • Displays one full-size version of a photograph in the album using an image tag in the form <IMG SRC="PhotoAlbumMediaViewer.jsp?media=image&..."> under the Photo header.

  • Displays the full-size images height and width by calling the getHeight( ) and getWidth( ) methods. If the image format is not recognized by Oracle Multimedia, height and width values are zero and are not be displayed.

  • Displays a link at the bottom of the page Return to photo album that calls the PhotoAlbum.jsp file.

  • Ends the try/catch block, and with a finally clause, releases the JDBC connection by calling the release( ) method.

PhotoAlbumMediaViewer.jsp

This JSP file is called by the PhotoAlbum.jsp and PhotoAlbumEntryViewer.jsp files and retrieves a single thumbnail or full-size image from the photos table using the PhotoAlbumBean JavaBean and delivers it to the browser using the OrdHttpResponseHandler class. This JSP file does the following:

  • Uses the PhotoAlbumBean JavaBean to access the contents of the photos table.

  • Uses the OrdHttpJspResponseHandler class to facilitate the retrieval of image data from the photos table and its delivery to a browser or other HTTP client from a Java servlet.

  • Defines a string named id that calls the getParameter( ) method to get the id value.

  • Defines a string named media that calls the getParameter( ) method to get the media value.

  • Sets a condition to proceed as long as the value of the string id and the value of the string media is not null.

  • Uses a try/catch block to ensure the JDBC connection is released.

  • Calls the selectRowById( ) method to select a specific row from the photos table for the value of id.

  • Delivers the full-size or thumbnail image by first calling the setPageContext( ) method of the OrdHttpJspResponseHandler class to specify the page context object; then, calling the getImage( ) method to return the image to the OrdImage object; then, calling the sendImage( ) method of the OrdHttpResponseHandler class to retrieve the image from the OrdImage object and deliver it to the browser. If the value of media is image, an image is delivered to the browser; if the value of media is thumb, a thumbnail image is delivered to the browser. The sendImage( ) method supports browser content caching by supporting the If-Modified-Since and Last-Modified headers.

  • Ends the try/catch block with a finally clause and releases the JDBC connection by calling the release( ) method.

  • Displays this message in the event the request is not understood "PhotoAlbumMediaViewer.jsp - malformed URL".

PhotoAlbumUploadForm.jsp

This JSP file is called by the PhotoAlbum.jsp file that displays an HTML form to enable users to upload new photographs into the album. This JSP file does the following:

  • Displays the title of the page in the HTML header and in its common page header.

  • Displays any error message under the header "Error message" from a previous attempt to upload an image to determine whether the value of a string is not null after calling the getParameter( ) method with an argument of error.

  • Displays a header with the text Upload a new photo.

  • Defines the form action specifying the PhotoAlbumInsertPhoto.jsp file to process the upload request as a multipart/form-data POST request.

  • Displays the upload form with rows labeled Description, Location, and File name:.

  • Displays the contents of the upload form defined as a table with rows labeled Description and Location, both with an input type of text and named description and location respectively, followed by a row labeled File name: with an input type of file and named photo, and finally followed by a row with no label and an input type of submit and a value of Upload photo.

  • Displays a link at the bottom of the page Return to photo album that calls the PhotoAlbum.jsp file.

PhotoAlbumInsertPhoto.jsp

This JSP file is called by the PhotoAlbumUploadForm.jsp file that uses the OrdHttpUploadFormData class to parse the POST data in a POST request containing the uploaded photograph. This JSP file does the following:

  • Uses the PhotoAlbumBean JavaBean to access the contents of the photos table.

  • Uses the OrdHttpJspResponseHandler class to facilitate the retrieval of image data from the photos table and its delivery to a browser or other HTTP client from a JSP file.

  • Uses the OrdHttpUploadFormData class to facilitate the processing of POST requests by parsing the POST data containing the multipart/form-data encoding, and making the contents of regular form fields and uploaded files readily accessible to a JSP file.

  • Sets the value of the strings description and location to null and the OrdHttpUploadFile object uploadPhoto to null.

  • Uses a try/catch block to ensure the JDBC connection is released.

  • Passes an OrdHttpUploadFile object to the PhotoAlbumBean class to store the photograph in the database.

  • Calls the setServletRequest( ) method of the OrdHttpUploadFormData class to specify the ServletRequest object for the request.

  • Tests to see if the request is encoded using the multipart/form-data encoding by calling the isUploadRequest( ) method of the OrdHttpUploadFormData class.

  • Forwards the request to the PhotoAlbumUploadForm.jsp file if the call to the isUploadRequest( ) method returns a Boolean expression of not false.

  • Parses the form data by calling the parseFormData( ) method of the OrdHttpUploadFormData class.

  • Gets the form field values for description and location by calling the getParameter( ) method of the OrdHttpUploadFormData class, and also gets the name of the file to be uploaded by calling the getFileParameter( ) method of the same class.

  • Tests to make sure the file name is not null from the getFileParameter( ) method call of the OrdHttpUploadFormData class, then calls the getOriginalFileName( ) method of the OrdHttpUploadFile class to ensure that the original file name as provided by the browser is not null, or that the content length of the file is empty by calling the getContentLength( ) method of the OrdHttpUploadFile class.

  • Forwards the request to the PhotoAlbumUploadForm.jsp file if there is a valid image file.

  • If the description is null or empty, uses the file name as the description by calling the getSimpleFileName( ) method of the OrdHttpUploadFile class.

  • Inserts the new entry into the photos table by calling the setDescription( ), setLocation( ), and insertNewPhoto( ) methods in the PhotoAlbumBean.java JavaBean.

  • Ends the try/catch block with a finally clause and releases the JDBC connection by calling the release( ) method and releases all resources held by the OrdHttpUploadFormData object by calling its release( ) method.

  • Displays the updated photo album by displaying the title of the page in the HTML header and in its common page header, directing the browser to the main page by calling the PhotoAlbum.jsp file, then displays the header "Photo successfully uploaded into photo album" and the instruction, "Please click on link below or wait for the browser to refresh the page".

  • Displays a link at the bottom of the main page Return to photo album that calls the PhotoAlbum.jsp file.

PhotoAlbumBean.java

This is a JavaBean used by the JSP files to access the database.

The first call to the JavaBean for a request causes it to allocate a JDBC connection from a connection pool. Subsequent calls by the same request reuse the same connection. After completing a request, each JSP file is responsible for calling the JavaBean to release the JDBC connection back to the pool. Each HTTP GET or POST request is assigned its own JDBC connection from the pool to ensure that multiple requests can be serviced concurrently.

These methods are defined:

  • The selectTable( ) method selects all the rows in the photos table, orders them by location, and returns the results in a result set.

  • The selectRowById( ) method selects a specific row from the photos table where the value of id in the where clause is a parameter marker and returns the results in a result set.

  • The fetch( ) method fetches the next row from the result set.

  • The insertNewPhoto( ) method does the following:

    • Uses the OrdHttpUploadFile class to upload the new photograph into the database.

    • Disables auto-commit by calling the setAutoCommit( ) method with an argument of false.

    • Executes a SQL SELECT photos_sequence.nextval statement to get the next value for the value of the id column for the new row to be inserted into the photos table.

    • Executes a SQL INSERT statement to insert a new row in the photos table.

    • Executes a SQL SELECT...FOR UPDATE statement to fetch the initialized full-size and thumbnail image objects from the photos table.

    • Loads the image by calling the loadImage( ) method in the OrdHttpUploadFile class to populate an OrdImage object named image with the full-size image, and sets the properties or attribute values of the image object based on the image contents.

    • Gets the image file format by calling the getContentFormat( ) method and if it is not null, and if the MIME type is BMP, then tries to process the image by calling the process( ) method and calling the getPreferredFormat( ) method to convert it to a MONOCHROME, GIF, or JPEG image format, based on the number of colors in the image.

    • Tries to copy the full-size image and process it to create the thumbnail image by calling the processCopy( ) method in the OrdImage class and populate the OrdImage object named thumb.

    • Executes a SQL UPDATE statement to update the full-size and thumbnail images in the database.

    • Commits the changes.

  • A release( ) method to release the result set and statement objects, and places the JDBC connection back on the free list or stack.

  • Get methods (getId( ), getDescription( ), getLocation( ), getImage( ), and getThumb( )) and the set methods (setId( ), setDescription( ), and setLocation( )) are used to get or set attributes for all attributes or columns.

  • A getConnection( ) private function implements a simple JDBC connection pool.

  • A freeConnection( ) private function releases the JDBC connection back to the pool after completing the request.

  • A getPreferredFormat( ) private function returns the preferred image file format based on the number of bits of color in the BMP image; returns a MONOCHROME image if there are no bits of color, returns JPEG if there are more than 8 bits of color, or returns GIF if there are between 1 and 8 bits of color.

PKbƻPK"+AOEBPS/index.htm4K˴ Index

Index

A  C  D  E  G  I  J  L  M  N  O  P  R  S  T  U  V  X 

A

application development, 2.1
Java class libraries, 2.1.1
Oracle development tools, 2.1.3
PL/SQL Gateway feature, 2.1.2
audio data examples, 9.1

C

C sample applications
ORDImage OCI C, A.1
Code Wizard for the PL/SQL Gateway sample application, A.2
Code Wizard sample application, 4.2
codecs (compression and decompression schemes), 1.3
compression, 1.3
compression formats
audio, 1.3
image, 1.3
video, 1.7.1
compression schemes, 1.3, 1.6.2
content metadata, 6.1

D

data
loading multimedia, 1.8
data formats, 1.6.2
database users
default passwords, B.1
DBA tuning tips, 8
decompression schemes, 1.3
DICOM
extracting metadata, 1.6.4
digital camera images, 6.4.1
downgrading an installed version of Oracle Multimedia, B.5

E

embedded metadata, 6.1
embedding metadata, 1.6.3
exception handling
Java, 2.4.4
PL/SQL, 2.2.5
EXIF standard, 6.4.1
extending Oracle Multimedia
audio default format, 7.2.1.1
document default format, 7.2.2.1
new audio format, 7.2.1.2, 7.2.1.2, 7.2.2.2
new data source, 7.1.1.3
new document format, 7.2.2.2
new image object type, 7.3
new video format, 7.2.3.2, 7.2.3.2
video default format, 7.2.3.1

G

globalization support
image data examples, 9.3.3

I

image data examples, 9.3
globalization support issues, 9.3.3
image file storage standards
EXIF, 6.4.1
IPTC-IIM, 6.4.2
XMP, 6.4.3
image metadata format
defined, 6.4
image watermarking, 1.6.6
installing Oracle Multimedia, B.2
interchange format, 1.6.2
interchanging metadata, 6.4.3
IPTC-IIM standard, 6.4.2

J

Java
client applications, 2.4
configuring your environment, 2.4.1
exception handling, 2.4.4
retrieving media, 2.4.2
uploading media, 2.4.3
Web applications, 2.5
Java class libraries, 2.1.1
Java database connectivity (JDBC), 2.4
Java sample applications
JSP Tag Library Photo Album application, A.4
Oracle Multimedia Java API, A.3
Oracle Multimedia Java Servlet Photo Album, A.3
Oracle Multimedia JSP Photo Album, A.3
Oracle Multimedia JSP Tag Library Photo Album, A.4
JSP Tag Library Photo Album sample application, A.4

L

loading data
multimedia, 1.8
using PL/SQL, 1.8
using SQL*Loader, 1.8
loading media data
Java example, 2.4.3, 2.4.3
lossless compression, 1.6.2
lossy compression, 1.6.2

M

media data examples, 9.2
media delivery components
Java servlet example, 2.5.1.2
JavaServer Pages example, 2.5.1.2
media queries
PL/SQL, 2.2.2
medical imaging, 1.6.4
metadata, 6
embedding, 6.3
extracting metadata, 1.6.3
embedding in XML, 3.1
embedding metadata, 6.6.3
extracting, 1.6.3, 3.1, 6.3
extracting metadata, 6.6.2
information about, 6.7
searching, 3.1
storing, 3.1
XML DB, 6.5, 6.6.3
XML documents, 6.5
metadata examples
creating a table, 6.6.1
embedding metadata, 6.6.3
extracting metadata, 6.6.2

N

news media images, 6.4.2

O

object relational technology, 1.2
Oracle development tools, 2.1.3
Oracle interMedia See Oracle Multimedia
Oracle Multimedia, 1
media data storage model, 1.3
objects types, 1.3
Oracle Multimedia DICOM Java API
Java client applications, 2.4
Oracle Multimedia Java API
Java client applications, 2.4
Oracle Multimedia Java API sample application, 5, A.3
Oracle Multimedia Java Servlet Photo Album sample application, 3.2, A.3
Oracle Multimedia JSP Photo Album sample application, 3.3, A.3
Oracle Multimedia JSP Tag Library Photo Album sample application, A.4
Oracle Multimedia Mid-Tier Java API
Java client applications, 2.4
Oracle Multimedia sample applications
located on Oracle Technology Network, A.4
Oracle Multimedia Servlets and JSP Java API
Java-based Web applications, 2.5
Oracle Technology Network
downloading Oracle Multimedia sample applications, A.4
ORDImage OCI C sample application, A.1
ORDPLUGINS.ORDX_DEFAULT_AUDIO package, 7.2.1.1
ORDPLUGINS.ORDX_DEFAULT_DOC package, 7.2.2.1
ORDPLUGINS.ORDX_DEFAULT_VIDEO package, 7.2.3.1
ORDPLUGINS.ORDX_FILE_SOURCE package, 7.1.1.1
ORDPLUGINS.ORDX_HTTP_SOURCE package, 7.1.1.2

P

packages
ORDPLUGINS.ORDX_DEFAULT_AUDIO, 7.2.1.1
ORDPLUGINS.ORDX_DEFAULT_DOC, 7.2.2.1
ORDPLUGINS.ORDX_DEFAULT_VIDEO, 7.2.3.1
ORDPLUGINS.ORDX_FILE_SOURCE, 7.1.1.1
ORDPLUGINS.ORDX_HTTP_SOURCE, 7.1.1.2
packages or PL/SQL plug-ins, 7.1.1
passwords
installation defaults, B.1
PL/SQL
client applications, 2.2
configuring your environment, 2.2.1
exception handling, 2.2.5
generating HTML output, 2.3
loading data, 1.8
media queries, 2.2.2
retrieving media, 2.2.3, 2.3
uploading media, 2.2.4, 2.3
Web applications, 2.3
PL/SQL Gateway feature, 2.1.2
PL/SQL packages, 2.3
PL/SQL sample applications
Code Wizard for the PL/SQL Gateway, A.2
PL/SQL Web Toolkit Photo Album, A.2
PL/SQL Web Toolkit Photo Album sample application, 3.1, A.2
protocol, 1.6.2

R

related documents, Preface
retrieving media
Oracle Multimedia Servlets and JSP Java API, 2.5.1
PL/SQL, 2.2.3, 2.3

S

sample applications
Code Wizard, 4.2
downloading from Oracle Technology Network, A
Oracle Multimedia directory location, A
Oracle Multimedia Java API, 5
Oracle Multimedia Java Servlet Photo Album, 3.2
Oracle Multimedia JSP Photo Album, 3.3
PL/SQL Web Toolkit Photo Album, 3.1
SQL*Loader
loading data, 1.8

T

technical metadata, 6.1

U

upgrading an Oracle Multimedia installation, B.4
uploading media
Oracle Multimedia Servlets and JSP Java API, 2.5.2
PL/SQL, 2.2.4, 2.3

V

verifying an Oracle Multimedia installation, B.3
video data examples, 9.4

X

XML
representing metadata, 6.5
XMP standard, 6.4.3
PK9K4KPK"+AOEBPS/img/cw14.gifz0GIF87a_{!J9sJ{k֭kkcJ{kƔJkƵތΜέ1c1cֽs1c経1ƜcsscƜέέkΔcckΌƽƭc1sckcƔckcscޭkޭkkޭkkkƔƔΔ֔kk֜k޵kkkkΜΌk֜εεΔcΔckk経kkֵkkֽsR{sssֽZֽksssֽsssssΜssス֜ssss֥ƥkֽֽsΜ!!Δ֜!!JJB991ޥRR|ֽスsֽ֜ュ֭1111ƽsƽs֜s֭֜ƔֵkkkkkckkֵΌεckckc,_H*\ȰÇ#JHŋ3jȱǏ CIɓ(9Xɲ˗0cʜI͛8sɳϟ@ JMF*]ʴӧPJ)իXjʵףKٳ]۷pʝKݻx˷߿ La-ծ≮ǐ#KLa[Z̹ϠCƋYѨS^ͺ5NkDŽʵoݡD j2pፉ>7Boaf |mݿ@[ ۭ <|5(A@f};h(% 7attx[uq\_cvW)vc[; iqE՘(q# (m_^ƒb(#8Ψes`bܹwaT%=韔tmXo^c_ h`d Q\nɖs6ZS*s]Sg[J@я}gC]ꟙ$ZWߐxM'emQ[Ej:'ڞ z٫FW?4_y]ql[Þ6c|8mt_oh.]y&AF8[:c/v7o,Ir8[c 1tW}j &[ׁL|=8Ss ˀmjC *hO:8fp7\>pP|yK6g^6:u=CCv9Н_foZ59龂S~2Cv)kɏB^iff9\J*Dqhۍ;HTn ߽7]vn@=7>}Wm7(q `(m/YǣѯZC6(a;+H2+-Mr˽b52슓/PPKN..Ҳ= ~xC_dF>eb+Ck"y'C`KJpԃe+{na=RQSvsъg "0(jNBBMMa`M j1 C2_"_Sܟ d-=R,%w'sѣ[9;jw+=O&L,z: Y9QrN$p H>f[|ҭǾ(>B"G&9EBh6wFm&:6ySk/3/<'B(5c%{ -hS43s4upu:T;&pRd;n&(1_v #9R%ITW CJ.12QдǩQHz34/Bd;)T}Y2-馨ӕXMpS`MΜey>@B7&5 s3( A3<)pHmh`XcqzuOguaV>-ytZxVyRpYV eG56ۃ`tCh;e `C|'C͌wͯ~[RyWc^KnU;}#L [87d <Ӱh ./0~|橫V21]bctUjn>NTSj|45%V #r!ia Ro)!j'Fc^F󤓜5Oe#GAbbw,~g>T)s !CNk&lڜ^բG7mk{3gApŶW;=Bk9F{A{BJL۴:Pk(w z ^F{Z˵-q :@2ATaokn=3`K7aW fq;tශKp@ .aeK-.q 9+; j  K1A3Q5u,COGIqX|~K ,q/X1 { 0/01I23--ǽ4!=ɋ:AOǾJ',q {z"\ ` Lെ,  P 絹@+a@a{~ T0 l@[K !k a"/"ŻB(/l:̸PG<GŔn %,H`Ƴ +Qll 'y̸'@Lܩ8k鷏 k ɞ~+9 )ɖF 4_+3[a;ɧx ګ\ ;~ @â 򫽚[ʼ ̞l ,;Lػ#\;Oh+ z  \ \[K͑,Ϸ<˥̈ʯʖG'9̤gp{" h~w,!o|n*L+AzuL 0 p>JX_ {j^>! ǜ>ǡp ~Ĥ>JX惮cm gNǜoNF _! @F PV<1l1=Ws! Pop  >lH ʼn[ُt! 0/S"؉U 2t,L$I$ p)R8RA%MDRJ-]SL5męN9]5+# I 1ǧ$C"Ȩ%VXe͞EKgϴ9Z(2!Lj吝|GFm?YkoB@(R6jEVd {#nLYlڵmKXST-$li\BUz\'xvݽ?۱]T,r$9HjANNI0@o<E)@Blة8 1%p@G$Ē mN dL1Fg Eo1GmqG2țzH#,H$dt2J) J*2KԲK/t˱4QED3M kEWhPM;Mq|T8qOCōvи@%$ '(m,?֊ OB4+i T.8<̤zh/ jeM+ժ S5(YZl.Nbf*BUYsd&b-LbLH[ĺ5[XP+p\LJ^dK̢❺bL܁?ޱ`0<Ϩy 5cOL wb1~*6wQv-a^d">^m[.#/ ?3Bfo*&f\Pc?D>04S˰$ u-Ҹqlh'Gq/ǜ 3|;C']KG]Sg[W"scSrӁW ܇Y|eXx4ݒgH%ט'Q CGt'_ fM ?/\U^c%n$?y52ƅ* x"-B11]eZB/kir,k'ܝI /hW̘E3܋4 ED0^(ZвZ Di:6D6,$@ v^3# 4ܕ+3qyE$ Є6Z8l ᶢåA;#H12=(Q#"XffI{.-\?zþr /x,?dڼЙM1z+3(ar(Z$꤇vC:[2Pb: SP,6 NYb0tFd plYxZG-N-L_  \TFղ+#W"֚%IfU B >1k[Zn; SF{B%b7f4"U|,%: l&FǔiETYK`V:ldsuR6͊e1V+73W ̦#AUղh>R6|E(䖖O1euܶrcWlGFv?*^նֱtR]Elm Wl~ ت ҽO,U7kdLWVp)i*T$ .a\0j=%FJtBDXl e/nh+Ju^X\z!ҹq a{GVm25 )EI2 o{Ě+Q3 2 @,{ɦPsuJΘW%6П*_݋KtRG!_ɷ Kt$buJїv RsHmOZR/13_DfiVuӨ_mɣM4NBhIXq;G;;ҋΨ`>%Sai 1ũ PU{Ӻw#`A" GV\x+d "8u^=68s Vpiz8 8튤l'o!wE&ބ۽kkz+?3}!RcɆƕTz*-ѩukFq,#k (ѵC.N#toI2xmATLC|St~1vJt1vp1wjխ{a7yy']uw QtEh Ő(_Fѳ+$+H}i "ͅA%8+r%OYB[,R!9(sT S/C,9-T>k?,>?1@|1?;>t@J@? +"rbB 7Rʱ&B }Gd_@) t:!™X*+D**(Ҿ\)(CC9ÌzQ/C()^R)RðX =hDǀC$A**;:zZs뻶XDШ$;ĮBÕ`Q"S #B/[ B.RR@碭/#.eĕ;R>ƫ Ji8-".QFF9ē8lLy>RG"Ȣb9J9,.'3*#K 0h)1;KHr1S2J*C2d*6x;۪vS<ÝP45z4F^KoS `+:6K#H#1m۷C4Oc5P 2+JPKB؈bG 9{LWYgJ!J+[Jk@ʬ8,-zS̿{7Bs̡LO9+2\#I떝!bLI8y$_)<ѤSa<7L5t[sʛ)̳==Ľ/e8K컰ԸdI]"S#34<݌DyQ{JSژUYzATB|!@64@E3CLB/6\AnėO?03D@K[> @@AH{PLQ>4ZyŜ&e ^4!lEDN2R8$ TEWrBhjtR$).% -R!0]1%-3US3U;6B6ܑ97STiA}\ >[\TH%1]ȸ͚u]Z=٥]ׁ!\ѥޥ8:TPXRU^hvi[ Z2@m!^p-Zl;VB8} gYiE`$ uߠߟ A  |ٯڪ~Ǿxd岿z|} xWIa̠6-Ȇ{`̠߂HYq8i^h&jiFVwn$Nj.Fꪶ.FjiGxGFV. ^ (B빦뺶.gN^|fklVȐk 8plȶ.삸l6B0=8hlzKD3mDmH@7xN!0mk@@AȁҦ熃܆ֆAރ0oo ` wN(P}6fn@  : 𹰎8pVxg{ uށֶ= _m^ng8p}6rn!1pE֮uv5pg%x(yduy0v^vwg~u2 `vlwg6os 3W xnm7hu7ghwzu&u&uL'|Ggo~'nN{Fg~Uw7xgmȂ,{2(v/|)0|gg)+h|(H|v{f0qx#8n8ytgoWy(`782vvnu6o38og)z~}zK_t!rogOqHup~o6px{vnւ-|. yW|(p/0pς/}GL`&(ȣ!!:lhD2f1RD!ǂ. FJcFlÇw'РB-jJm4@g@E?Lpm]v G ףlœO`>nYN8O_˅V@g 0g nHDA k(wFхp8!8r5X B] " P /cT'آiŒ*x׎ `%$ /|S~1Xy%Yj%YZ!O2@ `ÃAi8N~d@}r8(jSO(~(J:)jpƅ(ll:*vr*((j+k iqZ+X,:,`@Z{ʊ-`;.;{jhKn-j/ <0|0G0/KKM|1kq;1!<2%|2)2-21<|393=394E}4I+ȭ94QK=5U[}5Yk5]{5a=6e}6i6m6q;PK͇0z0PK"+AOEBPS/img/cw1.gif,GIF87a{!R9sJ{kc!JJ{kތ眭έ1c1cֽs1c経1csscƜƽƭc1sckc֜kkޭkkƔkޭkks޵kkΔkޔֵkkޭk֜k֜ޜ޵kckƭkkkssֽZֽֽ޽sscss֜ssssss֭ss祵֜s|R{ksssスֽΔ!!֜!!sJJB991֜sュޥRRֽ֜sss罽ssks֜sss1sc֭s罭1罌s眭s֜֜cƜ֭֜1ƜsΔֵkk経Όkckkkc֔kcΔcεckkcֵƔΌεcέkc,H*\ȰÇ#JHŋ3jȱǏ CIɓ()Xɲ˗0cʜI͛8sɳϟ@ JLF*]ʴӧPJ)իXjʵףKٳY۷pʝKݻx˷߿ La+^̸ǐ#KL9r++k̹ϠC,ӨS^3i[eڶ99=wp}KނqsVp췯c/=`r6;@8?.M$1P8l !z\4So_]}7l#oV} !eb( Gyupy]3F]z-חȟ]#Gd\Pp45%|(b\!x; b[:)UZލ2f?If:v Oyؔ{8z%]%'[a2F[C,Y×oHXǦ[irY6h_h?t ٞwC̪9bu tȚMږX^۪smhoY!z~ m$Q|szm:J zDg|UzѦW޾"z_ d'tYco܎㸈q|9*/ #>9r\6)mEzlql~ڦb@H>;"usi: (N6XAbp9dМ>{pЍx|q v w3f6 u߼59[&xoV,5))~CNBr"![ [*)YڊN)5cMC/f#Ab1ᔚwIأ 5<<K-(p y%|;R%:i{s C!ЫuW.8̒ł3;_09z6{ˁarCOWyj! 4w,[YF`ڵdN̔'^K7QE.z˂N;茰Uƃ ~9 s #qJiĹ(du%DD0vT걭UI! d'Ɉ35]DVݠi-q$L v+:c NFp H|$s jFizkc9;@QҔo朱;hK ~ܥ=zdq[3%f12J:0PP H|1\ NOco#_mpaYPڤMB@ W~CJ,:E)sXrOhLsTdPK|#jjJ&iJ!D}RcM5iT8& ey A 'o sF!<@+,bxXau=U j9L "kw c1,qdK)qp}yV 9uF/@Aԉg3ش]_C&oq6RUͯ~߻($̣vK;X.}'LaFΰEs { Np{C`qm%iﴂӥ6F;UuCX4@ƎdPɄK܊d35*b{f'8fdaz4Oìu,=mw8iQ{LΧ(->5[^4;D ij_Eˆ{6ߙRn5a7bEaZDZ.C홞v1WtUXo< @LHjQ3I'֡A{ LjFX̮tʪPAZVU3`, ٧a6+WBmc-H6EU[;=#}kM\#>pۻx^\[ϸYԢ{ 9O8.(? SIY9gNۼ%2w@нH_Jѓ;'Kԧ.SXճ|^M/;vp;U.])tcFKbXxpJЁ oq9H#5,қ  _><L`Kj'{;o @6@_}C@7S@@('>O~ﯡ}l@ې}' 'y-{g~y{ `q s{Š Gzp g䷀wi{ׂhсs|#hxg*x k Fh<8cJ%hyq0wM/~'xq@gwT]w)ygy7Py{\H}5x}x0zG5(x 7pXXwI؉Z}WljX5G.؊'NJ X0G؋d8XxȘʸ،8XxؘڸHq8w_xNj踎Ox'8D'xiaR79`ayJ?! yYxyؑ 8$y&y㘒*,ْ0+G {+5ؓ=@w@H,q/{h z0F+h~IL90/ZIXP ΁3$@Jq/w[<a5Дw`|0F |xk b b g+zx 0 uِGyȗI @ G藃W:ι9P_əx|Дjxl` /y/ `)  ig9yg *gx e(\NHȐ ,19rJ y>y{t/J 0 ,liԹ@+1ɚ9y;q)> ~sG} :~%` -N{|ʟx(-Z6ڢgl kPs ,6ڦ&iУ IE}G:I@`X'L }I^zW 8IejZ |z){ pf)湪~:ij@h*!P|b ڜy6sڭ_9 x 0JIשxz/ x}0 ª+qꨘzy ˚ 8ɟ c JFY^ v:y A0ʮi) ׫Z5ArI}ɠ#x~{ +|Rz=q/Y } q)# YkYjl9j9qi 8 u~ :|+#PyvؠIwG Cl';XS[Xz?RIVkڕ &fy[ᖫɘkFqI9qLʙ,QZkɚ飬CJD1[AkٹI :㪞칯I+W]ڟQJU*x~膄G W, w o+*}1: K7 9*<ʿ@aH:yʤNOXWY0I  XJ7AwPZ;-sZw٢~ *ûj5l}9;:*-a~xǒzۨ.Ů JjjJƿ D.az/ >{ǺG~ܾʮ“7\۝ʲK ۛtL+kħš\| ʼP K (+Qٲ +[êGH<~uEkG}H|{|xNr̵쵇 0egim;)7<5hx{};@ wҁ۠t+x/|W'"}sԜLKzRmwT]rwX wZՑ^]g7d=vf}ajulYp=`=ה[v}xך|ݹ~נ؂=]ئ}jrq)>QK5!۫)^12!3Ѷ.z̎jQˆL۩ӫ|/:1>Qwp<ۭk­y0q/k61r.1۾ Mк:}y gY;[B$KX '.*HImr =٣ijxfNq^嬫UYβ x.KYry=v Prjhč95`X缝Ρ ݢћۻ /^܉mϻR;=I9>~Þz=ޣޣ~>^{pƪ+Kp۽gѧ}= i}_xP.>®;J i)}]ަ.pn6Ъ  #}J%+2ɮxO͢YJo C_LMNV~JaiۣZ/\Jm9?O?)O߉qڝ]*?p{&␩"P[i^A_+_}_q YkKy y,n8d¾?\}YA[{Zi o`ZVgiͿտΝhoj:[>? ʃoˆ^qq@@ @B >HGs ^ĘQF=~RH%M.LJ-]SL5SęSN=}xPEE:ThRM>uiTU^:rjV]~Xe{VZmuWܮpśר]}`…&4X⋂?qdʕNYW̛=hW;t8oܔt ,@dPtdG:-YrD?p|>zxG7'_bAGԬa1wi}9Y\y T$xc!>* >{h<8#CbA"O2`?* q#>BQ[zBCϿ0 <$@D9A#_@(2 1"[|K&8$HH"׀r-ґ[&D"4`Q %\<H4hӢ-լa,SFhBP-H?xP>c8TQ =ب!B}rHcD2,EWU5~Q$4>M=W8cI=(<W]5ϕiѱ 8p ;40!OٳWyӐO"l$ۀS $xEd[=ZâMu_w@hQ~ >ܒ;\.|?*b ۼ#Hׁ^@e'z AM7;dgS;/neP}7RH:i@3=U~0KxΠ-e&o=M(mg<qSzV .ֵjې\q9iV4P'TrBW# :!#lT4H'}A2xͲI! {_P|~dB䄠VlO'=%K?]׹]Vkf߳3yJ^ @(|!8AH1 &ck88By%nxS70,&dIqЅ7D RR;#ēMEb%40< ~C)H@2b") $Y"F'>!2ІrLՌDCB梌 cIX1&6vԣxqpC*ґT3jTRt(gR]<}_z$NOB u($J]B$G 0#y[:*WJVL[խrEkSǝZI֠LYI֧yl[$ɤ (nђ(%wҐ >h:ƹj#ƪƪr]LiPGC(PF0w*&q 23g9К9kgj4ă@ӇjTa(Ӂfd)hQ)38-f#C&BAo@u9m[3㜖US|Bwy{B+BD"t`R(mupIRefw6,4AO{[t<$=0eȓ=1LzmRj0JG}!^fYYZd{`#-n[7$\K#Mp?]eŮU]doI^dEFΛ^Bd/J_f/Kޛ_`]/ v0u!N¸].oExw$(nra {6ƙ"sC )"($J nV'D,`JYnX샸$;8*-MA6GH%kI *%c~A?Y<)NVpRY a&1zz,.]αj09H w"u] Ӗ/XtoU(;jo b]#Ηoҙ6pj)A A9c֢բ[ɍQ"ުV<㪬E*N;cR},dv݈zn{_FOmǩ@vtɰjBē(K ;8l,LG x%c3A 4r 0[*̥q059ij[x;NxjlɓqsDKsNwfgGSON# Z_e|.!s?V6PGَ̃&ʝ5Ija夭oQ߭ŚUb=[  B8kڜWPV4™Bp&3y"!'X/`˿yу3TKNPsʡJ6+>MYҚ@ML:}!W/ơ4*=U DLZ(MSWrr3<#1= yR'Gs)bcJڿy@>sq:+5C4p<,@B< 쉐KA:7r6caA)sҩ1R4:[V(V>)ɾ6ë,A2$Y6j{A@!InKo󫾑XsQ<ê:'47+Y3$';<`+x77}ӓ')-MI:X(ģ( 8%Y5y;~ڝdëp8Y[c 8g4L ;j<n/kGq̸o4dLƞ@!B0uɹvw܉ CGG.F0=8*1{:T%鳓<+ NF;IȐ;9k?$bcA2{Jl9 RL<"0#3׫ۦ(< "ʉY=3OL3 <᳖#193M0s.T-F>0tF{LLbt.c4f*l ,?\ K9ʡǜ(JJT$d5|5~($AZ(˴& B!d8,$YA—ZB'<)ы¿~5>E|Nt vlel.t iQ(ǚ5# !%#!#UR`&U' J) ),͠*R/E4/S#20ES;5e5u]k8u8S;9!-=>GzD@G= }GD-RAFe<ѩsI뺻܈u$PTT<ItA(2esKt񐓕UH<ʤ\hJY2s3h+<Q] A4KTKBJԾA4NhPpbitH"5aP+W6A%sVHl\\V5H<@m(:ymh*gp#W 5٬M πs A?n>xxm d|/Wg_hy6_@EyEGitWoXhPgwgphzO'vj?k&7zW{&wWne乯D{٭Ƃ'7GWgwLJȗɧʷ };PKHO&,,PK"+AOEBPS/img/cw16.gifBGIF87a{!R9sJ{kֵkkcJsƵJkƔֽεέ1c1cֽs1cֵ1ƜcsscƜέέkΔccΌkƽƭc1kcƔckcscޭkޭkkޭkkޭkksƔƔkޭk޵kƵkΌƵ֜޵εΔcΔc絵k経R{ss֜֜֜Zkssssֽssֽsssֽsssssss|֜sss֜sֽ֜ƜΔ!!֜)!!!JJB991RRֽֽֽ{sֽs֜|sssssssssssֽ֭11֜1sƭs1Ɯ罌罭֭ƵkkkkckƔkkΌεckckc,H*\ȰÇ#JHŋ3jȱǏ CIɓ(IXɲ˗0cʜI͛8sɳϟ@ JNF*]ʴӧPJ*)իXjʵף] KٳhӪ]˶۷pʝKݻx˷/ZVYLÈ+^̘1-KL˘3},PϠCM:3gKc֮Qo5ήvn»mV[!yaSN0-4|{`կ@{Y lp>;M{5c ᱇}iU`gysWr}Ń@X)(@!vZj~];Hޱ7u!rks []֗b}mV!V#Y;ٗg%酨߉hi" (dwW.6bdi+JI?4x&bYjG#'jne)q8b0HzYJ*Y;qKmm&Fni|,, >8tq=kcA^ vx<%ρ⊭r<y7h5,uߵ.[~_CCvt{^9PWRg{n5a oͬMg>o쨘MQyŸ#I6/D* ))ЂMr'ڻZYɇ{E_Z%ʇdkHkȗi }Aِ넯 rWl]C (X@T}wTWe2q'##)Շ$vQq$"eklaL8t< ؕ>Ô5. ic¨n4*/ .HRk ]JMp~ 9@ iK_yr}6[G*WkdV<*cb7˹vxN+fߑV{ޞҬ@YPÌAmӆ ir4b5t|xKW^3wIdE (ͯ[S;7 LԷN3}, [¡07Ǒ%ҁ!]#N_4bRO/[L㶰gdHidÜZ3Y5B10 3<;=5R8R~x,@tzIu,d3hάEcoΑ@ǥ2òb!m+OZHGpaQ,˛Q_FW *+-Aa9_DSDui.Ԣ$u.(4F n*4L]]ΦL&25ky#W @䒣h[2nŶutfM~[57ϩgZf;|>xg8'Nq<+ϸ7s%GN&OW.gN8Ϲw.@gHyѓ;KԧNDXϺ}r{`wNvwhOϮlx~$:!r Ȼy62'~?῱r@~%FOhC) }Loy7IUn?>o~%ᏯK !dR|'&wg+>PD׳7Aͣ@ K0|%7K%xz} 7y{yxx'} ȀG WyG~,y%7ׁǃ'+(-z7g zhyBh1(* ,.Xu 7}ِxyŗxa(-z&x4z[bxzwc Ѕ_e8 g8{ py oЀ)z8qG-yW|'yt/xZ8}gg)- Xh88}芤xP|x|xX(X(xɨu(7wx71vh|xX}w|x}h|HxX}{y( }HXzo8iHɎ8z$ ɑ(9u>7yl؉3 69א߀yW.a هXHFWx'ى*@T ZɆ_-ٕGxWه bd)nx_XtȗYbzy8nٓw.ӧyKx`(yl~Ǚ+)DY9)yLɚ!(כ 9٘ɘ)9)9y7}y0@|P|xIhNIoz7gx숝։!؝뙝 wYəXٜr(,Q iȟȝ@gɠ(퉟\9z"ډ {wzG DxCi[z*zǣKȉ)oz)).zx($~@ ș@ʊ:'ו~Iy ;Rz1:]W:}uڦ$ W-x@zy {:~zY sIrw*~)x/Q!xǩ:r뗦"7grڪ/ ZG~ګwǫnZeb+ʺڬ:Zzؚںڭ:zqzG躮 ^|:L'zCg<5;.'{wIg z;B{[aT ;&${Da(?,`!0;_4{1a8B&rI;>a `r۸7Q/5A 7 Iq6a GEkjNp |ıf^Ώm^~" ³.PLX-N\1N~ N꣎,+i'#GW!jd='']vn!WC)-?1Rq;\޺o6K;!?Ow68!=A/w  Zfl`G< ЌY]ۿrNjè.ϾdL૶Hx#tw-ͣpϕ<6+ZLʤ̌,];;Xx\nHb -yr{uLݺufyX-fm=xtTkz]-okO;MҀܐO ٗ;퍸knQ;]U ߼}W/˂L_{g:|X[w0Nf쾎N\~tƈNns*>`@@ DPB >QD-^ĘQClhB""I"dJ-]SL =~8C "jETRMatUTU^V]~ QkXe͞EcZmݾ;\u2{W^}Xy Faō?vdʕYJY憘9shҥ6Zu_ԫ]~s2ڵmƝ[n޽}\paK9q˙s sө/Lu۹̮w y:#=huћF R&}@I#p Pɠ|? (;J* =2:;$Fz пc$M>Iq [|Ld@MR9q1ũ>pdH63}Т"1~eW7Sucv~ۧg8npy/%=pPT%2Bh6;Eui0YxĩBR!~v׀=$NԩyNޱϗ'Om놙Dy`64ɱAdYbesɳV%rZ\"ڜP#|W/.-XCAh5&Ɗf\ t O   J )P/'afd+o9G<[Dȇ.xMŊڨOwGLcy"؃,'\MVm0O&80H3 'κuw}B_&C p&t$<ǒH2߂<>!) /Nh-@akbP/D2y}eZ+3u 9N"Jdj$r5<̓iEx }<0 K P5o)^$Dο[.M&t 伙Plb@fZi**dg)E{.2t,A)/ Xx)NXfBApjJ=','(BC |󨦃B⧍µʗ | J<)lIfA'I(89)?d$6.l-R.)ѭd!*L\p-5uN`rRYgz*٥,Ү*H",]-j,D._,z[4]+f# --E0a-4ƑF^qC/1&C0a@`1x.0-,0 /|3Wd110G+03$20iS0{I3)Iz XHGT+H:SE [ 6,0iHw$,bQ|@K=;HS> $a>;Ȅ4q4+)J8/3)5d4|3K,5KKT0ıTIT3\˖*{ZKTSS˨I-ò o~:EPJt+W)6q-_̓!McA>8lxz68iiLYcݬdzD,8hKS6>LJs6ޔIIE6]SLٶ[6T3t% (kC:Al A;Dá; :j;e<4>{iϷ˟;CS E>JSKc K fYEeT9% z,KpՊUNSDlRCX`a`*HI'*4Q_29gJJVÏpE E Œ,wM0LR59mԯzȹ:-- gH-|@@iXUXX*H`XPUTe÷tITA Nb u >XU㲮لaRP$%`؝j*[ӵj؋!XE^MY4{USI6!Ubi% !~b#^JN%Q]Ob C}l#AaJѲЏkR R[ Pl;,{yZ9< c<.PH[_W0F\sa9ƸQdZ@\Me/UfeWe+[^V~XA OMB[^/9ѪCO-.ƴ;b(bn r~p>$m!?`gkw hgSgZ̻|痰~h<聦ӂ6h8Efsn}vhCR.i=鑶6i9Bv闆阶X高2ըiQV "6 #0j *̏iag>zYH+旜 K  AhHNI} 8Zt?l~ ބg,h`Tyeg7-iDf՘kfF=Eֿl)U V \f'TÌ@4Þ4\-BzFkuIgɩ3- ֶ>-TVFznjF1-hl)>GMlke7jN=Xn=m:d\0tYItIj[Nli_rBHy ӆ$;K̜ٲk^o[mQN2|F|oἠľjBj3I1qӒS9KQ[Q" %) O m0 !xNevr+q,'017-O3W/?t/tBCGtQE?Fw,QH?ItKohFG2O⾛!O_@6P7K  Kn@%Ub epԊu\G_?M}4ιҍgah&ف&^uO5lkG Vldv3$pvpX+ 'k(u"ن9`)m'mU9d)"C1xRR7xG´BxDH"iMX/ e5:RCj(m`mOR:x.dxuxbx;c]2/b+«d)F EP4/Dwnc /cSD.BG>zl*..RKz7u7zZtzMzegz{Q*tF w2G><65mBYɝ8 0x;Ff!H3Y}DG %n0/d;*1Yk'}ُڿJw܌?I+$2MLrU~}O9ԍ33;Z2RJ$K}qW5IIQ"iMTEР@Uj"J.64h2Pl㢑\^9A -IL!m(D'fl5B,A'ឤv`ۼ\F ǝ{9:_ۚI+?jfJG/ Mj5XVDY-^@|w||̗ȁ|aDٷЃmH!%`!֔CV~!η_:Xa|&Jdm8D$~(ZQyhH-+巤cE&d҃B&)ޕK:#8怡xۏ[#3 Wz}Ԟ :(zP!(:(U : zU:*Vj*(a'#Yy+UV뢮;,{,Z%:,JKZ{-jhdhv}hR^I*b V۬V".^CRVgf+~F+pU)L*qm$Rv񵶽P*Wʼ*2z"8KE 7b"沟TC&Tt/$ߣ(c=׀} Χ,:Q%{*iDT?F.]wJ8 d~ M3py[#"u"XYE!4R6Ƒ$r4d(8%"$cVƬ1D鈢H._"2ǰ :)J#7E=*$M2ɑh)G9"86d$,ga HD5`%QVwN"0RpYp.8IN*ɔ3(7J5v&5mР\>-{sJO~T4wcʉMgZSH7NEf.{tԕ48u\h ]% jZSJC!bvyЭRBQ跒+@G]3T]VArNˑ+ISԁJ+0?DR$7i@sfd%"N O&&M%bT5Lc,*U<+1M C?Hqf) a4Zn:5MPz[&>_).&V4rg - DrϴufJT!q Eٖ 1YD™`ca R%2f`Ba8Y : xA|(#K" \3/61s\+>1!De2oN~򧪕m"-sQպM36yde2,dNduuC2׻yiWQ,rE4jyӛլEHMʇKd` 8Ã0#Kp)Np$J@(iOZߪ-43+,0ך>* }RQ@ޤ!HFٜɲg-m.׺1'&:Im&49ݓbtѱ&<׉gosvrUءow[pg<ǩj` KR'?lzw3<oHKㅉ"еofq$L iWh;چ<<(Z/O@Q\Y7Wg0-:ғ~+N7.ۊT:esں.F}f?;ekl{]t{7\|+Z?<Վ3^:#QG8 |/(6X#P6 S1 2zU_ @{^oB<_XKv>=*~G8rЅ/t7AJW4SZԔ~w(9P*<1E0.@$<}ZɘJ5 LY^_iJ//EAP.Nd BאI1ذ˜ٸ լ٬`B%8%TNeH%U^aVRf Nn^m%UZe*ꍣX.U-h%SJe\ޞ!"Ng\<]"Tr\! H AJu =eH#^_- UFB4QfVeW:2_ Ulԍ|Y N2 Yr uYN OH`kVg_Φ-f#b ~$XfSZΎPB'ѥngVJ!6&m6"dЮ'*R"+D,e,ib2%-)Z]ّ,-&}(D:=#Cfm+~++ƫ+֫+櫾++kOlb.,6* DN,Jf,V,^,~jr6,Ȟ,lXʶ*,,֬,`¬,˂,l>lV` !lntZm†ٮJ-b ZJm-[2J- D,@ @"n(..@^nH`.R.UVA AAHA ,n@V@ nOr.zn An.ƫb&@ kA @:nH.bU^Dno E  ΫX/>p@-To0op4T06nXT@p@040R 7p '1ע / Sm6p<@vkW0 gE|pW@"q.쎱o 31p0 ?10+@ +񺲱%1 1 2( 1FN@\0$ h,2@2 .0r/2 3s @/".( `xs[0n2f678 4=o;ױ$ 42Vr1d26ǁ86ۀ63*.+r/'o0@-@I Ts 5LK߲L2Ax43,trSsSW5@x4" [UGuh<trWu5d  rXdD'+p$g"[50t+SWt7kO2SuWGsnH+2[/2gr4JoikKW344MtR kAn?A0A86p 7>Xwpk h[u"poo/qo(@]scv@LBcew[B42@5b' r_۱R+p/vr7 ,qbxgvn.rikq+ \0+j8s \x6lj+t8\c !7vkwL#7hV/&vO7rwAnxsu'yvV@^}GyaG%ۀo L#8\/@7w{ |838kA3_1No'o A:kvJ5,4icVh81]u(GA 臾{L պ+k>*>Ԯ>>[V>k. ?k+Cu?m+?2_?={ CJkfOq(RNogܵ??@8`A&TaC!F8bE1fԸcGA9dI'7;PK~=BBPK"+AOEBPS/img/view_album.gif[2GIF87a4|~~;=;zr(dWT-n6wybrO % 'L I$+'2/Xume:<=J+(OH@g;6lIAqKZnXCiXxfyeZPO9.JMq !T"R 4'UUDSKZugLPF%8H0SZdi{{vnZ`f5+ ջ-( P:H47*wȫfgtϧ'&(ľҐ4͹ؿʺޖʌ((8,,-FRfGXfriws[uH8NXt#5q*&(#wUrĬh`owMzxnv\+K&F˩ȈF#W=wQFg2K5)V(uO9ZSQvy;da^sxˍQyY8|lku҆rnnHKYTh|o]vsxțrxM/IcWRWj6X9RYYbP)TxxhOexxp9]E^8aJ|ŋgڵI4fvYx3yZ BLז7K`:=qs?9QN ^ONPQ 9`uNzv7UhY|X 0CmWD 4fD|8 @:C Z@dQI$ZO‚@Ͱl٤wLT66D,% U@D";P4X&P ysi~ބMdPoNk}2lZe>av+[e̺Ph * ;<amģ8yw%N\zSO)E Ա+IiU*ЦN & <{<\BepnKqV6e^P~Ȃo}}Ӫ M9(Tmw(PtBCT4HDae&=q8U0^ 9tURDD|~WԇM0+ZrOD@<*O< PsMlψv Ue8Yr_Yۥ:r3$jЕD~I\m^jID=;Zu5xSѰ r >FwN 'ɊGE AiuO6*89s\ǩ3Nw`O^@q;poRlb > D wS@$mXM (< ]3:s8)^*azB@gz"acR,*L؉Ṛhb1#tR= +Q75+&oU=F pCdzw0GOwqF IyʧLNcp2A$Ꮑܮ&'? GX2PN고RFF466БA)k"ɓ==A>M='P8/A y`fMӝn0BýMzf' hOΉn‚6)~ OH$GyamHIrX&J{K/mKޒY"q'!Nv!We 1M:nN> דDj&I ?`:/Q)'<ߢSPaJ(p#O©6b$TiUAQAӨ!7LfmW>u0K+OE砻SBW}rPJ:)ጭ,3jޤ>X({QPڴZWUgN @/j&Fea DxN͔?`` p3;4[`HV/y^fE؁+O;5bkYļ1UJK;*+ņ*ŊzkҴf`)*ݜ{N-!'%G1% ɤIYlRZ,m>oux脽3 oe('Jf! (*;{|~,<ك)[sL&q~|mժ_eCCŜJ] r)D98s:l|WcS% `]58X3 <5fPL#N$2شe2h9ubDG65;ф2̠Tֹ(Qz޻j2:!bͭY|nOfO3M`ő;v9}r{rtQ dd`AB[L y: ojڔ0h*Q82,Ky;[Aީ ]Bp:q…cp[Z⁈썮D?M334's3gNInqUU\L6_u:kN++F _y\@5IqsgQxoyӣW47*Ou =K?kIS}t-R3b~fGuKn͏Z (H+SeT,hdE89AOŊpWs}!-}nhSUml-_V줗b%+]87YO/3Yd@Qj1l3tN+ E$,J<##&WT.F%%`IWwPYVuWzzVfÁJn=*=Qw8_ ]wȧ;hQ1{w?zutIXv" "NM-b$Zr@w, 2[AY3\0HyLUwg3iZHN/Xrȅubsw6? G2vg R%6;/!oo^T3IU-D@q4BÅrb:HJل1LfoaM,@I"(-Ëm*N`-~8;Xo6#%4,"l0EȤ Xw],R@#2r@(sAhgrhg2cDŽ1S*!ChI'ecyZp _?k m0U{W+/81/X+7*Ud+;J]]q{d?4p R8=1P @R FJѪF۱ặJ7ʪ/ʮjXe۪ʶk˹cQz۪ +|qmwJ=k<l l@MOf[^ u'ۻs[Tg;J黼`mڳ-Xb]Yʑfݢhj,u1#|o}ՊSa$BqDf?q*שQ1 2GC5=ɡz3u \U2 5nٞ7֑frmUlTmm+еڱM}۸z!a5ۻm4P2!@rM]2qa% MCCģۛ5 Jۍ=]&R"s xM=ր-~=2>-E5"a]ޛDStC1`}-a㎂\ 3>N6MPF EPH`b>d^d^{ܝ|ӈN0t^v~xwjOl%ӄ^~舞芾?->^θdΡX>^ꨞʟꬎN^nΜ^^Þ̮6^מ>!^nR>^~?_ _N9T"$_~(*.0>46:<@B?^FHLNRT_W~XZ^`o=dof@ F6,w'tr?4ӚA!@WQfAWmV/Jd K1EAb<%._}!j-F!o?"+wɘ')ی?CF^b[/V]แ" +/3.A#+$p-Kcp?"4 e6k#=n:,9y~,G="D2*=hJ,*򸨌ʫe+":ҵ$˘* BTJhT*N,sMʼ1+ER{IB.߄ P6113p3GDaH+?sR7\3NQ:%gUHZoŕM5oDTG`4޶[.8@YY) ̺~k/Y<H;P\m\I/4Vm}-6^<SOA6kL vYsVX(7H=c R^㭘<8M Qdd0L@ lىEC i95TI fwƠ+V<^he;jkePr9ŕCz 3fqXIۆ;n۬J*uS>/mG>'|G?}ه?~_}/'@\Y< $Z a@"a!h) `FaIʀyO|S,@ A|,5AL`gE5A |eFqiK/2Q e#P0n& 4 %y5S g6a6F8 b&8%  0| ܹ$d}Iz8P{B43|PfrYF#J~ԭ=[Q\Βj"H(ҳŬq$w "p DT±$"PAC7N#̠F ̠4%#8 td"5Yu۰-g״,m+6׹}b]D0WL%kKF,!4l( dLSA@OЄ&X J(fd vҖ3FH8w"(3b !wKjG A 6+\˼ح/ԳTd aB* 4ao+J'd34k+h8P$$Ow*!䱛CA FpmZb!@qK"-~s H;7s Ez|uYpЃm5z 38 4[Qg8!@F[ 3 B%,1wV >@<&a<7":bF( ]rѡ2jۢ~X?Dx mG@0"(RDBu4 3"hX(& ]稄 40@B@5C`|vЩCF0yA g#i@v!. k`b^11ATڢY2sbTUxx#.q ч]O;$dfulCۦ<-t y!4_H%͹ێp60؀m6M:A ,D&Rk :7ݺ!cv7׭S(W%)N RDQ>!. A,u08!$B/0B#k»?#8* i Ļ#+kjTX/e:'0S$=C34p3 Hx[Л6:6&)gj&3R/:PP[LkA#O%R>MSQ"87B@>X.DC8\11_\*>)cT+:)؂+9 ZhD&&`53h,eZ2C6e<{.((T>V =؃>@>H=EdI"IbE#$b,(I77=FZZ-kT/)k3P# ذ2< ȣ 'm:Gt 4Xx:<|KN&?{{:@oo/,PP&fHҷ}}:DO4󱊚X,2yl(PɕYd>XC@\!E\I<TI> Wh$dP2 l=r&\CCGPLt<5H$@-τཟi󲁝 t0QpI3H o|)3е:3*`cNt< 't̠䣅P!=FKt&hbb)H70)SzЁ[$ E mZPE-T܃UQTWFVHh,mBm 94'c A@!zuI yWy5==JJ TMۂe[PLdh)!p,Q儠'/%8D*A˶أ!PUAIU X FPٵLHֆZQtSk5,3Uĭ!5۳ױm[>J,5Q,.8.X}ہ}[ WEWi23#<#؀d+A#d@ ̠$ ЀPǟ Ѐr&@ YNx5Vo^a]o]`7KZk)(0ut?D[J &M@p߳  [.N/&X=K֝ h,NDzh5K'@pC%}S,,Ҝ] a`;a Եҝp`U]a}ڭP\ų" )S5b!,-([,^5=,Ђ=P3-fa`6f5 0[Z;  J3;Nj~/zu9"`<ր ` 6!ܩi& -ϟG=zå`k*baTrZ"`L^15̵S/R1L Wb6f]>8>f-Ѓh`&b&"8 1&ߌ({,;bcU Ȁ7;-_[Ъ=NdXhp~glY`d%G p&dP.&l)R2L3A!ނ3ڂi朶.fN9F\ko_mӀC" -z52ہ%@oCN~ީiYjg : =zF]̊hk&h5ፄlV)@E+,nA(& fւ͆ho.m֖W=o`/_3i/<@7b#7vB5)gHh}h6gHVXYk Vg l> Q%11^Bmp?p043i&цfiapVB dN H:E2wj ($;-sSqށsD2q5t7kdOh)jI  A:_E\Ʋ5dNNV .1*OL.8DrFK8hdׂs8opҞ:.Al_ʬ|pt=8nr'bp*tqnV~&jbϟg"PG|I3h/,`-vuR>#Uԫ%?^gAjaxw88O~p8igiiW3N6C:VcM$qOw# !')M&ֲxg]<$h=-ajbgNZ!TT0/38lV y'|| jM(!y4G|@B:XEo$ `W4 !*-5y?LOWW?I!hY'YTؕudpI2=#5u'os|Ÿ/|H5j)>>F$rζD'}!*]}$NB JP6NbI8}$ !.> Q"B H ʔ*Wl%̘2gҬifkˆ sM12eJ?J4i#gNz'Xc:(FV8ǒ-kYYvZܶI7n]r/5VTfZ1$I D2 \Tb DYC˖i"eS 0g xܐS. Uq '!:D0!&a](DǓG0a>T%KvFV?ODRru[y *Jji^^U藄\\yL%4ф BDY&HР6Q .dƙAm?pB *DRGM4uA4sQyo 4A,l $mLz;SV~y.!JT~VQR P $&DVlW__n᧠v!k$₮C#Ԉ#6ga&>BaEJ,Kw'a~ׅDR~MA~ٝAq eLAv> 2.*]֜ke(쐧ShAt Pjm]Jry0j+" C X3f@: 1ζ:f"4M*G@BpWZsi4p!.+2e/y^{27RZU>M_DمF[՗g(*U EvK$'hrl(B,OR+g"5Q$ +ZWl2ֈ2kJ @B m{q 5T>p%Y.p`^;-CoD;oO0J'z->O0x3yqZO*O X#\28ڙH:V2*<6coDЁiu xJBH R8883$# e &PT??}[P"N|E!U8cb9maT1Ô%NzD"ol^j  "hg}INu2JyS㟉RP~~oRڱ3j~cy.P[4t XAM Rt-5;,T&"iM7 vD7PnU! )Y(q5nmJ E)Z8jDW1kJl!"1qT5GUFV 4lf9ِĦY tjY# 38B9HQ f䉹*Kd$kn8u9\`.wK\@[Um%5RM%N/@_jA^lfvULCK!8>bsZWÀgV¾!,l\=Vm.8Vs LZ-Ғ !p@7r-FH5̃Mer50['`]gQf*3ANBLeJnECdyD "-q>7h~Hxӻ^#f}7.23G#.Sf3s8C.򑓜 /9S?1 sQ2Y4gJ 0%~#]%LzK@dGo:Jr'@=o$317IjKv;\):nN' ޫ6]"O b|M 5I^%r ~- M@g% WxT~pst}';Jln@_c.{\d7}P~M|@o{'Q>>TgЉ>+=M/NcBՑ~#oa֡aŝ Aɞݜ UPA`, `x   ޠ  e4ٝD]-]@n^6a1!! ^i ba^ْJa`  !=!A^(~j)(~*j\! $##a, a,b%"""#$$.^.16 ֡%&a'R!K)v9r#7F!+^Ž"! b6H3ʢ-` <.b% y ]J%"!HQ_~:@$q9d=EY ]__J JZz!yM]L& L*]q]xY΍!dv]u^F$^dcBY*\Y. ? X%3\v\ZJZ^%_e^_`&a`%b.&c6c>&dFd:e^&feW\vg~&hW&iif]j&k&\j&lƦlkΦm&nOm&oohp'qFn'r&rq5tFtN'uNAufvJg]<x4y'zz4x>|Aԧ}'~N0@),x+B,@("$,+x+\@)g)t' @`CP@6d606(6l7(h7ti6("Z6(iÊ#L4gLC ))" !$.)6>ii)46li$2//,i,/i2(CnfM @a < A@-ԂTj-A0(dpV) ,A e*2B--PR!\%1m*C2obq1Mj2/3;3F @,j$8R8XNˎ, $ B;kr l=t*)@^Gm@),mN'|A4+X,(AA  Z pf2y-߲J4J2K;)tN4l۴34P&E6l˦ǂlTnjqxrA` p`Zu ( s @@^CCTxl-u`3(xB4D+B"Ta*dkgH}ȔIh7)x))/,LǶߴ*/~qnno6<fA*,TS\u-C A` l|j:cAAWHAnAhA2A@@I@_p@ x@ cB Aj@fGD1H8I'H"@9 Lh/vn~i4,z8m˂'@P+ l h'x*90_nc9l7lVx5 ׬HAI#BH"A'@A Ĕ,4‘A30Ā(WGo+)"@1YFLO3)z|1t:/:øq\)|u#9S\nr71A첕(l.n0l\ @34+ -l=&wB'ȁ). k "\"܇ kzJ#!Qd¸ S#u@j`eWR=k0|0p(#I&ąC+A^I \r30ZhY#>sxRhD?^[=PCQ.. #"9@C9 _~iRJFT DؠsԪ?5x` B26LhK"_m8)d7Vd/Y'Ml"ڄ8L # } HhĂ/؀KLc-ZǤAHYE@pD! ^@ 21xa5s€L! E.BE'\qDgR}2:B(.%+,A}% 6hő&8!D%3Y.`XI^hpHD 4A"xEXp$ΰ?jC0(?[dPGB#Ȁ1|SaU} P31K @ֱ}Z[_ӷ@<00`.=V-h\ c 4"Ȁ{! /% v /! E@ڍ"M6M~` h@FUZ@@lb&C %fbi"&D@ .`RUo\ hMro / v`€2@\X h@ 0@tj~c Ѐ6`JDG``WblpD(oA deB"A 0@ h !A $ ;!>06)cZC%6\dh%d+&z1D @`|: K 1 P` j/\jh 1ܐ ~` ,rk>v v@\$dbb0>+ f eq"#a'P i:m /"h# @>&l$~ZxqeeȮ MP ( +M"*# ot/o~H Ql`r`~M  r+a6 Z`<D`v`lfE&4r#p˲L$ NK2=gSj r~'|2g-8h0$eb&v>l2 P8sE(R) ){O*M:S+wl@-@ cF/PHTL X_v@~ &gD7S=h'`pvp Bg5B+ A~ A L@ PX4ba %$fPcp%nG-6ekUt*JS8/@f S::Ks@F i|/|N2o԰`_ а=pTLaCQ!s` $? ^A2_(SS5uD UEF_CFQr ff6sS%:5C@:k>.&TP:%H Дt*ۀB R  ZtKK5Ll0b2 }/ ``_U>#Nh |\. t` @ $V4 r;808c L+y . X!\/)5US Ԁq?%߀56-~v&&\ "uiYiZOiY6kS\a ]Дb_TO#_ "`TX" ؠ ؀kBA1u4SNc .c pl9@Zv!^..@`FYr0'lNjckrT8&~ggo,iѣw}w7xl/"k[&wO O "% ^ߖ_"B\р6Hob ApC9d8tWcz46V~M~_$s!btU3 FЍH`ތVM&.g?uR7oWwˋwxxCXxvjc|dwilKLE_)"^_ov|7UX(}EqXqO0 h 0Z"]'\  1c&E4@HC.Ft DD[@9\B#.X;WG%% (gVmF@X\[:U* "K 9iSxgdy%DXǯlO"bnSmtn ْ)7>X'bwXׂZǶc 1M3 Fd@sH??*~<`h79F6߬Wb͌֒عY83TKo`:K:+a7JN3Y40q JLzVJjV\|G>j  Glr0@S Ci` $cD@9#W?IT%u{߶^y4ܙYЊSsӞu'ZAXX3CX9W 58j.ecz%Ƣe{ qx sTL4LYciAsG.n4D@@DjΉuI[uucU*)U8xګӫ  S34\OĚeWGX(Oؠ¨G4HWmMc@AR4@ iٽ%G6[F 6@?&(T$̴OkX7jH0)4\j@Yk:RP S6;7lQeﬣj#jCTc<"|\^V /0Zbԕ]i` bw%Q7z]4[z`vʛTi8\?^@9pgU\"m-M.PKAD|K\[39?GͿjL+jP=Fv'0ÐA%dk@x\1 C&GE@`!;; G]zq7'oW]X߈gc"Sio[I\Q`k/]y:I9՜%-}sG \:{-:͒l@`XkAu*i<#]fᅴ$Q#^UZ%]\ϥ]\K]WzMؠoxͺ3ޒ+1<}ͥ|ĈxGUIjqs ^co7h#2%!9ݐEU~.:[ޠk^=Ͻ҇7#8}0GxGX\^kZ/:XiaD`79`IQ?UY?W `im!y'پ~?`W(*?*-` ^?4w?" <B:|1ĉ+Z1ƍ;z2ȑ$K<2Å U| 3̙4kڼ3Ν Y 4СD=ԦϘ68cԤ4:jpjTY=: ဦX%5eڰ@ 5Ds}kqLRpmJoƴcH@.Dt9㌅%&x$ը#IY^ n%]r)x!^Nxa*@ 'aH"AeFXYmzXF$'C*g?{/g 磇'JYoTNh@f H[Bધ^hi&M +Ή827kA, ߏ!뫤,Gqึ.cK&m/~{5/L%\?ZfoŐY wZYz<L^ 'ũUn:3ga1ol&B\i`jC$yݦsqRuҕRsUgWua}*ZM;PnkZ+rtv_8끠]o,xfl/N]?O.&YyoιU'y袏N:knQ骯z롣]N{ߎ{瞸B||/?}o_}U}M܇O~柯~~=Kߏ p,*p lJp/ jp? p$,a;PKi܈_[[PK"+AOEBPS/img/cw4.gifD*GIF87a}{!R9sJ{kcJsƵJkֽ֜έ1c1cνs1c経1csscƜƽƭc1scscޭkkޭkkƔkޭkkk޵kkΔkֵkkޭkk筵֜޵kckkkkkkR{֜ssZֽֽksscss֜ssssss֭ss祵֜s|sスֽス֜ssss֜kssssss֜Δ!!֜!!JJB991ޥRRs֜֜֜sss1ƭscֽ֭1罌s眭s֜֜cƜ֭֜1ƜsƭΔֵk経ΌkckkkckcΔcεkƵckkc絵ƔΌεcέkcέkc,}H*\ȰÇ#JHŋ3jȱǏ CIɓ(9Xɲ˗0cʜI͛8sɳϟ@ JMF*]ʴӧPJ)իXjʵףKٳ]]˶۷m@ݻx˷߿ LÈ+^̸cUò|L˘3k̹[zMӨS հc˞M֯m]2Cg޾#A/xˍ#ˣ⊁b'W>>bn7s1PR@1t-!|%6^` f NfWuIWM_m=yב[^st']ՙZsiyDAZϞuI>gJime֕--:Xl^#x+}w\ f8nf>nb[>P{xsl]CK Q$~_ov)a q'& 9/_X"AM]yV7$86wo_eXrCca1WזՑ*k]+']#.ҝ1\I=Ctuu!;ºŠ(VVjpw8P=r؁x~6*n.6zwk =A8cxq^.6I鿆c򊚒=۠'s*1)ٌ]S~׫UR7#Az: ayi࿋=\me=g[^soXL_&}C5;qR DD"v_,/T Sǒ>˵1 u/8y6o:8dQ PŸL*źPS2JBhEo gFBbH!Sw ytVv4 3GD003ѐy\ĺv{5~wg@&dzǣ7/"{*M.t}2\ U-qxqxG `h(OO0 cNNa9w\&:ЇNtHOr;PJӣN['Sַw`zN|fOc%o;NwϼxϻW+r?ω\ %h1b"!?<# ;$)ơ,4JlPC}Ynm8~%׈@<a$1D^G>߿񝗽[N{ Ȇ6hG@o }7&G{v؇~y-{yg|H"{p {@ x!wm|w{~#ha̗W~=(4x{X9+R(X(h7~t z_8S7x{t2~{Lrxx |z };xͷxzLJ;xW wsXax؉VljOXHGgww؊ȊXwq؋<l!&PxȘʸ،8Xxؘڸ؍Hr8FGxp踎[T8O!xJagQ9:!y5a0 9)y i  9)$y!ɋ(ؒ.084y6y㘓:A Wg|+Q;x<u 0k0\Zɕ_vjٓxw_k0zi+xY}xxzkzЖ~Жzlp=xWzxk`iwo{kИ+! ZruSؗ`+ w y)Sy0p)ɹǹGnpy0 Ȃy$w @i7y x@ 6 (0 ٛ+Qy /1v@yx' י3 2py ~iIˀ~m~9w x<Im;Zڣ,q' `9Yrz.ǡ+Z;8yYʢ4jx(aJA:>jiD) `N3/ATWʀJ AڥVח)I)~),q +z` y WhkXZG0('I)9'IqǚXȚªyw5H~Ȱy񧫊_jI}"°{ʢ7AIѣ5>*PMZغ'h |xJy LɈx" u<,[.2ۉ4[x8+:Xس>?)|_LRIaZ^ApI}Dњ9K z٬yYt6( jk Éz˩ʶ^r~i㉸)|I%ʞ ; | ||Jٟ9)*ʙ ih%z񧢰I P@Ʌt~#jmPɡ9ʦ mZZ*y*LJ(-aHY[T kJnz;Z}}{G 0 Z++Q*˿O:soתLΛ2a4sj= rs,Wn }{5/yWlCyЮxxL%S1''}),2 1=4! Pm`7l\1/r!c# Y { ==*ӰNݙiYJ9<[]- |0֊ikI\(} R-Xm~=P٘̓)#;j׃J ?t Q/;Ɛ o@TM_s3Wͬ-0-1ۗןڟGk j7N|9j) +oGm~1>MjTK m̩9#=?B aL{ GH ᎩtZ)yӔ${S=B-4bf^viF D:^B~8Ϙ9}Iy{γV:|I ݛ@ ynSnIꦮ7=b}9ӬN -&bS~pY!>جʞ{N~>M?\סߛeӵⴍm>(altm9 e]ԞwhL Ҟ?S]iظ@.NZ] R R{ ~i9in>=LQݛP j,j# znr;[M7Z_t\C`c&Y"(hsj[on?xm47tsvxzozy)r?qʈˎq s`s qDg` `  `gBg5P0o=q`?Y۴XQ]_>++ W p ,Y rb5?=OF{s, @ Y0/q/G ˟OA͛ DPB >QD-^|@# bQcVJb Gv^?Zc{liġ&6k'4 L4u.CI@NX*S C 3H(fAN-ۨ,ln SP- ;-:\:ZƃmOp R~2H!Ͼ8 $ %:À85 Q Z Bkʄv.Q6.Ӳ5f$M$S$:ĵ4SłR1 =BsHEet",I&8c!?N5P 4.J(\/8ri5ͼ Q 3ʩ7DᨕTbC jK6b6Zi!zR< 30RjB𒰥| Ƥ (s+r(@7ݤ ^;=7W4I/IĪ\UwZ7Z#Àɞ/C49eWc_OAgfk91@˹gg&h6:if:1:j~zj:窳kݚ8@YF;VAĐUnf3h )9p۰#;qr!`C y"_#rcl%00K]#*OlthEO],& ( ="u^}Ǿ!123>|I0Ck.h(w8(~}**Иm9L&N\.r"./ LUĕ=m"s0Tt|qs3'EMmnӜ'Ja ՞ G- O ]`' ӔhHP~胤Z؄Zԥ Bbv!/ F1Q<#QFeэ2F0J]tb,h#bY0H&bJl2HXDc2iu2э"F,ƨOT$%FK y|F~)*R!+Q OT%/Tcj $Ы7je/bZR;xd) tV.Qy=^Iwֶ{$_+׿$uK' VNԄbE$#BqØɔs,\7/2i2C F!QGAѨaBQ^D:ҒԤuiLeԦ7=LMqSFD=jPSD5jRgT6LujT! UVTjVSvXjXVkd5kZUՉhuk\Wqlk^FWe|k`M؂PllbCXMnTldؽ1u#d5.tb#ʝGgayLlLѤv=k>;E)u C{PO,[6>%!J @Fڑ޺Fv U=ɴwxLG!,Q)r0-TҦ<huɢZ4" ;%iX9o} ")oKc +0DTY BBvBeqeY$3StTGM2LB]ܗ8jrweTFvef!YUjƆ‘ qd2,dzDC6M!zA"'XkBLx\&ǰt AA"Bm)tXiNSҝ6jRӥFucFPZ16j`P~ +0{3D"Y^{9RǛJPፐ?=SuhAC'IUCXE>t0)UJ ܖ%ciCڴ'~z?OWe@ ;߱{\Gd'ȡ钟h%:tJXbAvnW4S#8샌aIY3:%2m`K<1!0-㉽{&QA0TkhlI]s638#9{3G`}YFAcO'23?Kƒ"(WA-G3+XP4IbTH3AC[Cn8C:Ch< =þ?̫@0Ħ"Dh<ģÍ"GD\Zh6Ҋ6 >`kiӸ@ وT6n;/K̈Hա=7݂Î8p;;00K ,8+Ҡȍhx8 cs2L[Ɋ>>oLC$V!?:#Ӳ۹t-5[ SS2eчKK&ݓ$`GSbVӦ134x1Դ@m1MH=94LLNO]M$RSEU5UulX4X[**ո_e`H=b+bE֢Qejhijklmnopq%r5sEtUuV=)vuyzW5|W{x؀؁%ouy,؄y-8؈؉XH~U،؍؎׃eN-X (4pDH4(eٖuٗX=W xPhٝٞYmYYuX,8ڥeڦؠ--ע51 /(12,0ڰ۱EW h  ش]5ڬ0ڽeE [%5k5[8j][n퀺 ˍע5)1؂,\-0\0 ]%\=uݱM\ p[} \p=}])/X0U]ו j}\ ]E Ѐ(_i%_U_]+[U[ʵ_, h݅]%Ђ%؂.%%#8`V^֥ `M\u_ōX^aȀEh_ǥ8_v% P^n-0**(^+@b# .. V[-a2i=᷍[5^i=a_vacm-b#ȁh''H"(؁@6bh-Jdvh\9]N(<eRF<>c;^\8a8&G)#8$P$P^^&Hd dVfrUܸU\ 8ci]5e9&3~cfcW]!5>Vd@6bh)6*b!!@d >e~%̭_p݂>hehci]^ phq&nslUDgJFihb@eET-!&_;F-ʵi 5 HXa>ꨖꩦjn-Fj~  &6k vkKj V`pH} YKnXU>%&฾xlhk֥Ϧ^PuVc6fcemRؖ٦ڶ&6FVfvֈ;PKVmI*D*PK"+AOEBPS/img/cw8.gifL'GIF87a{!J9sJ{kֵkkcJ{kJkƵƔ֌罽εέ1c1cֽs1c経1ƜcscƜƭέkΔccΌkƽƭc1sckcƔckcscޭkޭkkޭkkޭkksƔΔޔkkޭƵkֽ֔kkΌ֜ޥεεΔckέ絵k経ֵsR{s֜Zk֜sֽsֽkksssssssssֽ֜s֜Δ!!֜)!!!s֜ssJJ91֜sƭޥRR|޽ֽksスֽスssֽRss֭֜1sֽ1s11ƽƔsƜs֭ΔkkckƔc絵Όεckckc,H*\ȰÇ#JHŋ3jȱǏ CIɓ()Xɲ˗0cʜI͛8sɳϟ@ JLF*]ʴӧPJ)իXjʵףKٳY]˶۷g Kݻx˷߿ LÈ+^̸qݕrKL˘3k|rؕCMӨz2װc˞mz5ִָqavu(8sldŏ뭀ĿG' ]۸%;|@_Ww ]1uUG#\z D3 \5~ W\`{7X]_y!\;4|`e&Y/ _`]%^mxV7Wsx?ҥAו܎iyߋֈ6zHWU P&f10#V#3ogpU ői)X(X(]n҅dUC )`8i&Prs\ԙ:Y*&u_']H4ϠWCqJ *r_e'yJYta! Ū-:_ &YU{n}wu/t`c~q{&F)h '{yg1ibvUJ;f2~@2ߐ?x 0^RG,PsӖJ'ؒx5xƔsZSܱ 5!X%vyHN Sq'w'jlr?fkM0wC83GϛA P6ov|P9d=,x/ Li<\b7c}%I,HÂzc%Z^}m/Cٿ|$ >z|7[꧿l% ܬĭȯ Я59.]؜@j^q4&!g|"wk cpf?m7Stvز_qyV R8U»!R&$F>պ$rbF+[`E6v]$d5 ^yyatF-!Je,9C 1C$ѐT rIrGxE5n2xyQW=…{awB@YItR[$ʮG;9g*yE+߰Α0D E0ViWߓ߀@"ʄw$IJFL_wW#fTI(|c75J5K"yNNiZgKX'We{5BG6fiқFM=1h^i 2}wj*ђЗ&qE˳U>Z4% ;V:È78%Uگeisc}XR"TɎMV>ڨ69M^m9V]}wMa~ߩ>8Cp(!>S \6{s`/NefOǂWi;NȽxO&" @@B#B1BoKby\3|ᇢyB Colh.نwc%&`JT( Q^.1kB{0)~ɏO?aQb { j@׉ ^p1~~K|G@qP跄v7xڇ{xy P{w}+x }ҷ+qw7y Gy'ǂ+ၟ{W~,p#0xX0|>H4Hy&Hy<2xw|' w~E{G؃+?3x8(& s'r()Wx*xWxi(|px nh+ sHLj+p~X{}fȅx~Xݰ0`z0xzzȊ+ W8( {}(yW8(@Xq{!8xXHv)'8ЊMH ~H}g~zWz~9,X}g|jXhx|'~Ɍ׏i7|Yx)؊-1uwsz( ;w]{#;95Hٓ$pøGH72i[ȅ Ny )aYW ayQ{X'((YYDvj1~`[HGjَyj88)I7xbX~b,Q3Hi9ؓdg~m9^u'z,Iw}醇Y.Pg9N 7G~ȉ GyyŹܠp{IЖ㹑尞`yh=@⹐:Y߉X񙜑w| ({Ȅ)%ixz1iחW~x#}ЅyHG+h@xg 9z G~:CJ Xمw':x) 3كRF<9>Z  fiG:'hH,ڥ_ZSz 7 Ue/=gv  Ze/q}xw)vwzʩ:G꩝zvu:u:b ګ:ZzȚʺڬ:ʫzJvsڭZsrZzr皮 rڮqZZگs[{v r ۰vZr۱ ;$ks[(+#$, .+r \7 :<;B+>+yEG 0 2ѴCP UxNR5 S۳?+]p j bKq;9a ox;<;A7`,{{~ m [G s[f+=h +׵31 gP6\E;˴~ W\˳@۹,5_;WK ~ mk-w M 8{{ Z k y拼}++k[  ,ѽʛ j[:x0{+B +„ 2BK,qK\O5z0(, KKL&,PT!r뿧 el oy+iwXRǣ6;ȓ\tL3~8`;<;{lɄPG @|ƹ˳Rɺ{[ƛܵ ʟLPϻ,L\N;̽?+˯jЧˁɎŠ,ȥ l{,q bB, {_+X<f ʫ˻ȧj , J\Ə0 gRۻR;80۵c쎤҃3@]Ȼ, ȶM,`һkl1-칤}x| O=,{ՌLM!=>}+!K?mliY]pik ǀ }NiNkXMү|H؏hعv՗+ɛ.!׍͛Ӥ`@ؠӋp}w S |̠ƻ  _Ф@͂}đ7#Ѱm݌M-'߶ mၫͫݲ,߼}+a e Cjk85K1^GM6@B<A\._/yH?NB.E *^{鷠m-,>@n';O5c>.-^r~V.[kZV~?RyN6KH~ 47w'+3ցΠtΗ^-`v1ް> ra }B3Tn>OʳkF1>K8oeўnJ[EA-Ѹ1!;aw{Cp }Ns./.η7qB'<  >B{_4Bkć]芌 ,2; ,١0[h+šK [8 ,j+-*|Io~D:,àKn[O/M \;c/gwy Ek"LLWZt];xKɦřR˚LÞ촰<ͳ\˰ș ΣB$ܼǒ +,\ʾ[{ϰa W֧`o? |ъ,+!RK~Ljȡ ĿL@@ K4hԀQ(@FLFM#H.tqŋf4r$"CfHd 0]R "˙p@!4pVR%, uE:[IaMV+zP@ce& 4a&:e4HxLҦw>LXLG Ë,ި?\)b-Utkĸ-6lE0[…!^zI52 1dgtL(S>=zqvmMԍR9foiiF L]z}?SiKl+;(2&K2uHbϴ4Dh QNcUꉭK\.3BD @ECP LRDB,q; t2ꩼr|A*

d~0ArQ%t!`H;666Eptkj*oYHQ0_-+e"  6ܲB2@JK!"PP?#r₃ K n%MҎC6ey|: ]#jG6Rdף%VGɝ$1azD0Nq9HIhJfFO*a he(KhGHZJ 2HjbK|Ribε(9ԏΩ8O!x :*g&\aR&y$?K*A<JrqoǜD1T'yg/ǕG > ӜdIuO @S8{邈ܳu#:-!&YMj@'Tit~>ukiSG1JI1LIqzUL;9IR (O#@͓u ?#dJO= r tu _xܢ>Kk(Ixa?$ŎAsβhVEJ(L)dOvZX0 P5MHǜu-A\V#Dح,g:{݅7[YAˎx/zb*5_2h -h7"2.!0Kς%7W/sfp. [ Q72PʊV /cTl3>$ v]2Hyokrd1Y˰LAH1إoXreAqj~M&!Gps؜g>M=hB-ЅFtݵCrf.{f%4KGcZ̲ Ś5.|M/:ύJ;Q:wYV'i]jm>5PTD.yk|j<Ú&$7ͤMVӞdfbԐq.0p'AevFE=IyُDc tK[t]o+~- l)XȩPy[!16T->3TA"IX-[YQBt$R ҖfB|2)Y&w}DM&jKKKY,?D䌺$V&?w֣f 1iJEO yR](a,Z;3;F'S׆X1iP2RoHgUB}+zM|V< jGk+B W+yㅝɯ4PaK!%G%vZ9Jz֧l. WIs )p~wc-05SHu6Ҫ.<ɘ>wQh/)>I10d!1"y1;0 q72۰9!] cS GT#/lb: ,!44볠+B=AXZd6Z\D4\^3^`lH|i0cDce`$ih6x" fFĪFjlmtdghGkFs!|a &yǐ m9k="GHl1H9aI`X6utbtixryDG >H8҈0$jP>S 41Lc6SdɞddmɳaGjGsHID<$7q#rۖ3g4!"!C؏BLm tqCK°=8a`ê䚫Jry hɽ\9&{IKx A4ɷȍJջ։09'òt>S̰aLiʓL| ʌH lLc;|KLӊ ĘzMMr[x;λেI?tͭMgαTN 4>DOK1̒KЋѫ%e\ϐFJ,N[:(<#J$(8͌苾-(x5asmPMNO̐e -ŲU(m@6⦱,Rɦ<4A5jᣄC47YCJ2HAϢadԪ8ea0|SFSIR5?9±P}\=dUqYU#[U>^Z`E`bM\5d>GSMFeߤF NzdVjuOkb6NX@IG{HPNM{Su=XuWrJ557,Tn]DdMWqJVs O/JѯsX00%0DIJ$$6JElXǃ `QY,SѐM5Kpx4¤Nx4ٓШ8XpvT/=PM8/ -$dͬd2M{ڵiO"pكUR(:d 4N|Iˈ"\"[eV mY[&(P%M=qS[2όPJ[eݚ =ɗ-;uӭYٻY%(ˈES0QR]5Ĩ9}O]އJ{JwywMK61}2MScP<^^rsShP=yyԃT{ԉTH%TUtUi FߴMgEƸIY UM7X%vA [P. $"V#FbT%N&vbn(^)`+,\./X1nŷ)Sšʝ IK*؈cycy)8[cc ;6APiر;6ѿ䟱\kY~5 #dVee+Kȃpe >.TfVVOZ-\g{ /y5a~ǩ^QkSkDJtjvɷ,! r9!bg#21-~۟8ո?7+^/ʷ0g vh!͐7hTQ9k9zS Wi"(RB#G3t~xy5xb&`X`` Cʥ$E_#!:hjN=Q:A˨6% k*jp:3@¹!A(%Sk%0oQjm;CCꈏY)^GԟzM& K{)"[9ڻi*+ s)++ cf ?(^6BLzz.@K,L1 m Hr?6h˿JL-2"+k?$QzIn&r^).7$ώ댉4ґh. M42 KB1@/|f~gI0jɗy>WC`|AD2 Ssqy1 B/S92{Qty>W6U9B}Azaa3vD.tfaY2$2uq@^V^vO$b@3ddQ1 CIeGOX\6Ylde5UvH4ks/f[ mIJf.w9B" *## :`fxCΔ{V$QI]7~sMy'k]bcCkl楧hj8뿶d9P X ȓ @Z"kMB*;;nN".6n_A  ^9mO>lIB+5Q p{O{q#oOёB6F*'jy!Xw/yG_Ɯ;[Hҗ- +Q{tё{p~@ ii@#Zs'vHQuU'~\rbe(- u+*AIH@䤄MpPȂ8d2(X>/hJilf)g @TxgkA~ +"!5*=Ha1Itiߣ\҈#Bh 7DmuF'tb@hMV—]褒Y))7~Q*  Zi*cђddqX"ɤlF~ppᯩ7osw,EI%qr[UeJ!}W+܉36q5Ȉ]|@=RqU"0/UmQV[uuF7QM2R(ŤD!=jA;>VCS?}uTQc5Y5aegvKi6 Q\y7e}ZHR /n7W^Cc ^8,b3WѬhfix R&EYYf78"9D,Ͷxc}6Ai\h?L$pzp^_eAGnZ[7#h;MPW;6zJ}蠈]K}3U9I1p"󥯁 Y_C &_*3KSʝ3=d"f.2./(Â@!i$ DA٥J=H_ A!*j3f(p!|^ U%KpjQ: ICtZ,RF^ȜmiU-?ܬ%2%S#d%+KՃ|B+BںU +Xj&`LSz/4-.iB ^uXMz+W) '4Sy)klf ^16kR "e ;u%~؞萛97kk'e \Mֲ]~=VO\\Nr y> _o- %Tz5H?ʃkci`2^iyߎb8s9 t$X7W )|p Tq(]XiW]I& yx_VHǐƐEfPO >_ U!`n` ŸVy_@~ Q:Bfh2YLDJ[KKZW La\ZĕJ͡!܅FM :BVP}SRi"BQ]hg#D&G#:՜T%K VFG"Rb("C^%+B(-.6T!^"g%KFG #R(@D*D0N"-36hUH`/oY&z\V@u|؍|Tajt"X!=*WxA.@!8VوyVzum!$o)$iaW=)Z"c5VyAW|x%Yd1 $t`}>qYBACRJQY؉Yǖh[X("p)ZՙXhI 1)YphUeipaHv$Uj%y ZϥQڲ]ʉI%P٠]>ՐG*!Y!YXE&em\_vlWvi_j&RȜہZѝ汥S5l1ErZEX _ %E'\fk ,X}ڣ}'t^z!Dkr,QKMHYKw6'O=ʑ"f\}\m܇~N՝uԹw\ob݆:xVeH]zhҽg!o]t' ݀*Hǃd- ˹#AmމڙJ$(Σ)($Rm%>i  ` 6RLJk]U"N *m̱R`1 @ YkNZD "Bb16NbQ, 4^D.΄ dH!X3D’B,˾@E$>4n"PK#,CQJ'#VF-fφ!SU_YEbDOmHlMpjJGXmGA-T32D4Zq6FRA@jIM(Q&t\GA.!LWA7mt$V?D"ػ2 2!"WwdDf1t-W@2@ZdyܤR$BKJ.dKzV.ix1$&GH =r kԠKr JI%e%QgSR``V:2^&UBeUoi٦fYf&5jX %fYRYZF[/U\AQef/gڜg[Bp\PnِafUeqHgI ![vNw‰a&"u0.䅖khyl^ShgN-sb-g^K(Q^h馐JʧZZ͛&Ra7e,- pӥ.Ev2BH(H֩h_ &˽|՞Zp *|:訞)*#+?d42Qp|*GJ:&1&%nrqwzi5g婝j^!q&r˥B^ƞ~j1EnRYj1`j rF*&+~qJu*"!r+ VI_l -a 8<2`kPlH)++~+R O_> ⠮Rg½S_"1sȖjxNNBBN^,?5``6=ab'6;-6cc?69EdeW66]6fCfougGRZ6i7i6jk_6lC6d6GN.eF$wpaITNq;`5 wOdJTL0I*erww 7FH͊Aȸc?Vo6N$̮w?)7IdYp`%$fp/X RRP78@D緱(qkx_J{+IZ|*Urr%}%5\ )˩ tµB- `5e 4~%EPWI%ʙWP676z9B6w乞Μ?9z˸܍Ƕo,:^E@1u s;S3OcG4-mFˆ4uoQ&Юqhmw\zۄwKBQȬ5CwWH-w]Xe䅕$>H$t"D2o;$DP:D8xgoPF]N&$T 0yew&OM0hhEpD?1g+1{{j*g;'g!SN|Ѹ7h51w-krb/wS?~:9'Ϋܗ|;D߬E[z3^0`ͦ/^7 l#D&~/sS7mmnTymBh-Uf{wxGyGzAc>h@(8{'}.lP?c$ #}g@8$]Pq#%q )AȑEXbI'QTeK/aƔ9fM1%J)s$"D\`ECP^xT(G](BbE%CBF%錨Stj@ض ):%URgԁ`R$ կɂΝ #&Z} @Kwfּsgϟk:$DXjU+$%]jrmS~;lܘ/·% :c饜T!Eݻd퐷<{'tܹLѧW}fICKϭrp-Hn@$.0P 3 40K.lOYl;j>0D%K+ j1Px Lx0,LI.R{ +%0:nH*bh UARH( B5lM`J*ÐC q%FI&)p -c=e$g$e1KVmߤo W\fsM7rmwMx^nW}5~X`nXb!9WA9ڏE.`I>Y]LaF/NhqYy矁Z衉.裑NZ饙ni)驛꫱ZkZ랷.w6[kΚV:J[Ӏ\ /\ 0qW|o#\q['8] DQO]Y_C?$E>[$EZv5܁g@~o Co硏$>F^ͮ{10@7` @//|_?x.2N B3{hB L>l~%كF'C!?50{H\(( fP%ԙ@'pr `o+tA @D}@`p0̄"q! qzA<`KX8&C'VP%D hE+P 0gf$ &MT 3"!}GʡG\` =x qH T<$j܁F`ȳLf@'&aq$_0d!6 =K;@pP%!I|X#qF0KOteL dZrg;XtN>Cl"U .1DUwOpRx3f fՠsHu^kgD5HƏTF`]$vl=M.%lg8ٙ!bEpQ XYPp3Jd-TsK^YmZ>!$&wj @U Zwk&5H6Kp&@M擷*M@WvA(`u{XO4 aJR!H6UhYUo)4l0 6J&0 NYb=3nB\،V(cʀ3 _Tu.Hق"050Tjm<לU]336Y_EzQ sFP2Jg"Uߐ6,a6[H @ 񐷐dr |\,ͥ16P`sd 2{%BbT7g]f yq~񑓬l9/v6-uYe˝KҲEgEE%d# I rWh6%hM(Da BY}f"\n9/au<]wR@Zl@7Se|i' S>Xv-03L z0Y^>=u]3 Vda^7o=<wZѻ3w>6&9ЍP#Pm0_˼f⎗w]xvl`h^%0QpOPYgqPgq./qwƮ.4ppGfM/ ň ; np 0 ib ݐE\ p_"pZDc1q  1q!1%q)-115q9=;PKv̔pLLPK"+AOEBPS/img/upload_photo.gif&gGIF87a$R>tN|l4fT~lݍ|7_ ;:LA¹`Ct@hZeO jѣw{_zLb;*(#}ri; ÊD PlM'S5p;0ذ#B ( 60 O-_Vb ֡hB 1 hC e) \9ϞA( CdAelƒrO6ϝ0oCz^S+E[ D@/=/+cZpaޔD0%z`aBb|g,$W7|)m/<*O>R+-=U'_6uOϻMye0к`9 tz:ɻPS9tk1r\D60ג"078̀ tN301A 3\/OD0ZA r0@#!)9˙ !/ E.\:4,xa" 1c3zF{`f])R.yl*3rL[R75aV{bt DE]TG+ sGiЀ0Z 2Y7J Z'ӌ%t@+WFI )fQ΃,$QE +i@tʥ * (M$2%Z͞Z*P3Eq݃@HߑS;ز\YIJTE5Z#;AyRwVR _ӸpE+Ð{N[|֔z:'<̩";hVrT:eid1?`c?i^=@.Q+je"Lɾ^Afo-|i f+|G-nʧG}-O[şʑ.@K^Pك%'NջumJ#H6-Z!!,}!2uSGd GS N "=B6ԧt-n4* o#fYP q^8^AZǢa~SrVy~}EG>M0 ?Ȓ8-' |LY6`{2)MJrR6'a%֤ ]RcCc١t q@Y\b3/25[x.lvӷ+uiL¶(Ț,KkVZ gAo{֠G`'e^$(+Ʒ;/y/[I^}Ʌv2`̲ne˚,afzkeJC!RebYfRޛa:Xm3SE;2:G P*t{hG${(s6VbNWׁZ2s|{*F[ӟ: +GTo.j|?&跫[/dT*rd 2MabtG3v<(OR+%1=ڼ`,eA=`/m*Ft.D_ P͕, ^W a;*F{wv՟PGbJC/T]`!3rHrW-z;v, 796"P-3'VyVX\36]9d V_kejkpZtFuz3~Yחs٘9%pٙ Yy99Y隶ٛ9Yypȹٜ9Yy عٝ9Yy깞ٞ9)YÐZzI ڠy:z`ڡ :$ZŠ )z *):̠@&z8z@)Jp )Ͱ0FJ ELڤ0ꢹ E*PD^HХ0WZ cz `0@>z r r*20@yj u P@*Z 7 @PH%@p?J Pʨ (P)z z %mzp- @Hr2 @@ y}Z 1p 0dj ]KZPhF @q` ʨFPmj c<0G亯 k   @@͊ @J  ?0 0KbکХkVʮXZʨ`9 5kFZIL۳ / Hp[j Z[˱̺ʧxzqڲp_ wjЫf˱ʱj1@ZRZ г KдRzFj,効Oз@Y 12 J+ˬJ* ۧ k KJźK@;iˊZ۽ 0zj гRP[K[ [ z>z͋ ̪WKA?pk!+ LJ%+JW2P',;ʽޛÁ{ڭEI۳]*=kTz +kk Qˢ M;.ۿ˵a[s٫ +J$,Yl˶rj[aۼZŲy*j}z Ä 𾟊 иAl ʣE:|O >CPC@=l-{so۬;zZ[lª,|:;ɪyzlqj>ZkK\údDLK<`E@0>p0FХ=*T P ΓFP̪ pcڥE*0E[>V|ž<ֻA? ̺+*2mIl2]=M4Ҷ{+!Kī5|+}i| 8LZm @ސv۶d]f}hhlng tM J_ gk2@dׂ=m̅M؃-؁؆;Ì؁}،-ٍؔى٘ك-u݀BӮ ۯMԱM۳۷] -mŭɝۼ} n ؝ݣkޭ"=}} Ͱݟ}>^~ >^~  >$#^(>',+0./43^87<;@?DC^H~GLKPOT.S^XW\.[`_dNc^hޞgln9 鵰ImΚګ=| }s |  ՙ> ο~`غ p@6h @7p꿰n . Nû^~ ^+ݯNT۲U+~ ޞ ^N ώN kP~ UkEn 1ܪ~Q/z0o/#};麾6ڙ'X芎o0?)K>UCp7?N)#GO֎1Rp0*^oc?Vo >\/w.[p/&piS?6` 5o7vZNiؾ_,_V/{.~͎ 꾞1봾N??󧏭};Y_Neո_o싾Bխ?^Io:On߯I .V2Ͻ00@A@ 8I(99(iyXHhXi)jJZ9qZ{iةX)i*JxXk9*٨늹X|ʝ)}+|lj^|^,?O_oPaqz%)CP.L 7k؄H]yTd1hB8B)H0mU17IZX::%夞^ iD ʴP±*H֨隞*q7޽|%Ը }ڡE~"K8x+( 3Yxaw 1N9R@qMr<^B 9:{`,ͽv; ]buT7`ܻ8Qm/dt7 nb.̵F臝RUB{fs +z8a}fF =ɈCX6,̇(_nP֎ IdFޑye|=@)`ewayZ~ fbFh$frx f+rމgz~ hJhS桊.h> iFJi^iN禞~ j*ޤjj kJ&Aފk* lžll> yFKm^[ϴnmjm+䞋nn+Koދoo pLpp /p? qOLUqoq r"Lr^lr*r. s2w6ߌs:s6sBMtF3H/tN? 5JGMuV_uOu^ vKs-vfvvn w-wvߍ7tw~ ހNxK,/x&xO7_yb[y4gA馟zꪯz뮿{짏NS_P A| i@ 3$ =`{қ0"A=̋A?OkӟrϫA ^/KWozҁ&M@ \ ,ᛀ @0(h t@@ɣR JyNL}Z ^  h0` "\Ђ p} ("T" 7(Cb@ED''RƁk}||"@]ÜebCJVcdB5Jd"5j2a< vZP!!;XLn.yf:s'`lAzZ#af: Hd_tg.A%,Z1kF0Pt`_ؕ)M{t#aBQ D$I2wՂJg;e%Ьumu=]k +umxg׵u_ .ce[- Ğf7ʓQ,Ⱦk:܄SBˊv.  DM@J@8 \ uI܎bWъ>qŝp(ZB w-iyrnuJظ2D *,"su ]76PlMx۵_;%20-quנ(})[>r q^0 )oQ{D+aRުkރyedY1eE/ c ^bxu N?x 4amVə]Y+[r}<ڽŚEn_)ʾݲp`aS605֢]|zv.yC4_/ƌh٭+($g:ORr]T1Wo]k\Ǻrv` `u^ (] {΁ hK;`U*h@Pp{.ύt'Aъح^`{ \ hu}>I4xV߉S$GDckcU ?A*OեjaC OJ`$'(Hun#"dm @(Q&b1JVS  @ b/ E)Htj1XԀp[/JWܽ(=]6xQ&f4pJ22H˜G1R#Y1\@5ˆH $Xٷg{ńlZYO5)nS4"L(5e.ѩcoDO$A؅a ß4 ȀyϷ>P{q;. H UNhzWp7}` t $Ps1q}\'[g~]c`]7zu`'{83?U@/QTcdEX{<{PᓀC|2 6 R"G#RR[ !u8Qzcp`~%uwvP%Bw*2-n_uMŤ*df4z>Т %U.کXlgnzvv*1i'[WzGz[7Jz}ugJz dwǪ ϊ8Z آjg5z"(~Xح7~ 0YW:خ[#@Z*[ j 0@[˱[ ;"۱'K- 0( 3K5k79;˳=ALmT GI݉'Om4(S ^V[T[]{^_+aK\;f[T k/o q'"ukw[t{˷}z뷁+gDw o˸븏 +Kk˹빟 +"Kk˺뺯 +Kk{;PKU ͝&&PK"+AOEBPS/img/cw2.gif"=GIF87a{!J9sJ{cJ{kJsƵJkތ֜έ1c1cֽs1cֵ1csscƜޭkkƌkƽƭc1scޭƔscޭkkޭkckkkkkkΔsƔ޵kƔΌֵkkޭkkƵkkkεέΔcޜޔ֥kkεkkkkΔkk絔kֵ֔R{{sss֜sֽsssssssスss֜ss֜s眽s֜֜sスk֜sssֽ|sֽsssススֽskssֽ1ƭ1֭1cƽs1Ɯs֜έ罭֜cƜ֭ssƜֽƭƭcΔֵk経kckkkckcckkkckΌεckc,H*\ȰÇ#JHŋ3jȱǏ CIɓ(EXɲ˗0cʜI͛8sɳϟ@ JhNF*]ʴӧPJ)իXjʵףKٳb]˶۷pKݻC˷߸a[ LÈ+^̸ǐ#KL˘3k̹3z=MӨS^t`c˞M۸%2 {73Ia˵-SWmhկ+Qg_HE"gI[<_X]aiF~`=]~T I `LIX>p` 8Y`p`R4: i!'Z? Pc a5ͭhUVGNX|OVyؙYݒyFHIXe PjA 6$f:$ht0ʕhJ)h.)a~hDY aEij^@vZZeJ}JYϯ?Xʆ*|ނAE|ޚneؾZ-Yw^Bupb"hbzy]s7m,fi?^ɄT_ 2"Nw X*/2}ĥ9V*yRJQs 0~ /BI7Ka:(;hĈIš*@FR0jp(2>3Kz.ď erݗu;@>%wvI9K^[N u}n7 q$V0?yZiN][]xx py=|?}L*Jnأ6bHޓYv\ jl8`:}K^ǰ"o]4a'Ii/^D'9O04DLx!4jg1SPVI[d O3۲>%H=)pK1)[pC*(v,QP/@ >TZ ,i;)$6]$mCkBէ1$4(sGT˪pJRY.F'2* 2mf LSσi[qh)Cl ehTu6>9ە‡$,@, *ii5H q qV?6ĸ8Br$;h/|ng;S.>/C>3񐇉#Oy?}PDN c'#t 8K0HM8{{%o ?_%8{ &JazaĤw O&7}2ፙT?2y4|~Oo?41F2VR|D8A"h?W' \q}G7  w|1|~8z# (|*, wUx+a G%'< W1yhHQȀG)<$/ }p 2؂PDQ9QzfHCyGPj(t:0y'0ȁ'{G @ `|pǂ,ǂ{؇8Dž;xzׁ}h{(zXz{G d |(z|x|h<X|w|wX-Nj؊P'{˧} 8a(^hW|}8zh ȉx|ʘzx ܘ' 0DH ) gۨM W'zy{yIH ǐp (iL0Y Ʉ7 W W KOG)ĠHXJyX)yj{!9z蕥(zg jP'Ȗ-!01yxIyGjǗZٖY^v:H|ʧ(,ɖ<|+ |8g+y'i2X9lkٚǚ-| W 9҇ɖy؀ȃW׉X')zy AwxH/+xɕx Pɛy .[杰7| V8 ){؃yx$ ؛2xG)Sb   im+1 lY|Kw49mi}y|:F j MZgjFЁ}9;X@x8HY8~/ w Cȃ G:Zji{P x)١[y٨/Ajv*Vߠʦ|Ew(}z_ީx@Z|ـn zǐ.HE酸'j*BZڀ뚤sHwGኟدʥ `庱ZY.qg y)+Z! *yCVz\ y ׀8zGgSeتj{Fkg[ g珯覝9؁Y̘yMk7zwpy I{}wzΗK[Z{uWΗhWu{x}y,Ȍ`k~SzKD맕׻ۻ7{w{vɻ{vu;{uCgi,ZwzJ2y@'zؠ˅;{ %`)gY/+ {yX: ;sNhȿ7qi -1 Gɂ..q*hë E苿١8X0{6#* ،0<{xЏ(v˅;d+|xJO˺O1 p{z8WK!skXWko<-v>;ByC ysb1KMM=VsE}ZY^]]ba=fe}j-inzqr=t]v}xz|~׀؂=؄]؆}؈؊،}m֐mٔ-]ٜ٘٠=ڤ]ڨ}ڨMڪڠڮٰۘ=۴Mٶ}ېۺּjm=b]ȝZmK]|zQ `;F!  ` }=  .o`{AAgq?63an ^|0C W Np'?.E1!1-=4G-a ,>@4,<">=6^P3Q#%^NI,Q  Tx݉k.muNfn>~+Iz|>mQw^Iun.W*΁sa^d Pޢp k.,߉P `Q0>GH~sNp~= N.G>^Ҿ{ ,!n0N`N޽. EMFQPn*P.:~g. *޿.0n.Gg\0W0>E].o.G~IP@ޅs.^NZi.^ DO>+ 7bgNpHc^o?!n~'<TkMUnm/-)n pM+L/,A?C_Pg ߠ?}_y~,!hNJ/ N ȾޢXEpo>.ꋾ淏>y?(I"E  QȣQPl0@ &c^Сő#?hbň pB+#ΌqADF $5CҼ84@Q>tAV_2=X!:ܹ%WZuv))(Hܡڕ)P>bɊ2kԠ@"76Z*8box)Ԥ^;EtBIOU:;ihU }0oh]n+ă :1)*d,z7i! +@Z21F"mŎ-Cοs*Zr|$ ,"!O<(1!FQ"%M0 a#E3>(zi/CFr$1B#$Eu")EPG#UC1TP8ЦPU>A1TI7ՠ^MtTMo=Y@ca%KUB 6Q_Y#GMWk7mV_cpfV[ UdRp?vr%$dhYk%7D1՗(TG-Ϻb/\1 c?9dG&d SdWf)v9f/ o9g=㾝:hZ.:iVZdj:kֺk;luzlF;mI׿f# u9Y"ʂuO 1[lĊUm%H81: Yl"K|vԕXkq/v.Dx(Cux؋\Yxع3ek8F̍+J :[']5XbVLߔSU1{\vD{K(:>o&k J!zEDNǙђLڝ}qO{(D>#+6Xf;X[{OF%xcM3a!I\hUy s,aGچezI^!Bd _!9Y+B2C"W/8KtY;9K]*uSI:yUG>:]3psHB;yR f>qg93`Fr$L )V2[ pcC8+jѪ ۿ]fr:vA*fY -j]т km`8s{hլK+b2ǨWʲ]c֛[j^*E!{J2Sv4<8C|suq$7h#T*B)'?1̫q'x o7)Ž d$0?>r j@) 8t(A9k *@Pc .1,¬5Ѭ7 ,,9*)  BB'ςC .ǒJ BŠ +zCȎѠԙ,Ad3:Ž@ -!L8A B0:)0L /z!BD 'T@ 2.6d.8̒PS`ļ/h;S51D#1E-2F.{# !j. !.&k;E/v$ĚQ ;201p3|tǤx /10:(B)%>y)6 6BK;[3rm^\`S95Jv)v3;a#H#Y97DcGڵP{.g34Pa3u4l}6-ZVIWu4xD5g ĵ-Qq:᷻i7lDwĘI +ٺtTɤLȔ̷tLz+̔c̙L7I9ĺT47a:Ti,ªPX$ O 0$$UU>C%ѻ1+=6=pi%)#tO,j!D0Hh THO J)`) tL>,ܝ2;l@*)?PA QOx*-A-B؅#\肈8; B=&tNS;,b Zp&-ɻծ\8N*-2+Zr<;Ƽ RL-P2/r; OP9Z?}SfQD-1h 5i{-G$[2 9v!llL<U0N=2\X i +7T5W N ,Jrʅ4I<4IZ!P։Kh}Mkynpr5usUsuulwیyά{W}XlMׁ5X ؃UXwK؅urk؇k؉؋$׋X؍Xz؏Y ّ5٪)ٓU~+ؕu@hKٙٛٛ0kٝYY!+Z^$CŭXԟ }+5BIHUDy+K9v ̓X ۿ"^ض Zګf#[@٠u]yU bmJ~BKM+tOҤ!U %75F]%nbA). Vb_'~Z+0^+NiCb. v&:Y2؅ESeR9E S;Vt;f?>"d:Epd6 e6QR6ET>UfuWX囥Z[]^^`a&5cXQ~(x;N\Ϥ#=f\fe~;]=8Q*15Pt$:Wg|6-}({FUcgQRl7-hQQ.G D G熆ˇ6ҍVTR-ҿR0-G3+-Ihh2j6 v/Ϣ-=_%/'* +=.W23^+DO%u`$P#̤ +>B/W8et54T/z[޷AρWz+!7j/^XP<o}=X>`(Y۰(6lyaO%KL= QLm ߸՗/R%{pAn1{8Y\abcdxq ѽ\@A1ILƨ+6X"sHYeV`-+ᡯ7sSh-:Ѧ5.MI;z6NJ3Ms%4t! QҤ>LEU Sլ~5LOӺֶJaYgU{ cG fNٛY#!H-T䓴9.pE[@e&k\DW5%QmivёldYWK`jeWg(Ȗd5ۼK2/);Yk29! ;v]Q,LShKF'"r-:P+ .o1,Xષ>Oo$ URKxۉܞ($"^λwjtŤL w% K~}sڲ_Rei#o(w|qUG.6ѮN#l^}kNOߒtlJݿ5/|>/>{38o>S?6~k~7/髿I ߞj?  &. 6> FN V^[R)vJ@ `  ` H z b  .!6>!6!$@&afNa~!\!J!! n СbJ"&"."#6#> D"!f&n "Hp p n)+",'ZD,ZRDtVpZ@q$`'yA:&g&Bcg{ @f @k.dp 8֧c~B$| l@fDva"- $^W* m$zTx^g@PWl(\A(J2Hh _'yh#hN&*& 7cgPvf{'Ri 8%o ij'銆) bhPh['酶@i&*Aid (d 4AfV)`&T|*i"B(>VBAwh&fܪڨR()>f> $le ^@%Qf8ڀC&(Afe#e>)f{-NW*j(ir%nT^koA*[,@2 *b+Ⱦ"P@Eb) 'ʪ,}f `fPlflv)z+.4 mVk@*Zkf-(jf>l*k'-"d>df)6j@D6@c6 gk ..2,"ⶀ F@V@j-" .閮. "h.Ʈ.ƮXnւi$,/&.o@\o8T^/fZ/D.f,j&@//L/^/r`m/0?5F-05GM0_eA_wsŅ0 0 0 0 ǰ 0 װ 0001W;PK5'="=PK"+AOEBPS/img/search_metadata.gif89GIF87azg:Ew"s o ,h#Y#X $  #I 3 !&79"-) !(!4 /3y0%(0*6'49,E"2p1\$, G&1%?5H0$9 $F$L(e3v3V*W&Jj0'484939LIEEeLKP+0I+GqxT[BYU9ThtuWGM\n5TUwTsEo*J+QLysiLKqvIt"0;k4WNf|Fw6g)W"Tdl'X[[5jDwTM=}TJ4y.qz*k|42@MKEtoeɧʻɜ|l^t̖T~ҙѬdb\ԬLbάLLؠ,$lj|TTpT`̖ŝ-Sӹ 'C,%2UC P4-z&@lH iQ}Ir"! Brc qgGùOs  9NwP9—!gb^6&X&,aLl*I̱Dr adJ>CNND ؂M2+em&p#/_PEܰ&,)ƿhBrΌBBQ8VJB2K9@HLf/# %AR8MU="D`.,Mf8X"DT^{)jlB8"KZ&!$74tēpxꈆZdޛ@ &J!71$'Jx('йJOE7[P>'i#z$e!`ǽ G ԡ&}hT*mM :R"L2T4߾ -0ɘӕbp%Yͪ@Ѩuxn 䫯cAu&:R|MN0kH`QXHbH- stM#dZQ`* b )$B pW3`EvSZWrҘHY"tN\*Z)j"}h2h[Ȓ"9Re)2g<Wm591I'b=!4ZԶ B i&wF `Rn >@}ӏ!3+Ȓ C)kxq*R5Xu wg![_2{rs78R!!j`Ĕ9#4@H\ٕ`#b9bYmdyhy4^nzp9t ;rVz|p9j Y!y?䡘Fa9Y閒yٙ|9YĂyYyIٛg9yșoaٜ\9Yj֙Y9晞9ع9yYyٟ9:^zz `W  9@v W Edǡ.ʝx( WQ6ZP:> >BJxQ-,zjZ?!C:Ӊ; GV (jO<PZJZ :! ^\7ѣP 9񤉠>jaZ {&  x:QjZ`JaZP;A!:!NTxP7P *6;ʦ;ʦ2 :ѣ@ Ъʪ 0Pjt ʠ*3 7*4<18AH J7a`A?a&JZ! ʦAң 09QlO:PL3?Kʭ #)j91Aa5>=AAg1 6 6* Р>Z"PۊZ_%;X{>* ʲAT>K={:z+𩃋0K;yd:Q{*{y+KGۡ~ I 0˵A I'۵ʱ): 8 P˺ 8Aau 멂˳<+6:`~KZ ;Z: j37i6`Y `ij[Q˦"6P Oj6i / {!sK.{9! k* 7kJB˷= 6\6\uEβ6!ZR{Uߺ dg-+6@@. pqak WJ2l@7l=<ÄlZ>+=|75 K\E ` c* $ 6jY{JjJcJ#z Pp,˲Z {ͳDKٛ{ʽ`+A[D뼦J))|ll,! 킠ii{E@CiѹD;$}%( )}*OҘ2m&+M7-=0ڞiB_4M:=1"%/iqSe]am(&э:5l;.KR!HP6E[:;4C1+5>DOYaE!F~cL>.A>*^1y".9>ackH:=ј>C#-lS\&41).Vߖ,@F@B~{.:]Y :Mq]ߢsј궮:~IN?:l5mB>R?m@^6%n^յ~K~_$.q3B0~&7QDB.`&ѡ_T?Oo~t!.R"~ož02l5.:4c@>2x;NExN/䰶EEo$?Yydg_^c2cs&e*Z/g2=`Ro;n?gM 6UO.'F/E^f@bY ce_?4cLE(g磴6RMq>bno1}?oZDeO_b;1l1cOp1@ |  @| B *PbD Oɕ|JṕefdqI jc5 N)Ϥ;i Q$m8B:OE4=z׈T*pPekԶ_ q܁QL7ȹN % J1ЙmUI$ꬋXSm 3XzvFzfEsM lō7@҂/\j?FϜ3/;F\sOG,߻c.死9pbK=ղS :R:6.<㓮ժ0Ͽ#o!2KȤꯡċ:ܴ0nMCп_Q/(Jp@BJ+[n?blq-g*Q|/SmC44sDj 9KqFBMk0L p:[ AL 1:4pPBb4|q<#rEnr7<;=tѷ|tOG]`SguKwCfvo}Dt߽ci؃u@~:Y0x|*Ow_+dD'wL6v>طᦱĝ*A`￟$`b%2@ `qKY9u=8d2rATB_:APr ]+;W&`Hb8Þ$d$BЈ'\]LQ(Q&ZTM~Ȅ'*ˉ8%B?4%hKhM crG@!+ T8%b %ٱH ,0@'b K$A e++]Y@\@C@\v(|(ZyXM1[LQ 3-4~LCr$! Eod:1f6\1E"Dc!EdHn '\H?@Q0#!=)"[M$'8?uVtʍ! BW#ͧK,@Y jMPF9@4sȝ<iQ60?hB\,!b©$AF>p T [቙&*FLP'Z@ ` h HjF4}KD"{PX Oz9zxD !c50obCnִlJ{!&ie{oZ@k_BrWmcwuMp]'0׹ͅs]N׺nr1]v`nx[-׼-vѻ^^ow_wi_.v.o 8.0`7X(ksqm& oá_ED,q"6q/Nc,C{m*kmH]` 'xh'$/M2)GWrTU 4{l9eA`g@xX*y4]!1)g6VY%4k&`"!DHLF̉p$ QdWmڑ9ڡWa;kvōm>/x#ZAz}S7JBp\5n,M@CvML\{sir[Ֆx'-K_:Ԏr*Dm$;D'fwGm!OL"ўy>U3I7*cMեim<*8ȷQ#RS]sDZ!@ F>h"DzrjT%.@ zlG Vsf:՗.p'Og?~W:E}m7ۮޥXU 5"}޵؇>S!Ш@.7▧mkۢ:uMSo>qG./24 Y P4 4q:WN 01EzU<ʫӸm<仸S@1>z;=AU`934s9C;>ld:V Vh<t8AA9[* dB T YOPq3rN)lDr-ޢ9#@x3CH0C1$344,5DC6T6,$aFtGHD@DEL|LNãP<NRR4TTTV\VtX$XZZ\\^^`T`EcjYn+pyƩ9AE#Bd*FFVPdB@A0K0vЪm8|D| s$uGC>n9)m!tiKh @o8bB_T/%b"(?""+"-03#4R#6B{"T9#4?EP8  r )$!ȏlJL$QP R2]U(%[%]⥓Rh6R޸Ǧ8R(P0X 8l0r. P x4P0 8LLvxR 'z~LJPQNPe<@>B @5DE,C@G5HIJT DEDLOT7fPRૺՠYP,)k3ghs1-*ȉ@LA%\e%j$(*rЕ B'}*BJTac=g8JN$Pb*SJY,JbR΋h" @W[ y V%;e|'yL#1c+pЄ%& OڡA؄v2N@ΐRΞpNZ( hP݊ꈈ #V YC*4*Ī+K?Ȅ2lX&pͩxY"T#aY ۲N5@5XZY(FTR Xঃ5=[-\yír\\qTKKϥ.ɭA5sUȉ"_YF *6މh}Yd v( _IG}WŠHք@@h}I@VaGGu:`>0^(a~l&.HFR_G0v1ƹp2.5>^->.n/:;.^Gp.cOc<@G=>L:|LXFVGfdHvHD&dCcm=NOPeG\LUE`UfVvWXFDS>e=CD^^_CebCHZd efvVhNif/Nk6Vkf?nUnLqFr6g.Dt4B0Bgxwyg{gz}g~~&h6FhV>.fh~hn舦h艶萾h&iNi>iV^if闦陶ii^gvVV&13Vbί꩎^"벖oFU޶vҥkӳ֯֬6lFflrcD%^½>ήϮ!#68 Ҷo1HF NB ?]_Dң!/m9pFƬ>G"Qn!v&mAnk$>qѹAhP>f!q*l.p!^&ȈAS퍍x 5X*mAXw)Қprx8m {A @ m `kph Z p` 4k Ao @!Sqߡ`C `r Z zw@oьq ' ouy-))w JMBG3%+*^!;7/ `9i9 IȽT;wrMY $H2!YWt` ^N󨩸mQpj0t"u;w)UOܰM 鑶EUSOvp!v{* tGIvI¢v;trEf UgM_@E󸍘ͼFcg 힓6 6uN tqyn(v'G kJk*6y ` wY (8IwUJ0Q pEՠ_dy( s_`ym{R_ i`)E{opCwwOx֋SystNyyt'u(Bß}ˆbQ(uugiۋ됊0ɧh|\W/qN?F6O1xlIuEY__dANwz UMAugK:| >"} ({zG9 Xvw~QwA"z F8#5>6ac |wq)$E9$ڗ_ 28%U҅#c:"hw!a"'X yXȠmUX.V\j8w!fm' 7+gGO'%:hPr*FgrpsԷgmxƟ#"$}&z`B*VJzXojiw΁˧~ʇGr j:ଆh jGtq !*C$jx ]pFhal @{n|1*lJq,Z|p Vd!qޒ A|ƾ(G뼳m1dhAFs!GyZAǯ,+"y߉Qr3a^DqEg!GotFiCP;=u}^!#ztb~gdevTXqcjsab!{SW\Xn_#:)WTZXNBZ9!bl_`x13G^mkaUT\1hFQE_paa` @u,hhx.2`e(B0* V \B0r (u)?+`! a@B0@ATHHB W( *` cBҰ^ ގT8` ,"gB.Q8!0*` PRAr \""IhS("iFMAw ڸ%TT8pR }c(TWReR"@̡(@@rX!a NxBķ**a Y$'H"@e-o)/-e/I*< ,1IH@GhBtJ^ WX@ ܦ, p2,[v)!r4@P&HCPA%La \,yP"$T u(N Ѷ@&L`QfK؀(@ xLh 0 2@p@L*uJH` ԦCs4-0O'*W^R$B( 0<@$E pb@2e<Agf3ֵr6lmEKJWu9A'>x` @ %p=pV l,0f;\},dK њյ\O0 Al%-&V(2 з].~ܱ`z+(80w>Yʞ@2, K o~C ,^ ]p p `<zX(.R) lfdɍ"qX 1gcfc-XwӶ1Sq{Z&ya:~v j}i'\smGzۖ6M\_8wӭtKRNA&؁]0gpɱU peΗ"یaW'@0PP:&A( S1rSF^8Ç| _em׻X y'W9mp&raHs{[|@wN:#By=d#w*^/{J6ϞgT)@v? A^r\;MnL 𞗎v;^So. ,5EqdPݣ&R=~z?@WIM7G `zB3 13 9F39}'P п  & [6!F@ S J: |P@ DUT u`c   J:  >F : *a E:DD\an!cPQ$@ 6  #?@>!?@$A #B^=&$CB6$D3F$E>DV$FY`d$GCv$HbE$IrF$JBG$KJJ$L6Ư$M֤M$NN$OO$PP%QQ%R&R.%S6S>%TFTN%UVU^%VfVn%WvW~%Xe@;PK:88PK"+AOEBPS/img/cw17.gif6,GIF87a+{!R9sJ{kֵkkcJsƵJkƔֽεέ1c1cֽs1c経1ƜcsscƜέέkΔcckΌƽƭc1sckcƔckcscޭkޭkk֜kksƔƔΔޔkkޭkkkkkƵΌkޜεεΔcΔckkk経kkR{ss֜s֜sssssssֽssֽssss֜sֽ֜ss֜s|ֽsssスssֽֽֽֽ֜sssss֜ュ֭111sƜ眭s֭֜罭s֜ƭֵkkkkkckƔkkkֵΌεckckc,+H*\ȰÇ#JHŋ3jȱǏ CIɓ(S ˗0cʜI͛8sɳϟ@ Jџ*]ʴӧPJJfҪXjʵׯHWKٳh^M˶۷p\@ݻx˷߿ LÈ+^̸ǐ2˘3k̹ϠN2ӨS^ͺuJM۸UÖo>WG(a8rʙ_v|y 8g7tҁH]% |5;%`O v<0Ο}bW}#G!L7q3Ìw9_8p^gyA崻n6-mܭtB5EUgeKg~ $I<7;Ad(RI*pmdw7h>b^ݛSdl/I:6/i 8H`Ø@ #MKKO b kyxI^FO(K蒙Ňk($@\t[:}z_3$2燽KQwUʆ*x<DC L7u^ x:E9N XV|'~qG:BH%c.cM3a>PC2Jg@!.8@#fz/n(eRӧ M}+ck^=,P29#$!?nx.CcƠ 4H;lTԂiT4Ϟִ p =9hm@UۗFQAv B[d,W/=Xiw8NiodD 6vXL8YIz zxilJ݌R0_"Iɗ7N` 'Laΰ7r 1m<,f Q<1xe!C׆b|i[J"^'BN^jsd&S73)=;(8W'ЇrHOzZ;Ta:ԧNEVϺַs`N }fOi&o;Nxϻ[]*|oʥ ݠDQ  ȼ+f<)@p|& O*6k*#ʼ=ώ>0K@И>mǽU{pm<9]3- Ԃ+}Ym{, Bk~ut>s ’^ϙ덞 .vi?Aӽ ϼj/̃Dm_<5?)Oj0 Ց6@eM*[ŏ}j1X")RMt Q AM#6$1^TRH%MDRJ-]SLęSN=}TP+mETRM>hTU^ŚU̩[~VX]ɞEVڢfپW\sś7j]},Ή C"THrLPeω5U6@' 2Isg$ H`ʥ[>H@/ %?*% ݬ&Fs0Mh3IKgV52iwgAdAˋl`ja{ Y/΢B#O J$K.B" Xjpà;"Γ0ѢL1"@^d1X{n,$9 ÄHIcp0J( Q&፼S|-7,͠m<#Pv.Z6eLI&yeLMW/SqZ0l qTuG*U'y݅D>ZA 0㜍E`,}+i~G=ӇEP3T5N>O9Mw]h7'p+y">FFt[ɅU aBӠ;K<.ݥioq#ߘINEu)mOQe>*"rS>9hR^7h~+UR #Nl 35'Lw2Ƙ^JnFaN ʺl1br$[$@':՚>VU(F#yڸYF Pv]/D;߅\ff'm&xܜU>XzIsWS4G<=۴|t<<կ'}a=kbbTp"Ӻ*ula*6vle7)vv瓦u-3l;ՌaH0WtNc) ɀ<+ez1@s%:Z{"ĥ)$ZRvV[xDq6툝ɪI9"ǸhB͒BL'Yybۿ#?:P:h;jW ,:檄ʄFt#VqI .H.2r:K#D VWyMDM#U1Z%l9!$d KL1l/KґJ/IK8d)0~h AV3)F-s+,xĒ*kH9FX2BK?+K2?@P2`ʄ&{\GYbʍFK=DO0qD]I|cB7@4o"Hl Y>I."A̮3nB@C(>y>JaP9w8D`S7 BDHB=THEӈpTPTT9Re=UPHhP`U}"eU]?]%b5b-_U8TDSb%-(Hc>P]eVg%USulUkr-n}VpUDUU5`!H0U[}-O4 X:؃E؄UX>mtENe-8*؅ ؆}XoMN؁$T5X]ؚMؐ]םv|MXWxY~ΣיYEX%9h9XZ8G:فV7YZڪڨ9?X]NXЁ@( ֕mN[mڏm@Z TpZ[W5W xe5Ve @=]5VmYUUV}xWVX$hMXMZm9Ȃ(X8 \"؀EG=XU^h:X(Γ;[ă?vW5N|h.Fe{Ofb\`-+X^~f,f,-_^~b{e`.Pii6eefnNp=vQ@X@x|\g&/xe%kfc.-YUYzUUdZ.OdYkO6 `di\`&h'5b(k^g^l0&^6ftj(g[㘽cݶ =Αgavi~l)n淆 N[-Sf`nkԝaF &UWQVQ^P׎nNfNj4f 0 8Z5 d$H~zO;۞Q s?Gt:t=_9UFWpKLMtL nIN7NPtnQRSMOuQt1}[OM^u Uu_OQ`_na'_ch/Nlvc}cmk?֔ vlUo4,tWug= xDOy{(~'7GWgw;PK0;,6,PK"+AOEBPS/img/view_metadata.gifDGIF87aV|toe42@MKFʻ림⓭ȷ4fqIykwa@kP"株 V5Z)wB֛la0ʞ5pK 8(OPjM^D!ʟ"Ib4=D.9(F$)t/NE!Z0ɓG}1RBkfM"kQmMݑք7ݹp T4UqMa~L+&A=pfM( SKuOJ5[Q(@s\TB@W9L @hm15- ^x~6({9y#`f`ݙyӄ l0vL?pMfuO`4P ɉfM8NhF'{ r3]܇7ߠP ;EHJ71H}Q|́9ݜJ ŬM<Ѳ `G!Zܕ; r0XHebz_f5PD~cT1)Lsa)O𨁠  RQ~\4U*i I'v,܌&$ 'JmG!L R1AѼH& : ".k6~-iSLEHC2Nv Ēiݑ@fQzIф9*pFˉd( MEiq$|<A#x4$(LAE9E3cn^1s& Q5@hK"ML11b4vYaOt41i)n:$:2gLY0(0H}r_4?M/DDigB@**C4 w6ZHBR4v99`J@(}VMLhfҦ9Ssdx0{1#gB"*G Pҕa2A㢘4>JRI&]8 Va.luSq De֌8Y1&﹛d6C1^XIح6L ۙ8l# SAk$pW{X6UnrU-vۢ|,ykʹN(LFluP,dMirVה~MҨܻ.][gw?R0+!ޠ ,$P}3ixH[2Hp#J@6vH;Rzk0gYq$aboLnu@'XwQ&N-Jn+Xmoa #˘N ( 8  0^aevj+@Bp==) Fy o^N%⩂u\5N% )LuGTDW&\^JxW9)S6%@'S5Ŕr39'MtVFҗUD>(1m -V=9G{ue?^ԑNr)(#H ZI pET-~ܖS Lg)|2~GcdFhY۝M BDB2򻅯>m2eGgbˬ`_"J-ÁC@]3d@7k_MDQ"TY(=aEi8h  nb)}Y=սKӸm#( S% ∮:EE_X-JP& &wBQ=Qьzr'NX*Mރ D\ @$}I~HWQD/،>zTs:yϏ$6uιck -duxԓ r^@v?jj _D!QW =3'Gb@>ZGh[:I"21KR;O4x&,b1#!|0-;:WQ! XX4z~ S8S*d 3="bLOS)"S(#х7uSx@f@͓;=,Y%LՅ']x?ZOFs@%8yH r84TH~sw6H7QBm ࠜiy)y g`r  dR*P@0Ivu)=Hʹ3LJYY/yJ;36AIQZ38B~:Ljܒ6*'j.sa-s[yyeWʧ !)Ȋ pd:| 4:H:(G8zAAzF 隭Aj J誯;Q­ɣ b*:F9 "-J3aDJ!;jzrb*9AZ؟@4q zQiJZgy*By)3?k/:Q3a9-j^fZ3A:AP1\8pKr\`Iin1wKsy zڜZkr{7\{4[Ùpj{FJ|5@(*H귋*5z7@݉4aڰ٭w5jLZQ8K3 ;s:*~iX))S|jvʬ{zJkz;:i.,پ{jzJKjk˨6 3;9['[Dʸikǻ[ڢ 5 T Q 4AR:8: c []*ER P]};Ƙ"ؙ۵;I8:5ڜۭr["@cwI}\1x[ȑ;dž\ ˻z[|̨hw ZP  C:6[\ iij4<7,!]y7J9Z:Zk ۿ+lz ^<Θj ,{K *K[3 lC)a̩R NJ7MK HJLLNR=T'ZXՁzY^=WbM6 YԈ,j#n r]Iv y}c=~c׈}ׂ]؅؀؋׍׊ؕٚ}ٓ ٟMٜ٤=ڦ]ڨ}ڪڬڮڰڲ۴=۶]۸}ۺۼ۾z}Ƚ+i=,~8Խ&P/@D} p %PMqY `f    @ P@.rP f@ Z2&QN^    5.3㔀 r`#N R&C-M~!,^fP 4 8`.^=,B)= Y[xs~sGm/ⓐbP nhV~y-%^%$N3*> 2N8~ _~a!ء.FR8`M枅7ڢ-I #9rF\(r@Bb4Վh.Sp3!B b5y@]p3>Gn;~Rc){ߩ @Z`萞hꀠ铖`0:X&a$$~2 $P"%n+Ɔ)M+F3#ol&:D0 ^@ ~L~0 T?^'-(n)˶.!%oM ^_0رf4D, n)a&>0 p P ~ @` O/㗰. \#%!):1уp9O)!/a7c:/Mmؔ)4O&ClO@xTOLN /됰㖐0Z. O&79P'#qr@,k? ,( 2`XQ"ʼn # E64QJ-]SL5męSN=}%Z.9"<-DB̙6ڨ$(HJI2ӡЕFKW^}X`…sͫ2:vaԣPB-j3f ;v"AV"IoDWIõmƝ[n޽a">JGx=-(Fsm4ȑa5thx;uP'jE^zݿ/8@sg!$cC8$=;CɣAB?&#=C?1Dko%">?xľCF0 x 5l DடlII&|J+ Dh#E쀃z>; q,$ 䠔9A*@>VShB*M(+ A.E|`f0LbӘ%7Lf. # XpjR4x '!" RY"AD@RS~EmjKH pxUקFqu̴%(xK<]6}dkd.4q!e0L[[٦i @ f2'ռfHn6os{s 9@DFtDE <hJ d4(EԹ8+^J4Ok^fȴVb`Sk}^7YbJ0 _ x2i[@=nrs2+ ()@vl}HwL t%&0JśWo@S`Ӯw-\ Ǹ\*U/0X@+g2HIny,~rj bky{]h7LwzOuW]z3Nuw\zM v}d7{v}lw{w wt{ыw]|{ x^X7|Kx7ޞw| yf/IM2K>V{M`l*!NWC/ #}w"e,}F~/ %/9$98IDoh"D1 E@IBaK܏}}?.o?>䫿>8˖$? p# ?[s h=h A̋Ad0AH \=(P>K +'È8 PB= A'< \A%A2 \Œ C+"* @hB3> 7S ?0<<2@(?=ĺ8LSE0̈[ #E QE6,#UE DJ<)CCҋKn\h3[A3cʧ$ʃʩDʫd9t aAʚ 548JȼI<a> IH`Hl40|HPůlL,| Ķ,ǻÓ0BĈ$Lo\FDҳHгNUEI;'A?C>|>?ڐc<=̼D@K*Α¿ONu\C^EŔQNbNN#ΡT - EE@ $ f,CUQ E \;Դ`DCCQTOI,SsUO1=SRhrDŁCDG5||3ԯBO ISՈNUˍXJȤDMXJ $ErԍrMTW0VX@}GlVtIGHNmGP7TmpJrp5tJt](ݻK`TW"WxG?5yՉ|/ 7=ڋ +`L>AiWN>SICo@X}@BO\\Hſ*φuXv /(CQK$|.,Zz%RU$aB`QAM n< trtCڨZl H}9ˋȣT;=NDZI'»QFAQDD:40UmO-?ңY ڒX̕X:u=OmO\eٍ@Bܵ\+G0ͤי(ޛ8^ޕe- ߥ]%K؋^ ԴF sמ_˷AY֝ \4 &R e 6< Zʓ@I$M?hMi=#dՓc 2\A$T+W%e5B0Z pW#l]V,ٌ^ CU_%9U< FDLd#0OՃSMQ>FӬӫ]ܿ:ŒcѻI^E#5ڙo_QZ?J2 ( QCM:[SDFHTHI]F ی ;NqO2= IFE ^V6ǀ(NB4GPDRx`D<ֈ>{GmhZ$s :\^f뺻W{S}ƎN-NQ]VQ3D<_TZPHD q^^E]k>kLYd6 Sυo5 <ˮSsw(H-_[½GHeE>qA: 4 7q'ܼmK[_E+urckek.Y-Q̝E?]ZN$llE2UULFOY7wuq`Yߢ8@\trʮ$n  Lޚ N%fFU MgWwW_XϺ  L׉.uMd `pZegHv)}GOgjj>lPGU(}Q_8<`_77tH@lŋA߾<=dP?#3uc?y]MwG>e\B>`/ߊ($YAux=Y\k?^:F^rkFˈU%>Q%UV^F Q~[-TH GÇԹ'>͵!֓,lvĮ=ЪᦵQp&*Z&g&wj}7|:l9z\@roحQ[d>tnd= %kve5'rq>c%WFc3|ϏS?o/.G|apH, &.GU43Ae^B?m^SG?oh-&m?=߇öMt4Iڸm|mzUL0M]#(h „ 2l!Ĉ'Rh1!.rqG,i2F 4pRH,!|bM:wƔ?R(Ҥ X@OGRj*֎Ar+ذbǒ-pٴjײm-\h}9.^N店ܤJtᆃK@c1ޥYH/fY9@5;ei~`+Ԍ]0KƴUơL iv* S%`8!0,M>|LҙZuPݺ58>pr5tTSu׍gv`EWPqE@סQ*]v'` 'L!_2t{& ,HbjׄdsDE5R+ D^N_AiLɧ(d 4SJޏmHbiEq~nR)vyAц@zh{?[AE{jd㢋bZd&)mztUd,JإvHAjXʮjPjn*)q-Үn{n;.kun@bJP.znfAjs I%n |YjdѝlCJ,O)18cva*Ɣ얙:.lsK,&p{k۱zJ33us>1GD*f3z}XdHiw~@]b>Ӣ.d{pލqqZĄp"j2m Sz:vP39e]fKzAw-'ߪ>J<ߢWzg_دZi#K4W+6}*\|u9,@1'#qgkٖrV Pu&Ɵ/>+) Xɩ~D[$@ zB# NP|6+ PF(!2lP2! U2Ai H83bUH@iKsZ VQ0O,ח5n|[Z5±v#Gq~# )Ȭq<$"ȳO0|$$#)ɪ$8YG/C8QI$I' 0i$-CKc/iT,u*<\89*h[dZlxhmrQNbDW`ZX%ƘI}R:C@oҳDeIgg1;toFz cDPo36'D#jJ|D]D3QRt(Hѐ&HOҕ()%E[*ә#Y.3( T4)Phӊ G}Nq` 2H *Tp"N]zUZiN^*\*(拚| n}X:I5ܐ}$Ŵ *<*ZEaXRu}1 R,f3ۗjm gB 7=meCD!Tr5jʂd;0 eįR1+>-tO[16z9*Kidm+^NW!u}ջ$%I{Hnicj.sJA_ivXU!1MH ?01 sêC,Xx&mOΦx.l_,x6lox>j,dyFdyNh,e6yVfRu <h#h\67 @ z6*hp 77# ZA `H g>:9K r sAPJ4ͲHsuR XӴP0lZ7`Pv5 l23ya 5L>֝. Ydrv%XgXHm !7 ػ F1ӷ7hg{; 7f4[i>vC^Xe&:!܆mtW.LqoǪ5r)y@oM#`fTx#<{)R۶A2``c:!YO7>] :] 2;wWW9?ke!S$[@W~.J ̭63\e"4z8'+/dyƏcCGi/}=6J}dI/~|ϯ~'q/qxu`W =Q2BDzTNLRX `[g,JcHWBFdBYDKjSCGDpB C`iNb ؠEĉu-`G slTX:C1b(oQU1EL P~ GHCʌ,ԈpPTSǏ0D %֟tܔaTJ I|AlĚaO*.*,ͺ*>h,3UdRnɉ0 RI'(lC dAK0 M+]k@ŠJu!}/)JC ˢmtTVedNL@^>ɧߎXJϗFgAGQjVňx}.2F>l..n.Ů.5YA.m0Ր E*Q^ 8o9/G &0fn;sb+HՖF *5Źơs= .ezp᦯xȌU|+8J#ќFN MOn}6D-ڑ&l֬UoDwt(_K$+( ԕF?2uxF~Q l'xgm*8cjMO .L gKk}> 1^-Q iT0QS`I,~P Y r ohi1c,X$)+!+.5#O$GMO8/%ߪB<:-_u(MHtxEU&(CMjdClZNJnt e8NqXl0`b-`,# |('`J9pωLET'#,ʦEҼWAU4S1d5*:T7+':{vDΈ6Il4URBMV%!z,HO>HءBC%SKKǴ4MۘMߴt\N'!AB5sT /;_PlIoSoP/1:K9 r*r[]Q}Hj~LI|,xPt"45U]1TR 0( a;UaN6#n&4.0<6'v}?URNb vXp3$t X-ҠO)D7@fO>u$t`TX|Ju 8#>gzxy.eH;eZ$r~[ yB1?3C7}1q7i-ZCOx(HC[HV[j}`V 7=5Oz _8QD5,sw\65Vx\l(ovzM@Oe`ExxCtCV3WsGRKM-/rW8pB+WY36t P.Mȷ PJS_MrIǗ_42Rnj39JaP`wN@.nA=k4WMnV 2־.1g|j"EmF(>>RU7s( LaH $GS>_1 /:͇#s?]trHnlAU?1˷tAmv4Gpnd/{O,نN\aCM{KwI#m8+҉'x-R3bg<,LnEc&WG\I9 *rjd<#Pk"}ǗO)_qm[ib勤W~XQ|G$ơ/*"S%%QyWTnyI

,9?ؗ0%5=W$g)P!X7wO|SkRwz9 wm8 J i1Od-Y74P}K_3OSV{3RCUs49NLA@buL$ ,SU`8KR xmg8c4S2ف,9!Y\E9 i]syf%yr-Z;Y-G2; Nw!`Ǯ4hc6lBa8vǂ{׆,ĝ&,77 _:gjRPiG24wvq7=sp3iC;vvS"iV_E>'9vQ*l;N$_׻nn?3ӜȜg]t$TFϚ`aZ4I?[Nvxܰ)Or'}S YH i Pp"̰OdE-lq`\E-p{p,YIH<-IrddL;MO:t|dp`H#?7ahO#[",;Z|X.E68WhmY,?ĈDXBAk-i΁mK)uźT=T,ƂeM8[qtRIߡl"U6(xh{ȶGyHouXdS%1*WsgÛS' >N-5uQdӺImRf+stꮆ V%*)ԎFPE5VZZO i3Oy%]n3,xӶB % d_f}mJ-'IYXvuX7bF5!֪`M]l !OY2pb,vZ| N{K!***NCZ7bWUnӹ:*b6̏~[̩>:.G5`Z.X9͹'WV]LITS$*[0[*x@h{0ݦ.CԘ iǘ sߞKǵ; Z!WKؗwizp4Ep i\Xvf!'92@8V#K5ML`.bٚ(ˉJJ'nj˳H|۔r Nrw@ ' /LD8iq\g8NpcďҵÑQU,9\!G?ZRӺ4}j"b[=l΢6&Pfa$"`*X֊K~xRHwGTr%IP~Z}+vjֶ F:9(f5yuru}Jb~i2q4d NNhMZ6J\ڑ 1͇4穹U.R\q 6w2N]`MX&˝ɨή@II3yZҜ47ap< 5N]Bm o/+8KZpY8v% ʰ?#omIKm:#ݞ@*>GP·BߝP+]dgel֥r!SC\\jP/T-a~h0C6j\an%Ȯj @81t%xJ,62/4"{R.F?9tvW]6<f w˖zff4$ #H4${3$_EQ_%c&cB|\eTGv( %tR7`|w)*_[<$K4,!wȔ?3+GH*ɂZ81(ZW4WnB!m;1-2j C;w%6$@#Ur߶J_"w / J$ BB8er3^,:oh#@O6: IÁuw6mXP%*RE42Wv-⊰Ȋw6/?Et7C'YgEB"G &-13nEBM *c-~,ա?OQ+J}ba@.#Rg*qK1tRXAؘe$!B"\ɗ3%HQc' E oVT%yiFXQ"G VO/ 3a?EA[3]Eߵ'4(LsxBg*jzÐJyi F$IkIq à 9 R Уb NJqУ jMj4ٗ[]铬 +26 #Z !*8 P61 S#: 9*` f"0d;! j*  a!JzکIAzFR K 8D*28r8J;pĠ f¦`0 p)ð :z" P*:xӪ*e*zʩLѮ: j  @jEqj ;C"z 6 f"S캣06); YzJjK= {4:3; <j>NJ{;kQAK9E{zSk ʦ,ʢ|z `8j(/"ZR:[ TC** [7ᴿ ;U *k +ZJA!![ ;?z;۩{: ʸ ;X++ 8j p p4 `0 Xgxy -§ [3`KP,@ @k@ѯ+ gگ!ۯ۩pʢ" L;rK f2*,B\P9$ w>ܩO\[*9R`<LZjrŒZæ;1i3+f[ 㺬ڷ;ARr뛿1k{E6u| K ܹ۵'˵?8̰Ɇlڸ[ĝ|ʭɣ9ѩ*ܱ,ŝKkʛṶ [D "bk1v򫊆zlxKd.0 rTK컦z,Ak̰\_ _Z ;lmî Իћ!L }{[Ŕ -ۛ(]ʮzaXokcz77 "7Z GMD?P-H˪2,7afm`|afR E{d*l 갮*_rmlo-d]qm2̩rm`ܻ }klzM_֓ koڠ.LLar0}ƿp ]ة}Ťm,z<Jc`ʘ=-mLՍp>4:=M]}-^1<^ 1c+$ pݽY,`0>/*4~j8͠<@؈JD^F~HJLNPR>T^V~XZ\^`b>d^FAj3n r^Ivz~^M膞  ^I閞骉 ^Iꦞ|^A붞듁^ˉƞ9?AJ#[5Z7|C<=Tخ3,2qKC=4/C+Gn?= uNC' $\d>2V2tr>.C9p98@A"ZQ9'DUA<1$;um3xUV.BDO6q۾AɃQ ?(4.@ H3EkP+CWADuOx\1 Q0v [2N#Y䑏ʖ~K2`3vUV?U\Qaџ_?04AN1aAa@@ 0( >D %R,p! ^d#H7D CYSL5mތ @NQHSPF2:ңG"]ZJTTQKZ*V]TcM*6Uܾ=uPq 5}ŗ} +bƉ VjRL+;;c:tΎ567gԌW]ZLhmۆD;LLK4Ǭl]Lnƭ.5ʼJƪH8kt<84.L"& JS(K-U;*շR-d%@2?, +1zF-X= Y}ZbꠠYEm=ePF*iq+E% t;RBU%74-9~>rPx#L P;,na3b6 -L6f8M+S瓋8,UT.EY.Y:An.%eYI}rc;W1i@!tZW\0s31onV(w1Zabnalgbnůw jkuev߅Zx޽{^''v1OD d<33K+9\a<8+KxPkk/ yR5}ҝҠC^P:.PB.L,+UJX{@];^5\ /a$5{Z0m*ym~&$p\r +VK$A͘6MS,t!DHe)bzi.BltXE(Ls uxO%,gɋeqxЃ2IjgKRݽj_U~9]cvocޔ@'"E2`h,`Z-XQ Q `I%}?ʆ8jZ?k9*#iYw.N"RLPa~\曋aJe_zS:`B认.iOr9Pؒ_!-u<+E/bަz7fÔ^2eTز1jh dzo*˭ćF5]ǼmY"KE:PHH&ZA%jX/+E-M&:[P!O(HWOZbAY4GK.4q+TdI:vDюc 3&"Vg3 V\f2f s8bӄϔV 夽.eUguDI S} ${SEUNKR'v.v!@Ölaj)OU(B!s%Eos|QtD8ܕ4,dKNd@ݩrpzW|ejO5g7Pq%(IWs4|4pL8sZъ;na V;p7Cp NuIZ;fNTY: 4@I:u$E/@ ^Ecd*c T*AT{f]*՝cљnEx2&FcyF$ژ$QndeZ(` ޘ{\ M}Mi] ahJa|ڡ_mW739%SNcq:ÓY&m9JTT*x*(Zȇ[,QDWb\I2|+=`+U-XٱE!mUBHnr|? }*%ķOG Ukt;^2UC4Йb]dUϖAk`aO@׆79q6l 󤕥R%Fv6/$o<ԩz/ϐf>{W՚ֈj.c+\Th_amO$04u (QJQ{ Ϫ28 %Mpe|'<_kNduFآ#YXcADL63LrݑT, &ؔVùũRmlk}4lke9§꿯 _t!8b(oSmօ-w9|"P~jbV,L2l Mi5^fn,c0yн*Ѫ7 s_G8xlٿ1. *縪ҷ,3= G'#Dn$pS!0.!!2&ѦBGyGР%B-%RɃh$ lPR AJi)1+ TH:T0{Er:\  c Z%i&<(3ʕp@.t&@Cq&J C;@A?sLG{ǽ9I !3n&x'0dȎcȧ<[N$/H8WRlq*4HW̺+Eނ0ɓ>:`sI25QIy5/d 4!ƹS + C@/m+qdz+8xE+M)8\H&qHFQ"$K|52 I1̥2L˄:(s2ǜk̊5Ol;bD$8rÄY; 2\yL0*ć k`"M2)N[QZx6?=G>[S@j$;@!P6ò0+IOUsF/rFtZļdBtYDB`#ɝP62Lj" *1^ 3SQM#ՌHc<4+jô{!uQ @ H]D;, ;Fˀ D;30NC3icҙ̠j丶\J 99ûD ϋ,p UT50zOLAaL,kR ZTPr 5eS沛8-:ȭ:NҲPB3*l"xcĘFR ѡ8J+UC#ULl$sa¡A;MoKۄ?;+ĸ4<[s4"31S.͏Q*j-ĊIS˭*TSL[$xu*zI23y974յo?V T-Y85tհ^U5Yͷܽ-6;M8ijՔ;s:L$\%eY€ fhڢe*S(pZSZLa#Z'půOz̏Q1m @GB4"?nXVU\?Sʆǰ!P ܿؽԽE_l_I۰34V)ZuzJ~ ĎpӝwSAHٹ ӎO]s# -Aޥ2sk<푤1@--PǼ|ZY@sN KP=?^2ߊ QmUzQ T!! 4<1O; BA՞S$5XEsc>tI"7KanoLWzE] ti5+ӌ -Fr7TۡJST}\|cvp Z u0?_JaZ_fYGn"_Nz&I! o?&"φDГ Y(Tpj`d}3mō 𛢐prc'{Eq4Jj.W7!|꓎FĎAَ_ eo+"m! S߷?d3ǰ܀.}y^OᴘHa5"#\P՛532ݨ[8BFvb1ae _[mv< e E%\noO,w&t!mR}?Y˿x Hk[g?v2bPBsRg-fwSbcj_W$eRxyhNBΌ^wS-\-59|_MJP߿&z ?VL_4K7rW0<ܗMf;YrԈ'vNÄ8=u:mn(S[IȐXm뤭jR>@*x^Q;od , rt/ޠ3rlZXnwIw RyW><| U[W/ٌ*]R47M(I>swc/^ _?-1He᥶V?O2K%I2eBpaÈR"Ej̘ #G,idF(W2I e4IfM)d'@D`РF EECRMpQZjթSB-[lٯbɎ Tr5E7%5eo_P.l0ĆK1nxȏGA.YfQ2s!@.m4ԪWn}eʑcK\mƊw'{QY[|zSJeysln TC!ihdNUftN5V%փB5HCQF/y'~{|뺻R5QMA恉eO!-ABX"ZYabtr]hW]RB`%&*ĢB/(dfFY+1#Z#Ba\ϼzЃ5\qr~hXvYp—4(GMTweבv`&%IŨG[6'% -l6sލf+E?e+(C DyK%~(=)h9iYX^X`b1\p\uw`&& Er<2.2]h|<㏳,±1O~Zh%P(K xJa25tnY߭/6ݿhbhK<%_ZI4 > S g@B@ +`TW}$! U)>$U=0cԪV"D! YFQmz!ZP.;nHE'?1ӻ37~19YO>' Cy O 2_1%IXX2ŽjCw"&U=/gzUɖ'Rhf*ˈd7LQF< Ѫ^`@I-BKt/uLm֒q3߸6/>9 DǿK@W&>! )'XP)`!,ySZ0KKnˊb_fǛ mzWRHx>*ʉ<nTdIo '/|.]7JdP̹эlj37D%ᶮ %$*n}:PDD^'Q&a9t+]EXoe>Q,)rfg4vyL;4F$^$JEfؕ B):]SU"~mszLzyi7֦d|BC"Oy )`RTdˁb,T{)9!HJZs+R84y݂nU UL$<PŠ)X ꊰU8,rqD_ZOT|N[1,bۺ%,bN)%AjҶ=7j$$~e&ѓadqo#[ ~MI ׀2 XÂK|OCNPTn`]")GA lm{kDK(gJlLcau4hsVl) &$Y \|F bo&iO9ϼ444@H'U 吋![H4 `*)#[۔\b]G֭-i)3c1T}q1E^,ݰJ*#UBN^'SfƓ8\Y%E]SqulJ}{`5QLhJ&Ua=ULp]Tf㇫x"RDjTp.W27BM^k\I;6Ēl竄 ¸H7s)z~n]%w+풲WeŚY]}&29z}_B\L0KbKL-4Gp^a~?IS}ObGYVaB%l a;NJOGbVޯ5iOP\ޅETG6]QUZY4ei܇uQR4u ڞTe @<4HUX XӉ\8 $a̕AߴYF%Ia~IrdL5\,]tNe(UCkM2ݔNDy`؇ uK\ i }]֔ @h!X"$|sSr=GS*[$ӈ[^H˛8\ PՋlz^ްx! aIac9KEQҝsN\&LL"uOT6b[ 3#[olӾ0ؠiD$gğ "űXܮ"?\./fH4ِHeL̍2&#mw}TvuRHRK\xOr靠\Mݡ=]AM\Xq< aemoLE\]nA"y\]H*]w^RҰ6v*qTmH")ݢݲdΒFH5iI d}dAG8JY`eIt(yȬ#ڛ 2"pѪV)lΩr( W)\%vn[ ^P: F-fN4Wbcm:Hfpp~Y% H.^NŒNBRۛZXVo: =ڸnlK@XHY&j捗GR(ŊM"J|0޶dKod *~x+ 4Q 9o3/#%P.-&)omίNX[jGl=ݡQ+ څŒ(eq'ɩ*]m^=&q %6So툌`a&720ZeYj6))iQ*߬ m &|, RZYm#%|ĜsȞ~(! 3Lyx4 _ 2 g6z۲\RQX)|Rn$ ףxq(܇o%Qޯ@3Vn~k!iBYk>2g䄄)%m!;  s( zo\%MƑVaLOs$oD%(iN4*M`RWLe0cQ01BSlv5 n,)Zw2DOPpfY\+ 8Vo?ȦbY& aML_6j@hvT3hgN/ig8^:_%*hWV7qZ݂o jO!4OؖT-WǶ$pmbwF0OaPxnLzi{[ G4|[3|w痒{lwzc S 6v7= ОUTp^,q#7OWgl>bu'sZu\ҵFT\ Zͻ6.>^8&l)Qtt]O OG/JzJxwv g:}'ZOr<9>}Smc[# :q9r3{X+f[8;wyjxP EEFm.2$X֠;%]o깱a&F3.F4R4BekzEzL,Nyxs*:`n]X[K׶N$#I| N?7).n];뤑9'O؜8 D΁He\Mp%ӅP).LRKl[|cGc &ܮ[$_j.x&b,\ed_pvz)vz&y~ai7RO[,(sX}9@kvq?{<Gz{g%Bx PAڼuMIP-Lls*:0X<]_*Qޚb11ûjx|Ew마|wtiTsŠ+H93l(<3ȕ 4YCpS[31rǔrն} IR]ڬl{mמ۔V7,׭m/EL׬[zNHÓ{NH X:nI+ja4H-, eRvhRD|DadP"DuQ`H@+JibS"OI D6jRY c\`}.l6ğ!%oq)Q[v7z}o:{ q&'9cP{D7dO-VcڢhzG,C8%%(J^BM?"JF;QRZ!(xRi XnIbg\,{30~hAC{F(bXҙN&,.|`*T+)ȆՄlv.Mj{! @x1Ph#dko:NQ9+XupF5K* Z,$<$ Jr'l%4I"NBDe2PU6ErCSW۴(6BBNy4ᅍ|wFqL?@m[[@!隂 p M`Bf6@K$*ڙ ˓s:N3JI;T%wɝPtn< [*Paaf*5,%?TKa,227!)|PpE,BcމxK#ƶ<0%!?4{ QDaFSGk*Q*N:8) # wdR> l%oi8kHsʠ AQCLXFR %]"!tz_$/H~LL%JLq>˕S@!Y+\Xn׺ձ,LHlBt ~/GL#!]q9f9r:- n["X&$0XWeY0H-LIG擾 [h4 cN )Ï?mVK"rh^Q-Sk# ,9^7:"^\y24F#һLEB$ }E[9oh $%qiow.zɐ^4mqH׹7DLCa!-^ZƄ^·pq'ںG졈R$8tV~ 2ie(*xc`C DDשK)kc+[4$mY%[HsP؁V渝U`-qg=DP34Ֆ&.&W ݺ$څP?‹pt< L: V,,|E!\C"^^ܳbE1_ҟ;F.;L}\ۋ ]myy8o6b:BD F]/v;qD"k.:G#FKo xN8ݗ5b9aBa4yIHnT\ iK/H+B{ xdFMӓ ?0br$.:)$NrYv~T!BS g}lNWt:̠̀$I / 1lIFΪ%%_:8 fT fj;^.^o&i^4BLGElzx,:% Soo@ `)m>0V ɍDHD!$tZ!N! KBjP` A6`T墥/*g&   Z$8E&LF_>:G`<`@h;VIb)a@' `knzw~ bz+SjI!n !ɶpۼțNuh`FFbHP" 4:ڎ 6aO6,ZVn8H.i pe"J1*+]2K9NONgPFhdod륈f"K>pjV$b>Z%aSvQ-$ɼJovF6` /nh$44h.A!ˤ6M51 /2,)(+r+k &RK>gdϝ.GLAȇi1thi,%ɺ͆iDRbzJj& ``+1(}3ɪ# 숓DȪh b)=X$ `X`!Y ڑ͔"$G!!f 0/>!*ϴjSkw 8"42҈:OfQO/aB;ʬaF |ZE'DlJ"*.qKE !r r}4$8ӻrngD$S+X\T,?P׉0< da^W7ѮWĀ:maKA <ԲLDr >jgŕqTlOIJ"~0Zd{>龾0FJOj\iŕBwjoZT%)똙U؀awWre!lX!@ S juM1pC qB.y?kE 0"y^=)!^N[#DP 6tdi+.}qeXr wRœYA`!AnsytσI: SZapShܬSn2atx\yV9:K\%ɿFZ x8qkdm_:>ĮД`IL\vQɥfdk7-'%+zꜭ ڙlY:f1U!fӟ A4aí a,GYɡQCHw:Cg45}ckҤτE9O#*{i,6\uZJoMgpWcVa;eҹ]5dGxwW,gP 6lf:+Yq4)Z".삤XӢ6󲄼۴R7n&k 45z!Q1=걫xLO`V!jWkʹ |b#F'܎]-@܋Йt*9I{z0Af4@ Π ZCєij RjSkoQ[4/c;;K^"Mzܲ_[3-IspmSi5sMAvI?ǵϙ/\ 77Ɋ>sySg< ![;=ap!`ҧ#/0 |?q)9n3Mr\ [C9ZR=O &ʡD S˿|_UxG.:_Ѧ)/R-`FLtduVLDiG*$$F#Tc[xwU_5F99&!, Z:o bLa;M}4ӕ{mן|N{j ;p g5 0H<9:jٴ]KbǼ{~^^79rgB id'"Ho.HOf w*Ǐ@<2ih*u~YPB:tO/F%rR*`F/mɀ2m$EBa#O0q3eOK)5ɉLEU,8~ YeUV 4%Ac}>V(z_t)[9$^k- X`O.IbY"I*~)6UYe&Y$X™gfn r"Y[oXa&$Zz 2Gtlb~ءHy@awчnal1 ?UոP!HRkFZT `$LBHal T'FluBL-DB<(%ףY5ZHk\p-\ASuX`b Ifd&hq"tvcFɾa"h^|pI/n4u ȁ)vqz`G$w0҆$rA4e5-HK",+$,Z)%ٺxDɴӴaLH*r˸4Ne.Waow_~XR^мVJJw̗~)%e709Yfy&YqƧ@uxaa2{ӻ'd:q-}|\xa4"nGx}0=U UE Hd6 "@[>R %)J2kY-Gmo\ G)DsaH[aAjd,dQpt9E,{9"0qE-G^G`Cp7kevgH2ؚ<)w0Ї=PF27T?8Z r=I !/(,IhR ChNʊ (i E";ZQHTE\DKt5bPx3V:(շpnW%I,Ѻ&)-nn+*Ky*]҉#-${/' $4GUF`2WdP ᩩ,L;Ab`V`DTeu}B^ၼ-3EHnlҤUֶoFʬŚEfa<`r(3>~mAF[< dy꤫]-&^`&A)0` (LJYl>e9+*KbW$^bro +ԳaPDM8pۤQ4; y+S ْ*z &9WoB% ewͻRhxhP;@A l(vhKMbmh3dr7 ʰ7 ){(tI`O!;ݦEQ9Ͳ, (G J Mܢd~t TKKUw -!wڊz!<;9h][ME(_tOvؑ^l[]W2Lx^`ӃtOEaDGb0d-%4Y%,lWg&`rP8Jdy7w"vQ܆(x(ARxDnI<~4 w`؂7DWqWq䥃2z>Rgog qÄLUzMIprW|MaK5`Yx8/[Sj`t"FOWX7[KdB$jp82!YuP|(l&&`rgp'l&Q@lyw wdww@6*| '\Tt&pJP\ afi+XD$P'L wH8Lt|"V ƍr#Xւ>D#`}qEL~Nbav~x%qkPGYlqpl`lme?@fdIIa2o5xvdXI!)x@z&XQx ovo>R@"^Tɇy 8 px+'a^|bHY,~ : HhYeDBSʲAUxVc“"L]Rq@XaWmtAr$=XFH~T' X'&)c &j0j`l˃kG| 5R"ňNf={O!1r'p١)?wQGxo1? Qh&'h6p)r42zə  FzWE&^$y zKgUCT-VwB"7UÓ84F$W 9WgF7f$GXz:FJFY ku:Y&`~5&Z&tQ𢉄w:/蓁XDm{` 29<T95]\JAf0*qXjr g+'Gv@ǜd^oj{͉^MH91)PYD^L Bgلhx 4a$VV]I`9Yof aKIT#Ti#kW$QtQk,HbwHE&: 8iL J9l?Q'‘fWc&"i?TBH:u,YaBs@~{ @vrRR^w_I_M=('?y,Z55,,4hK#rR-]#Wa]?'FItHOgk0bcGGIX7v xiZcH!mm(zE!!i&?5HGx\&od־Lpt`#9KCĸ^g dU]P)8HX!Eyvwfzy-Qٹ@[cMU)Ws.h@*[kfB'Elx ~DwX+s ra1H{ԫH𡁨ZgX;S[!wѶӃ=@!4Jx n4cE\r3)@2Z"3~@b"ܓ'z*gGX @ʚ 0̩ALlUCY<_Dz MӸ8)D +.:,9 4;T∾?2jddb$L(; &~#[vLPwLPγ*gZUHwZw{y2Cu'Tԣ]J>uE]]vo?;(PrcG|00\+G3 <x* {[p\^W\ ;,ԙ ,7 B9lzץ2h'5tC[VvC) |f1nTsD$HE3>ƳsbDSvUM'eb7h?%lo2l5Ena*ŽE\х0?&xvУP SUqP\@ ]?Vfs W=RLƉɃjHLuʍ pӦl>~֦z'M.$V{:Qx3"|+7ĤӈBx+4c,(68AC6z||&" 8>|y[]29#Ft+^֨RJkCZP#1yYTvo`~V_F`W|P=HAcٙdfP< q'Qe;վSa4u5H#**Ýg B"oUשA[9|@3)K:V>%_* D2H+G,.쪨7X-[X#O]$*~u7T_Y_o΀mb7̦c=U|E?Iy  ij {P,d!=qÇω:gԹçH# \I;)4)K;̔)M(OI4УHY4ӟ~*TիV^k!@~ʴ)TfRb[qΥ '%x6M_5R&J xpClyf˙0kܠ EQCL I"ʩjd)ҬJJi’*L1j+.ЂR/ʋ-NjM6-;lɔW9#A-7 A@,b0Ar W}#JQ` H]tqRFVĂ4$(=f#ldzNc>**bj'2t)h= Z2&jMcY4ҏ.`8i;YSd6m0#f6*mb:MRKMgfocͩnwx* 9Y"DI*R\|u!;3]>h[ʃІswsI]\h AC$>%`xC k`4Hr"lk! TiCZ)9K8Ha/tZR&]-6Z/ NɝJI6 21&.7] ɡeFp W9t6(9YN@sb}Q@R.>9!񇇪ˎj؅>d$$PD(EQȊ 1HA/!} +LI,QK*be+wZ_XK>kw`/,j KM7(B1%)e.Jn&ɒK 7[Nq8g9NNU,a;dQhu@խnvPB9>xWGFt@Ä9 $$c%QR)!mBݒb!#(:V Rh5cG\Ԣ65*cJe SI*fRD'+P`gVd 7ͶnF12iú~ w-g91%( ! 6:b|6V@5Ⱦĭl%2lC*F^bĆ.ђAf"J{1bH[̸xqL4)[N"]'ҁ ՛RG噘TYEOX{`SP$-vBL]|S(s;9a$(,`+gGQ:4MyOAVAkլ3֞bG|k>,.#L̺C2FCAP߭[<kGRF`;dƪ%vHQt PU *$kCж]~cigKڬ(mNԭgCEN Z 4:ItR?܄3&hqmnCGlz5"Min.X58}bjΟOX+ .TZ@v=Y *cƄw]u̠^.`R=}Gw(w%\v=u8df\LNsRFo]hRҲy3,\_6mfl\5:-F,d[eѤm!7 -crІ3\ַ;S9G8 p*8wtw&]:77/0Szvݓ##6cМ#; VyU;6Bڎ"$Dۆe /6 32+9;{3 :(*Y2%CۥӣԳ)2=ቋ H`B H=AK H+oz0R #$#yӜ+"b>],0(#6;36[9ʿi -CJ6۞2E % t*=; 37C *..< 48i@7Գ X4$j&3 AAJ&N֠+!35 J5;j0pQ©0F:34:-ay?9-b;$C:ɞ=Ñ"`$C;E;E:iGG`HA2iط m>] n:Bp䬄rԘ#:=-:4B;~tg;_;H ?J5)SzU ,JLUȂ4Aȝ3 ;C%4SDA b4J; ǠKܡx n2>85:'y{F(itʧ#_#0۬aJJf㐊Xq$1) <Б9{C3˂Kƒ5?Ph:Ӏ6"εqA8JuU^7L6TLt<@7ܕMBM\K,XuT !MZEKܲEϪi=Fd 4N }5'K,u]b%1Ç?N-~{,D`XQ}D22$ Bw68{HY2 aF]P\=YEeV.QQ~Q t-tC&$F ̥}Ub=Bdս֔fF\b(>KMi_pM?H([Qpƶ%A)LcX0KHW8'T%.;>0=qĭ6It= ;`Aζl ܭlEBAϭ@h7 Ce+ a'q<]҄E Ca A9ݚAXX99^B.؄i Ƀ9<.a)b^ bL+/Tۓl.j\E]a;b,a1Q>u9\O:GfGhryFlӹg21ts^/XﮆDb+_,Nn#J"U /UspCY.|v:1c}45w3x^]躣\:`۶}*'6&%X@̃GZ< w.݄̓JYeT 03\X{⽪wKEldHlT[^E')J>}G,!,g=f uy3py7gvEgq/](p:pd`Q肠5pW`88x;C}7 -ǭ\/?H*)(:hg|.Pg@@ "'BLH ::Tq#ƌ sB yqG.Yy)%/vl9RfNh'&ТF-jQ;Nu:tRTV:iԬO~uH,X;)J(Th*6-ݺuK^EyŒa2x1ČK2ʌ*cάy$D;`4ЦONz5֮Q8*{7o6Pz6m@x 鎛5n@ϝNw'3|߃'xD@!_>ӟ?}|קI$Uz F0!PRORNqDF!M "< 'b~XFvtsQJbH/9҈N2uHPf2ROҤF.D0 UoOaUR@q$WUYv唘N9f[b[uVyu^~I^x1BcAeMfeia "|Xb hjlTF*RE[qy Gvnx]uݡ$z`g!'z"`{|A^z.z* sQȑ&YJ2bG0*$Q!|B" (tFo8P0F"^4!P Y#O<.eOQ5uY hq&Ul`eVeZdIu^oZMMSP1IB -k) e0H*b}[ ! ʲ!^h\}ggH=VCoqs{Y=DtYbuLea~(F1#b #': N,B0DܸQbwlA@TOϏdC-6D X J|.&)6,d"%7K~VaT0b0JLjlь,f˫m/5S]RT޷X[; q5HcOai(hYB$BDB&1") IEN<(a58s^ XFJ͒KSIM_tmhjSJ'rPG%`aŵ.fâK<2|gzФ V fTdK1U}fu { Np"3< O=`a) s&f6(j|@܁\:ء %C!>#Kٽ:x0 -H ƄaF9JDbi m%4% Yik"|4Nlࢿ.}S^VIf/**Rc^L82a "pՙI3U/]_RU 0<`GM}EnteN>UP<‹ ,`9A|@$kiࣹŮҡ"N\8U0ٙ+)!Tbd4y8cHdɱ_IDr!.mw(SէIiwdLh>a %HL頬7|SuRrLgEZ[&MVJ_x>9I8pPL5 &[NoZfe$u:RVkV T\X9m-蛲 2*q k`C*b8X8!ca(0 '@8ܷ0EAk8E SQ噇oT^# e bC3'2J0?7fUhV-9%?`OAtR+Fye,! BuR:[uR3>/X8 #7rhl՜q5m`qNbG߉KUHȁS`@HpR鎆0DA^0OltH!M-W o޽PI[˄׬ϘO\$I 1%Zw aPҦx_<}#_Mݩ /mqU B[qEAکA \֝ 9ή,Q4\ 8‹ڎGMFFA Γ 6TkiV цDXVLKxO pbޕ(^4!tTUME9 IX^Wy y!¢1B!Ρժ-e#AwX]spXTS-{`"]Tt$ X\B*>í1Ƣ9L 0l$ zQQ1 =0ni[Beƥ@sUb6jمTm P:Vѡ*|9Ue\ {mgT͒>J? ֱ_aXTPPѭ)A!%s< Ah"ceKi89`IKN_98Qy @0 ʸ dēoyԾ$G`E$BQ>m :e`QSf/Ye ne.\ T[xE8'NI\_pW)G.A<2,^Z!pG\~_<>%^BlP##ܘ[ )ؑGd8h`Evuf$j{،&]9(:^ 0B͛evUэc%1H,.LO2kFlđ:%i ,H%Kׅ\wfyD]5I9*֘#Q_.O< ?1i0.!0īr~s+z Uޫ XVϟ*q|R_$*(j atZ(0׍ ZTyPY ^AAU Fh@s;o)XzLf42 YԾA4ApA!boo1-/6MșƼhYF Јm8gD+AO-2뛪q$i&KlAM^!,\.ߡJ,(5jŒ*aӅl s,Hr. ݡXUs5@ (K t0buH( |3m_1P|s]GNHX`AAp!$͆R'ds#{Qu-*m +@tEtjVA;AY V$Of$W'nu*M;0#8IR,9*Ƥx#B wwW{nLboEp^cx8DH0åx #$gK,)M s!Z\*iaHdzu+x7&h~7-0ע#n%+ }du`c7>qe3g3Pdx TAs\8!SsƛFڞxg1)EiJM|:hH"C@48V- / qg#\\X~;R 膰5ѩ;uN HAyϹ9I;oSPЁ[mbb`L$#v<8oخrd5cDbz^;h/!`-VsʪҪv gWmqjz-Đ|L:JFøsiBL?ԉ@?,LErj%l;Su>B7{ 绩Ưgn4pAA UT~A=V_a'Ҏ3{ *[@A՞|D; ye:μ0¼2kFIiA8f `o'=sDGD;U:UR2ʁu3nk=$''4s0yr+%>T,?4hLPnQy:LET QU/Ի[XEd;b뮾{f4pZgLpA̐nPE #>M\QM)r*5H`+#},R w׍f J3`*b<#HzPߺhN8\N>++в y@ScV N,CO[' -4A@C-BV+SKƫ%-PODW׍7UKծ֭;쳟ض~;=>n?o[>TA]78]r#ܠ3ݶJXb'J_QHJUwq܊&$c'LhWF9h$Nj]HLФd{lÏ%494@hd s#9 B@##RG 2"i@0fc|R\ZJV[+[qc+tMkY`:@=Z6bX:6,]=;RhPo+8BP ؐ}j;֕*١]oBK(CJ{DEaW%9!f., &]P\ Kɜק=Mu1D5|f JHC!'7 *5@pHģ Uq d VDj/{2b< dKV\n'jss*VRNI^\Bhэpzh-yCPh8^R ER9&! QT%I8R9!r/}9EHQ90+^4q#/"Ro PR:ŗ31M\Q(M{^"&4MhB ?2.iNAzŸ E(CeQ&:Ő8;HΊzTLD@2zUWVTS%ay`e^KD kaM:"}h% "7&DB|+# zx]rң `IA*P ghЂIS (iTWMj\ x%]F87 MԠ^j ^g ]p*0^(nIbG "c\Vq@ `O (1SjCc e h E5 &EjoR`$ b@і~3}O$Kkb+ԠW@.N Iȋ*$ŪBC$08lo<;6l##]1cO27.1% w̱ I5OP!BO#$"L%QDl (CG7{d!vGl Fʞn % Űb o*J8 `rVLwh*cfn.tNP@ Vj ހ%h (B)1 $s燪ioҨ#vK d%(<` (Iܪ` 8beɌH%V.H00σ0OP nSm 3-s3 [zEMB E* B`f"BrFb | '¨R PwXB PRDDd iGPEҠ|\>W`5V"e $ W` %XdI Yc >$Bk`$ۑ@ :,1n@b +̲h2mNɚcuU@"KJ08oVp..σ1OftI!sa[H%O21Aı3q<ǎ4UEvɴ 54) 'kkԱ]7k9`UJ:8 IN# ^ &vrDJ#aj+<7US |XdTpF.2S2 ` K,9O(m) j0B).n&Jj ~u, 9C=N-\/@`@lR_LFu]+K^JtT_?0}tA1Ha#VboPbcQx3Vce =VFOdKiLMvw(Lܴe E.qԬ^l6O$:ǵhG k} ul`Bn9`KjXRb&O!5LCM#4 ү } @5X#FJ 1WS΢.` 3gL kkC&A4W0 tCFm.\mEvWC_2inQ2wq7b1c03c-?NyWKHxWSLd"L/t6eC @CeH̷fdhgBg"N : 'p`0lJ~Հvj ^ %Ԛ`evzJ38IxW# R󌴋莡삅٭4:-ER Iop'Q" l.Fwv+9Da6 h$D Dvc̕L ##GFg,?w;xuX=IQb "6x1tx8瘎y$wzKr"K$s ̐7#<:vRӦ%y'(y\kvBʸP%a:4k#"B88jaX J|NcҼ@"@43/+ EGw5E}.0ELc Pj KR x\0Ga8 B *dLjXՑ$@b^CTF1pt :_qga1[P"//S2ۀ+`d,9qyvU@JI4M6K{ #bH6 |}\1%HsuO]$8Ss:sd7 8 O;#@ 8#cVCbAT˥Ib wu/QkKcFjbfk/.4S$%L8H}䒸hA[avfDCAWbؤxF7[[;Gq%=JHXJ'aOY xx2mr;my4v;L{+1/ Oq Ȉ6v@L B܌71r$ F"r*iCA2^%8PksDP"M fW9P1M@#2V§'i\M~Mħ|6BcT@R J$ߒ d+("א5B7*Z/;4pGR0֡v -Ba13N2Zqw #4}zAM1.]:O yC ĄDPFFV2tBDFdFZg !\P5 MlKBXU l1TQTU.Wv+(g'ۑU&:Wugs8qbQg_+utF9iȆ^5챰ՄN>IjA_9p^@V)}-NSzFmmŶLdyUIyEہ]F|7`յGl똈2D t([$ מ8E.'8AD`Gex!LJK*C"% iU]%&D-o[JUknO7&D A 6Jš7gDDPIJ ,0SֆD-&^W9pf SpUA$2 EGjfh5e QL5Za$ % *.Y| j񈳆aq:Dذ6!`7NW#p<Hcu_S~-dA>rЧ19?]l__g2!z`(vȂ/ :HO "?{CCdJ> ^ ˆ5(&`Ī'=L4Zy%VJ@ L9!TMH PKr✅#$S0qyx#X-uJ*Ϊϐ S(0qVXf*B fHAhȃaXF%9 (%(F["')zR0A:&pV$5:⣣FWеD_Cz/YfGb -f.hbض YӘ4Mc2]Ck(Ϲ-LrWB5Tg U=y d Ha?낤J>2< 5/Jp = C+7|;6|t,{M%t-%%JOQtJRFd_и7zJ +:Ta{`:^ЙYNA E5kh.xF0A0'q.UN K8BLq#أ mjCu(zPxYr2u襝G}GC.PS mfsմPtZD&2V\Eˍ4Zzg#{)%-K Ʃpja|!v (2"D%Ve)rpT^?1s"f^;-ep\f' ^G2V/%>#4KW PUX .k䚅8)>Z%h/Y՜!K浕G`޶Jĭdg ]G$Nގ 9:tt䗿$=Ä Z9}}MoжW@]CHnv%] NnkBR g(8KIyM䫓YD9]CQ%tlDb NMO'ē/dë8jW§QBŭ&pAX6MfFMVƼ$ ^p !Z%'%`e !Hˏ­8x " n5[[S u5u;%Wʭh=s?K3jm9c|jߨFYo Pg2]STruFS^Tsq9uXR2d&eQm&aw 6\svN{Oa0_mG+e6L_/e-lq^OFAxdxAFba3MpipxVUwywqnMphFDc%9""on]H#dPz 6 v'*1L{It5uK.P\^acPqzz}gLU g R"gbh~2MM0/|vXZwNe2HsB72&]ig;2&c#nttRrjE^O Ud$PX&4k0e&@Q6Du+6&'-aPQwAq6CxlK(kA^We@,'yRTF# up][RISUL8+F*yKOQFTXHrcI?zc<ٲmLIH3D&xS'{'&'wzP[Cz@MZ-! B?1 3 /j֊[ff&[Z1~s:wMbN}Hz"&oҥAA4 $XFՀ$VButuHuqoP E*TƎ5AEg&~'re/˴ W13h@sfs:7Mj! ;J8\x\네IX¯OZ$TZM9=FӀ#^)*@B4sa֨&ekrQivh~:`.A%pRgb(YQ+R7^O9;%T>֐syui3F$z1b4#QQ;^ uv&Y{TeEp.A^7 X<(&u{KDQD₡8&{rA'Yi$!%hӢ5soV?s5Xs@Zr:toEOKBX]4ʘid:4uj`07QF+u7D*8EVSI掹J`^)FC"mJ@z:%PB&xQ@(6=tym$S9VŘ$ؖ(nE+4* w9j9\$)X{0qHa51lBkbmksd12W)*-3!~Z~/Cs6 MHM.j ikKۯK] %kWWI*KWuԿY5b,XD`~Bkh#z2rj6{6EYDx|:6MPWIۉGK ۩WaMr^8YVa&[FIauhY'a7_')Y8o grV.[{xl N_Y1᭻'=lZ/2+[ǼMeNU!Jl \.l+D2F|Ģ|Mt:U;yoY"VR{o2Dz@`;Y4kp9bl»RfD'k6bu ZBmTmE`G{upkIs$Vt@$geTS0q!,VKM*W9aVC$j8~OS%)H&7FawW?A@qWA`l{ "SM "!c֔ggMf!T[,xA5jwd=Ŷ,L\H\IϬϺXJ'$Sr]TzO(($UpY %^WV%r2C`hқhݵBT,ͱj_zp2҉P@T^8„-ِxCȴrn.cAcdP"QYF۶E}pjda Z7RW ]?by.o.%h˄k:ś..%n78OpÍ5pc4^DC 66,J(68(& %;DBɦIL#Ȥ66R B"2+9礓ίD:&*´@P8l.b{CJ+0ފOŒP‹@ 0L;(0mJs-X%X4-H 5Uvۭ߂;и[s4X&#^r$Bp 3$ \.4O"L# r92P>jPb=P 2U<ƘTJxA%SJ+ S- F (CF q 3Xq!2(#x0‰O+z%(KRikK\ 鎈Y2$TCIʤYI%p *$lߴޓP@54n,FTE~*,/0$vӬF4Au6E5`_-~c΃wn[]bg"a 'B P?AXԭt"Ѐ傮%E/&ӑ0 @"BAÈϥ?,>lTDT;Ӭa (H"HD!/cHB~$90P=a mhRH2A60 ?)Iv3mdH?j0%)ad8íI`QtXXntb1)b%4"F62jMFfq.WӜd%74exxVA byJt7}%PË\f1]IAth1aߙ[Z~>(iC{L"D,v!^#|dO^ 1f&E@'P-R%!Cb N$ȑNu1=&ID2HCE&1giJSt2mpl4g8mx>n|8#Ilg<'GEI%@6l%+dh8&:c Yn\= (2$bJn S(CHB<زD$IxІB3BL!?h8)I6G6"/B5X&$B(݋ p8 XuS| B$iJ+fA b  h:5D2lɝ1@hIX#Z:: REVdEzEŢ|a3[T 5,bpxa\AA`Y<ԕ3 BlEȁ){()ܲLG*(h#k.e9PG[7h2(ͣ r!>0&:mZVªA)R0:$8n(@95SK DI.qIڑ65ɯI@(X@raD6.R ;7ed-g\("ݰƊ;l='.S #Py'xlI.ռtcK)86;]"Ҝ$pTH˟) T sp[Ec?Qc0-RZҼ0/]$2-PtC7mӳLxz,شŇm (H3FϢ h\ϔ2!;8tsQT MdH(B-T쩽QeUН(P'˷Բ.[5G"=T!*<@H%1<PQ:kӌ \7C,#2 \d!}塌-WSbi[۫0庁53XRTc `D0 z  K<W 5 0I+N$ݚ0SX&'.,[X0؝a(,HӓHSoXĂC^=YBrTrT7Ѩ<Ԙ?6:LPZ8 2L+%.i'0ki\?2X8z.7:=CCCt%i4PPP\&կϐ6huiK*<Ρr( :&gHĿebZ5wN+b:0cƍߍ“0n$xJ}XE c"z-͓M$ d1786`2:B5}4Pު.#)x!.s2K9隂(+3o췠geyГǫV86L* `I q;8ި `az81+g|מ I WlW+"鿠ɚ`s= 4Q4yZb0gհzgLK}Qӻ[Ci;8Vᐚ]<62C)@h| ^k7ʩ6th ͹A]YY̑ jYA՘T%δwߘ<w Y8B=rC(#;d5i)&G{IL>Y`)L!BGK8p% R(2"Ov=.(OtTi7:+#kTu !^ҘdMSq" 9Yz  5 9ɧv 1Y3Lɡ:()lRC҄Rw(5~!r5b"#G xC{zgDzeYڪ;ȍH7^7FmF^qU!5h.^C6=$PFazh2AؒaH|[t}QmLZhq=׫@>XB$yd < pN68_/ J ڸd=wnԨ9j_ r.qϒaߒf  a4ז a1'&5E5}0 xxޠg$#5{+'3dBBa'bx-CW,'AKʇ- fxjlQh=yՕmB!dY$=蘎k)"EpDɒMTiȤTh"ƈ,)Fs mS ~/n8ʗ371h@`vll\=\N.Z{J(}{De`FFxLaUSxPM$FaJN _R$u")hx-^'_ TQ9/ae@ %DT4ф@qDc@B\䐃INPEi)PYeDFB'XT)M,MޤS зƉaEQaXӜ5^k%(ZlVjO]^)bze)eщgDK.jil^k [kvV[lQu|Up57-ZAua.@d=-MpN$mUսP@1Ƞ "``+J!>Hg{L05(_Q9]wX1S85G;Pf  4R\VC]NQ9,*ӸFA;F.-M{(R 5w FUZbPY!5|^mp+btي*Vw t-xV"Szf#즹,,|w g-mѽ遅AԟM+-{p 0p pp@ SJ)p`c'* -:jt?mANz$1!H I0] [pBP O(AQD 5PjE$K@HD*InvdmePxD!*k{n1LT` R5pC*FÑ^x%^%T~d0+y.2^hEW#,G^vTC fwLXK{u?U.ySb}bFRrAG, "[_跠E}r2ţ1&23R`ݘR$ 9%'I4K̖%!/U(a 2s0%. 6t$dFҐ"$d %>0%ZOyP N(⠠0m. \d8! \2RiQB׌Nr^cPe%V,SmGF5V+onWOZ<,b]J'vAH!ZiBڧLA18aFHE Q9"F lﷲx/1B }6a 7@E"A.(BAh-l$Q/D!hै4ףfЂBt5' KL&M+BPd6ĥN5\OD&J`;b kXXӯ4{*^1v^8Ӫ0QC\rVNmFW<.M]i«Pkx&K }vV^%-C` ,KYy̦5sL4iȿ|Rm~'KDƱ j|l';zE\yd}yK.M 0 n0)Le҂ 0| Onx@< 8,28 bJm1 TX=WO>\FSRUЁ v^Yc^0 RJp`!/i]z{>UY/ d~uhN&{|7E2ʻ;e|_ 22/ybnsS6@ C_x,(&:'s>nu 8Ie9Sq=O#,4C^;C`r1A WB 0A1ChՒ"aV+Hn>\b w8\EKd+@pt~oKXٺ,zU&63ETt'C؀=W Ҋcn/i%M4_xצ$%~jC28ؐg^Udj/]>Y_SzNNȶ:=F23P$ @u-L 86c1jxv<ڙPyRH.D%APGXw`SPS# tYWV#0U0ؑA=Eh O!G„DB 'DiQfXw(Hk4`Ť}*Md$P^S@!Rt#ę x#h# (@X*b:'z&q٠M Z>1=E)|(qV-4Cp@`Kx@A@C$E~[e H `-A@d !hnn @@@@p"D6$jGN'u ^dՕFKw!VEvMgMfbO^K8ige2PIu)vԈL >hZzSᙥ0 >),8]Z&Ē,-B׌Z >ݭe"=0%# A0%<$!|tbM܉OY6)̷ 7VT RI Z : IT%gTlsA%ꅤ *Մ2KIak!u$xƤOyjbѠ{bOnbES4̙md 儌QX:>m֡k~fehMh Mbԑ WDZrxdK<O NmV N厘ͲMtK$R8 ,&\k&řZ @NP&jP춼!^щ~,^IjKvɲ$|`lL2_ l},񆇳Icňl)mM9U]ͫo0jU @F=k 9 X E 5DNZ P 62DJZS&Mq=9ށn/@lHQǘmL@L S ܅Y/\ȍƂnnH1$lb'r'ʮwdvDu f\./!.L/7/dW~2Kd ƈX]Pk҇LZ~m`e] TAAs! "//@L +Ty @=ݓA T/q cJdS* tu(Y@ [UzMKoM}o,J.n#ՋUzeZL*gOvl'/1L/LńYj߇Tl*o:E-ɨS*q;G-3 |G8 EcK 9^@tC!#D06,)PBZCKum| Oq%p1SM KnRpf[@ gPW\y,ǮPln ^91u,7XHJswҷQ vĬuTDyZq>,kz/@{ %/jBC/QJĈVE +Ztm* ;#8 @lH]uD} (A@o.WB?XrJ oSy%LYюH >ގ(Q(a@\ @Es2 5KHpbY0m,vFJlK_ˮ_KXCjB}U>g0!?kk#ol#xp v7wo Yrs}HX2X@MAZ AHB@ 8s5G%.OD D,>02H #]WLd|<@;P_f0,udϋnƜ{+:$5DK6dI$KN67'_i`s&,KmK3e_Gf/<u.m Ւ3a9O^SO/|皴Cb&:ɋ:D9/{4qkHez !W  d`dAXlx:5A<)iA$|@DebJ/@4xH g(&,S5]0jĻ +&Y-aPIn0ͱ ƾ8ɦn03P;OۍDu#WcVKV!6/!6k%FRcDs4ǧ9Ρ'<+q tMyo k@m4܀ @Iw 4 px)74A5= @SAT]3u=$/:@8P&La 1b\$qċ!B PzPA4PXR&qdυ$sDD E"QMK4]3jӡC>Ù3H+eK@ eݪE'BD{@o]$H8 'VqcǏ!G^ hN3KBY"=tiLVj#a#ٷqܿom; <RK&X\J $X;w Et(1$:)¾F|E(i"_T.Lح3I&Ԍ23 *h"B2@I:h@MLZ ج$*v" xJ+J &hУϱP%(*J뭲2`NRKL- ; 1`UVY)S3 r˘L֌ aS3XوKhn m7g.{s΄:꺳n;$\s O@>`` l8.O^&n@"l! y@0@P B+XbB'wPwsء?#":&"xuHE 5$*-(#.)r l,!IE빳ufBZСZJQ[72j'>b nF(IЖ(-!Zt-:QKkr(2`T @JV ;lI/VQҴΌ;Vه56dI+ڝveZ#\﹁ms$\B;Uuؙ=f{md'" a 0V =6H>2W zH l 5@ISbVhh\b%`"OGT,@b"$#MB& q NNғ@OyÛRB1щyF)+BSqy\WԅT!\^0u$\U:=2([I:L!!y%R6 ~IB6Đ8%Q;%@TjL$)|/ l`S&}/壃$ VHĢ%`x?EyvUI΃^KIPR n~g$hNHOIdy.F,,!!X=\fXd een+B_{/xK^aU" 9ЙtV $/pu8RjX]^!pUR{m" uJҒ<j}E^ѕVLŠ)J(ɩ8(WtyHG'BmPQ9Rpp3or8E.awb"ꔴD&R*H`3Tͯ`FfX +W? xApNcDxHNd:IkJ ]9⦘ g–vC/˷ Mcy :8 <`pӼ2]AIx vZH.U,//vjLz8Wk 9MninKhz[y\=)RSCƢdit\:5Sy渥U552ծlmP4>po`]fCnFY؃ jvd{&LNZB7liG{Sf%yƻ{<7,Ho0P7 Ğdm{Pwڬ&-$"rq3rN.;Iڛnh ؉Abd1 ZDPi]/T*jƛb^jPV|GGG[<_}!` f $.V '̹4uĂ4~hܮ~w 0DCl j-׌MH'zg7 K=C_g} dN@)B~`( cnjdr> C=v`%HIRٌ`" 9&$y.̖/zO (Щ^Γ#IRjMԄK[HꣂO(Sb.<r4 sh8B6Bs<PeQ1Ho (j r"nEWDXPW30UC$L4<#Wj ׮T6-q`X=jƱNPb b#3pL<8\";zoBVz։(N5 ;:c\nJ%N~)dnQMzo[.HrFPPDԪ@" #Bf,!rˆyQNj3Jkq/4ڮ5L/-0HP 8<2:˚EJD@c?|a@"d|3[ A GdF3 pI$tiH% cN2n7G.6;9#͘:dDpBP!0MH:n2pƣp'E`;k(ňRn *'"80?-n"+$2RHڌAw"qBR2#JWhm$Ć/RdDV8=C?LE$22&B-#% *=b%DB&ܩ"Abkdmf&Oϋ"Q!NR>UR05S}v# t#PTSU@U,YUx1,<BgV&l-HCEG4lD{YIY o{I v}`{?U2P)4mJ1\ Yr3pN%${j!-Lu  7&23*NMdmx e\TkTף+s`v(5\"Br/~zi/``²hwViO rHQ4 04~QkV84-(VGPLXٖm0)mnEYn9!AQ>@] ?%{AT\(?}V|E#B#h39@} %xM9H$$֦Mlob7k7f~W .W4v~Ł3ȣ]h4?!7]DNz0ґٿ=,9\l=zAYC]G  q}a2=l p DHx5 O`0*}  Uvjky$MNe"'ƅ\"ejZ<"=zÈR ˂/wjhk}?)HJۻG pΜgC/֏U ȟa tWV-U]uPB&ԀC -4iXЄ =хf!HjK'-NS2r4cL4aU:2R:%Q@SP.D!FdqEa|HʥD`^JIe5PI"G?ISΔ·b44Gd[cԂ_e\6Ҕִ8fB!IF}5)*sÜK;Nw5Yp <(GS20bQ'ʷ,ty^fKO BUJ"Ga\ıp$dGNq;練` v@e< {9n,;4!EΤ~ *Y5d4Ik)mvM%j \_0Rj-|-6d坎9-0U58Ms ?ӪSsdQ9׽Z`x h$ui}ezƂJyXa×3Km>oT$rcS8$-^򓭅'iebk5Ou[ X}j].sM)CS=)Tu0O<:-pzb3d`ɝ5WƸFY<+aNk,8+.Nf?`¥|,c<ϴ!mcIXer:V[΢MJg -=`P f<8WԱc>*5yRbҖMgkgQY~Y cJy`!epq^owUvetPkJDO$ +FyNL "guQKqA` z46w .Ԙ6F=WU4Beom ondMwYy`m+_>^:7xf6W/i#L^ℽ'g2!}~uNvzp;@N׸ň5nyc46yEyr#y$cR<rnzFIGbK-#&z1~S'%tG%&vugWc qF Ic fsy\wȋ1OvT|8xPh}֕hi^]tEc6;pi_9Ms['$ #5nFoY^ɥ!3&Yww'+:=e&jJc)yyehoHv**J`$J&3C-zآd*2J]ՏgdteD,;l<۶\ALm9כyzz>|xH\*:jRV['ќthǖ;\:T*``Ԍ π\8Fg̣fDv}IvPo4VH:SVkʪLmwm[Yg0@U$XRdM\a,mq4;i,;]p|EC-Λ{H6)aGOԌ&\\X}BclLFb[JО\#,glAB ?A0>n{;puv6u mIXĺ& e|{z@*T9kHاl,Ӡܬٟ,*6QS Ϫۭ^#|&- JQf#Wlm|9ɭۺ쨁 ?cYS4ܠmmlLځּ|){"ښc+?aLY^Md| #'^$# ˼ -ttbnT~)*@%o$O^mAB,1#m1)U"{ad%uĜ*iMݺz^r,SO="&~Ⴎ 5IL) {K=<`{{ٛj-a1%M;PnO0#12`R0#$'(@/(3:o"#mcوV=~y> >>"O \_Ϛd,-M (e=~=^igdw?B.Ѷ%cD/#∅02"#$HI(4% 'n >,'c߂jb+"kF ֲFqǶ / +1~l& 4(r*31 zj\60(TB7*)@:>w 0` ,hˡ@HUtRIYXM/TJIT.҉-\Yaɼ[@WAn)bn6ccqYJ( FQQ} Hp%rp}tjIv%)w*뵷Rڨo HvMy;cNN΢)Ϝ$O Л@DUyTCUy\բG5uU#YfS5 *hB[!^çGV9ksLeʫ(6FKƲ:Y[ˮou{H#|/uVw]vN'Jk˂,ؠvm R8m"2ߞBvsGg8̛:q劻uؑ>eJuWw~x7^*(uuz>ewnX٪zh qL;qst,Ϗmގ柛{I^P# N 9.eaYR`4*h, # YPqn丅a ؜XX^Q2c @@ŸP;aU&)} ` q w]hYW%}ki_{t$ n`ԋ?4I`U@8+ 78,Y "W|))]"u94Vh`чd'=)d.xwxP)NDIܰ5&VwEZ$؇-mx$rfK?˸QTc5GSYJZ$ؘ@ZaM I{\nWN,T RFd)f<4$Z p- zKUNYNFo(Fo3ץX&q%-ƙh&yS(iy$Om !)H٣.]K! N|y=ejQj:fxhY;IHUF !VƬfeemk&k75ʌ)HU+nV\NRO\/]&3Ӆ7&k3)N=8 W&PYkԟC( l@!MЃU] 1ƀ`8WSxd?ܡJKZJCF}xV.V6&deZ6Ҩ.nkg |&X fpp5- OBS9 8IPeA 6{bsڔstܘ!(@q}|ul+0˹PV/.K ĮXS^Ag|gY[ƣI)3"!Iբҥr :0ţb=Ck;@ >K@@|ߡ)@ @@@ @-@L@|ASAܺ#>AA:T:H# ѯ/R2/zdh 4ꈲ1i0gKLhtǜLʬL˼LL08x1)", '@aMpM%*(*jfq)M) lh"\2 6I'J贝H |NT‰΁N>-b 2u"/lϱlM)) O$O)= 8 È 5 P P $9Q$nҼ,%5Nٌϐ ]Ҋ)ZM٘-(0ANa3rb30b=gP ӭ؉US%u팎rQܜ\ Oشc ]MhP5TPCCޒN 5i~Ĉ-eUVFј,h3V(]feWס&`[ `>WDq Taj61_~n(zR'j%UkkN4 XsoNgFk#6gu.pqynAm~nljޚg:tNlp.CnfZ^XuپPbdMM iNc_㖥FU~R` S~%A? ~W|n|j X(b6k؎V"t$@ ɝIH:!Rdy韋EyS>@ yxJWܝǚH.)P_Yք[57h5W$F,fRiw&`҇gVe` dvth:[)A&r+fKJ{s@UjPHuՠtrHTYp,+I*z'uAep^kFI@bK{[1w^ b!ﳅ{l;(t^s,0ɐ]?XύI4)*Ƌ;45|9dtJ߻Njm b'IЇ̠`cA|)Hu**g *)+@=NBa )ߐb +:^O49(ݤGJE7I ֘_ +\8чh 啡ʖW9H@9y"EqGZ0"+(1Ks)x@$>a`Fj& &_x%0.ĩV.(p].siRbb)ZV"Eh` O(2Q&d<׈4jt#F9X#D=u# IE#}4$"HE2$'9ARQ$&7EGrk$Q0` H(WDQx@@8h+9ə8{  &{< , p2%LNT$% L( $&94A)k.s&6oϡ|u⠝!P%8cQL'b@]:iAYQ62 EK FGQLKSnK+0By ɐH2^_#+]6ڒA P p*5r9Y@S 5TiR/ֺBEzL,1O Ԅƪ]5VPv*K"tk<E+M i7@6^ [L9(0T(ei'*8éH~Y_+cҔ'x*3&|(&(E;(~#-?SһI|Tbz&I`%D4!C ^)4X 3a-kςC{$+ɨNP+  -lY[ &w;3n^d,ha :i̚~Ǝ _oW 50&8 PF XeiR Rf5 S"$NWgTK7rܾ"JޔV-lCJY! E &@Յ"auWΕul^  4: KLn-\ F0Se/W):́v5iiveV_͂wZnK+qa_Rd0k/3[6P_}_L5˿_Wox{@B/o@0K0c@ƥpPr0ZwaaH{__"{ H`CJq"`Sdd&Q#T?W6Ogтf"Xe?ӀC$Whvo?D$!yg]h8a6jkdh=!&h*xf:H<؃@Xi?8&HJL؄NPR8T(;PK2 PK"+AOEBPS/img/cw12.gif>GIF87a !R9sJ{kJsƵJkεޭkkޭޭkkkkkkޭkkkƔkޭΔΔk޵k޵kƵkkk筵έkkkޔkkkkkkkk{R{{֜s֜ssֽֽs֜ssssssスssスss֜sスsssֽ|֜ssssƌޭckc眽kޭkckc֜ss֭kkέΌkkέkΔkkֽsssֽ֜sss֜ss, H*\ȰÇ#JHŋ3jȱǏ CF @ɓ(S\ɲ˗0cʜI͛8s$ϟ@ J(ϢH*]ʴУNJJOVj5*֮`Ê+ٳhn5۷FK.NvՋw߿jLˆ;=c}ǐ!/Xy9 aZs:kFD-P5j3C gK` N?1렸uߕ2lS̶IU%u$e $gy畯l?^ta>Y~4OhğKcR}%Adq&yTLuBwדYӁ-Q. {E(Ԉ5Q}&Ov7`89Z f]cI%إ ɨ APo=^5Xܜ`Wi+P.Dn4 cIByfw())AhiY.v&_YHi]H,gu`Hfd:guqxYa뙚q)y&vnFhBp6$uעmؒ+t=֑d}du⭲,5iI#mZsˢFdgL,kƱ%huF2RWJyeNvke41D_"hg݂ KLV!4J770~ĩhI}٣d'[p(c*Ѧmq,2Ԟ]֔ҖB7-hkϦR7h6xX\::EړȹkHLut'J}iK5wWfyz2njyE7{8T2 &,ow>zӨzrί(.6Lƣ䲌j AR`G;yan7午E4 vD9Њ0x։1=< WViτețA5G )t=;t oYCw= G2Ƥ?QKIWd&8`b1>dWج@FV  gFՈ fP '02H%[|G?c}dp4Iq @R g˜ǘ6)%*WJ+cIKTβl-sK첗/IL)H3Td M<:@^z…72k(c\!p' MW̠64 OHxr6 [M؉1H./}ZR$N8҄P BP tNᓟ48QԤNw$N*)KqERzI3oQ_{ӧ}z50Z`SùkYN~sNwU ;ݤUƨL`Tˤ2u1 sg)ΪSbu&3tJ%c3qSfJQF̱zXĄMv A>W vx;Hظ-T0M,jB/N_+xMiЖwmEob3 r +Qsdnj5<蹫n=gJngM[^vԞY{v]6ڱr]lg8ZpR+oc ֡ͷu@sWh^M682]P!ѳTz ZwƱ<Í0-5X&Lx7 *r4$Ys42rX:F~1=#QƢJr0DQVԼѿ &lJ4ӢU3暔tVs,L;b3E3Hq4'ISҡ347]KsӨ0GO(15WUԮ~c-OӺ֛5/]Od񂰇MbNf;î[NW;/˵1d[,ݦt~da@7nॲfkon˽7Ǥ/. >y#i"޹T|Ɏ8Z4o;UxC>w'򳬛=6)sc[ӈ9>r9,~qSVg%{κǾf?FӮx]+`Nm#XȻ=O^xNPF@Xϼ7{8`[ļ. [^SȂZ@OSnd>gRv(G9i* %T@LЊH('GZ&{7gY/|ΑR+ug2ċP wuP-qG$ @-0U ؁wWWx1~2&('2tB=7,^pb3h4ͧ|Q+ fM:hn XpHL?> MR8TXV8 'r)1~r~aH&c~GCh4 (@4% ~3u0RrFGl/*xp@/p9wXs[=a}TMMIKڷ??7B PgApV#H%(!tE6Ed2.gYG^ hzÈCF8ts,(!(k ĘѣrW x֗xx}`6@`*/P6p4 .-0xIjW4)XYWrhفQ83qj"!q^b' v%Ɉd .7|@/61 .$ pPI)Ph y ɐ[H2 1iI $i "9|sp R.CnY$ ? @FYP @p x) PX ِ%ؕ)'M/(~SQB}s Hxl ҍգ5[җ.ȗPY9 @Yp y{C§$|(4J|52_Ɉ@#岇 ylb;XFgx@`0x PP0 ` 1j xI{a{ XLQo3zpHJLڤNH*@SGrHp Pfzhjlڦe `Wwi&Py|ڧzW\HmuWzvj*auJwbJ80S$Fd$&,KRU) +˟1á2t8)50hdQK8+:t^ᨀ,!W:[Gj ww&|(w5,ƒx'¥6OGy~z8:y7z2izJ'{?iA{{Gīꀴ SR !BMp1`\blGO(n^ls\Qx,!xh%jH(GhIhF@HȌ)@}0B0E/,ҊIF 3`Mҙٙ9i;] }Nhm"0i}#`P]DI*j'0#ey_fPK"+AOEBPS/img/cw3.gifb#GIF87a{!R9sJ{kcJsƵJk޽֜έ1c1cֽs1c経1cscƜƽƭc1scscޭkkkkƔkޭksƵk޵kkƔΔkέޭkkƵޜ筵ޜkkΔkֽR{s֜ss֜ss֜sss֜sssssssssss||֜ssֽֽスssֽֽssֽ֜ssssssֽssssֽ֭֜֜11ֽs1c1sƜ1s眭罌ƽsֽֽƭƭcΔֵkk経ΌkckkkckƔkcΔckεkƵckkcֵkcƔkΌεcέkckc,H*\ȰÇ#JHŋ3jȱǏ CIɓ(IXɲ˗0cʜI͛8sɳϟ@ JNF*]ʴӧPJ*)իXjʵףKٳc]˶۷pKݻx}˷߿lLa{(^̸ǐ#KL˘3k̹ϠCMĥS^ͺװcˎ}:lٸsͻߙk t ȓ+.h [:}Aٷ]ux#@;h/tKԪZ?c@c]y@y Z @e1 mgB9tg`g jFbAMH!dS`X7iǍxM6ZsϥƣTs#h 8هXI%uy񨡓ReNUS&ig:g]'eg:hL>c5 K.F"I}Z V sÐC)v񀎗ʼnهovoJFb*g~=FFyza=Xq^x2vb*ĝ띺yʏM?.ҢG놃9Zhj.CRYnld9lݝ/l:ZZtU0*d{Q{qyOa͖H%I98@ሼ D)Ò#A^0i7SSWJk*9cqǫz1L`(K&=hS+FN"/ʆzx0׍&oU TJs,u F#0c@~=ݍ`հ>}+;Aƪ#xcMp͒|c2`NQx79)k+ՈgUn'~ 8/]jcgmrJ`  deP;Q!(XQpDQ\DY6VЖ(1bÛך$5nka dtR[z&)!f,u$pO`zX4lu1֥ADo̞>MaMR7f1&AB0 4F:QEt̫$f=D\>p]Z((ʎU$UiE1RI e+&?Ӽ 8 җ6]ƊZd!.}iH+%rA &7."ND,n$iG1lfpKceE,`,G3Gb %yP>GC"ћp@x,4I4 Q2^s_`E >Ϣ" ٹajd(BSRHddRAA 8@a,6)n"Po@ierGn}UfCRI[PW؈cPzNqJ׭-YWgBjW"6fO$%fMhLʧUi![кP 6(ep c!IJ۸6#pH@`+-j#viDž?Ղg 8{9@slc2xK:j0?ۍV [unOoBXC)ou6 f)UgC綒!]# xΰ7GL"n2I%NWbɀ038FNs5;q4t8VHMaj'L%SEVՃ+{>tk+nS׬+y9+jFhXglZ o2PF 2ېGhši5@Eӧ>}+Ka s MBog}M?)?_?~N=p}y(WG ~C{z}W.|gzywyyw}@~ h{#8 Ҁ#Hw}"@ ݷw~+1 @{私wzA@(w}'z؃'wa|]({3 / w"x+q{鷇o` pG`yA0  ~ '0 zl.ч'zp(=yȆxGeH{8W聿({Jh7( ~X7w|zǁp}(0x`z'7h~ڨ8|Rwwو}܈uaȉw(ĸ| yyʨ(ry~g{\hȍhDŽ|9ȁ׎{ iz9׀g-QX-a|x >9~|4yʰ W ؐ(+r'X6yh5PuHxH h'}̷#@S+ ]zW~ɘ P.zw{XYh )kɖoyyl \ǒ9z0zǕ1} z#Wg0؅ +QyaH W{ ɝ,zəzW ʹڙzi {)ٖ$ן5*u:NWdňKEZe'yQGڡ"ZA&rТ.02:4Z6z8:<ڣ>@B:DZFz2x*LdP:]!TzXaXQ\`:Q*dzUjhYl]p:aJtz~'xA|~{zZszkڨzc:z[z{aQq`]9~wz|Put HJJZ2'jt0z:/qP,Ѭ`ڪ: uJ  ~rӚ۪Z[vPt@ 5A+@ , p,a ફjj vwJv-rP+'kj*3#{8='Z.QH7{@OtplwGM\cHqP ×+~pU.;:2,K[PMKa;Dj 'ڭڭ˴J# 0 Ю굍;j]yګqp f;P* :^{F;x5,]: K(+ X+Zۼ++1˛[ 5{zJpkM˾ *{0꽮 z ͛L,at@kpK z`5:sjZ ,;1<1ܴ v0k+D-*ފXìzr09<;PܪGl0*\ rS<`z1|e zZf;ʵrw+lULS|Z.?Z{lz=ENMKn,+M[*ȻJWU5>s *~z,^jjnw.a܌ luq ީǩ@A֨@ѼK믮)^>gm:Ѐ~pu>s']8;-; ޤ }+u5Qk |ݫ.Ó ;[Nrߺz̸;a ]䎰nޮƝ",; v i̲l|Ƅ+ ج ݭƁ] z;3>X&m6=wZGӗ+\)o1&nv W ,n,q \װ;4=[:~zFx޴ 4_|,W"۫nң0_L~DOhnR>%y#nZ0 }!>u{yZ?}JO@@ DPB >D-^ĘQF=~RH#)V,RJ-]S&3męSN2kTPEY4TRM{"uUTUBUVAvVX_ɞEV@kݾm\u{W^$XU Fobƍ.vY2Yȓ-_Z#H@'?$h""LEcMK;\g`jk2FFVs N(6]Ɠߺcsܞzb8yΧ TuuGD:9 2??po泮o< 3o##. DDCA9LT{x=WN:X3dsϒ?KkCFa2qC+P?kӶmHd0FZ .D^[ DȄL=yI%-dX#飓^i4'jβYC t6An :~(98mY&dQ:P[&qA0of"X@86eYO}uIcR}ίuؕU=ݥ=tX^B 9~:HV_^u/>g=q@KI=tYSz@::Ľhxb/\~d&[&yT^yeRt|+ΙTtf7gs)ho'ʩKmn0ׅ8T (p^dM & ٟڳ1wthDQV-hF[BQ:GA K4%5iQ8mtKS5 MqE4=i(3Q=T +jT:UVժWjVUvի_kX:VլgEkZZՂ+|CSjUEgd)W &.W s 7wdyЃMye|JO$IϻN\Tx.G'6e)C<:t*n( v+ !x#dfg`W~~<񝏂˾yx۟k,TMgUkt wr􌿀 g⋠zxw~}$$!JOp@Qo=6Äa@c'C\; ;c;C9^˸Bp[U9`=Ƴ@>5317h;A;k6A#Bg#\@#';<˳+B+A.-t= A 6>PCK2d۹c8 Ӷ8Ԁ9C#6>0H XEdFtGDGd HKlIԼ1= R4SDT, @0:QTYERdEWNDS`pa$b4cDa|5`LiFXf|]FE,G-FpDJrvn\ *yL\t|t-x~g[k "H1ȃTHaȆDHȉHȌĘȏɐɑ$ɒ4ɓDɔTɕdɖtɗɘəɚɛɜɝɞɟʠ쌀;PK\g#b#PK"+AOEBPS/img/cw6.gif0dGIF87ac{!J9sk֭kkcJ{kƔJsֽֽJkތεέ1c1cֽs1c޵1ƜcsscƜέέkΔcckΌ罽ƭ1sckcƔckcscޭkޭkkޭkkkƔƔΔޔkkޭkk޵kkΜΌk֜ޥ޵εΔckk経kkεkkֽR{sssZֽkssֽ֜sssss֜֜sssֵス֜sssss֥֜ƽֽֽsΔ!!֜!!JJ91ޥRR|֜ssֽ֜ュ֭11ֽ1ss罭sƽƽ罭scsֽ֜s֭֜Δkkkkc֔ckkֵΌεckc,cH*\ȰÇ#JHŋ3jȱǏ CIɓ(IXɲ˗0cʜI͛8sɳϟ@ JNF*]ʴӧPJ*)իXjʵףKٳc]˶۷pKݻx} ߿ LÈ+^̸ǐ#KL˂]̹ϠCMtia[^ͺװcfZٸsͻn&Cŏe ne4t革?N''o@Ȃ[n }n@_ v$X͗@7,a@>@(A]XPx8@Q]_(@p=8Y&!9bxy\yqvc/6dMX9_=`y)(Ꮒ$ 0)~]oj= &C?6ؘg<.oDI(:(fa_rvF_8l9>AI&HT' ɒ ]QӨ@v:h'ȝb麃m>&mjtJ7 A";+qW6`} ^u*|_m8d9q&x`s/Bhoa) z'AV8#`z?&w7p,s:\d 2ƒ.,޹+ 粉̮s/_U)؅|>:<؝kq␣}J`nw~MC<'xχ=]x?P. zڄwZ^=ؐc>h%y7UZynt6IH>4n^eǚ6{ :`zzuggjjyK0Q@w$Ar.z.LGK;_\t/OwGPc&#M9 6;PxgU/^'5S'zG$ &\8 هҧpcǝ",WOv=(_B-! @BC%e#F%ƙyP?\ TE2C L!.6] m1kX:" n3 ND3̕`RK)"O0"~~-{OhTіS/y aD|&cZ&JZ%d2]jNe2U#LwޞETp[7eNC0TNGPL^&RLQ&0,(ir ΐ H>P#<>SfÃzUe")LY:5KbKRͅA|Zy0.`~鹁A\+R {4ArMi@|m N#CU_EC4vNv2o_/'L [47&G`(NnLŊdz`-}+ckatziȇa1Ͼ-;\?NI|6C+{/Jpc6Z=ュe6AyfZf1'v>v 蠤kO [zrEfv| $~tQ4-7vьAM_CFZ;!Y%|X<m4a7ꗔ݃EH^θkٮyQ`G*8e:v}x/yq&e%Z֢u+PU2wnʭoӤH>]rd"T-o- !SE6KY7C~d19WŜ-/0g8ϹΙb@:Lz.y!:җENԧSX:O{+:NvhO;Ϯ]lx~A)<(<P$Ry@5<5"\Bw2J_FQ={K*{<[?A?wIwoda2(IRAPu?+!}ϓ,!KO_?}W{C1W,BN=q' -}gz"|y'G,Q/ɇ~*y(gz} (%zyׂȂG4y=`yWw )P|W|.gZyG {`(bhF1Xy`H ?|C؁~gs8H{}рyP|݇y}SXX| G ڀx}X|8~7 X 0 {h,ъP'}}7`ʈG7{YP# )@ 0(xXh }fhԈzw=t(/@X-!38}~`C(Jy7{7 {H .a凑| χ %)x $8 y(~&y| "|P 80w-yg1y.&88S 0y7i\z`ߠ"yiJy|hz[c mГ]W |/ 76ai^I|I ?uVY~itd.Y䷒]{h"9XJ)hnei -i1yI͙8iIi~87ٔ`z2Ay|Y|gg }|yذC2+2869Ȏנ7 M"~ *鞚ɞ-'i8؍dx ԀȆǢJ"@w/渣)_9 {`hݗ HhM*HHJפ;HgH&yx`Ǧ7 @+ᥫn :)|"x{fO?J/{Ȥy* Q' Ʒ$ȩxx2(` xJ0)򙄳:(o ǫsڬjǬcZZG֚SڭLǭEPz蚮꺮ڮ:Zzگr:{]pg f;G{maf_ ;Z!${Sa(N,I0;B!4{=a88<3@;KF |{JB?۴NP7;T;V{/ks` I `bK.ѵ<; a01iwkv;=A3ah˷7ᷬ7 nyt`˴{ k۶41 `1;r K ;05q}++BAL组`+}K-/ 1 ԋ.0IA2A3!ӫ[~K;t۲{׹]׵A  , f{ <, ` ж`Π+ཱི,Q䋾# U cK ik` ,9#,,[|KLl 2<9ܹDL,O-ae, Uk¼+5oܻ*n k(°ǂ )L1|J i ƙ0|^y pȚ>]^~>l輾r^虞_~÷>xË^~H'ɡIRQzhcY @,"0 DI]SL5męSN=}TP z* @LrxrǦA y$)ʬ/&EVZmݾ(Ҹ02P!R#D𦱄[dT"Iu-_ƜYs-_:tCfr]?Z#RuX!W[n޽;\|Fixѵ.<@%CT;t[xͿlo)},%aInГ̻KOH;@D0+@ X)[D*ȎbC *C D1EW, 80$9o1GZpG2zH#DR("dI'\I)(2K-tqK/Ӳ+$L3w-e3߄4Zj&O?˛3E Z dQMJBu^:,C<,ʴ2OŨdv++7QWK0)4P(#꾑Jzȕ@WtUgu((b  :d CWjYuVl-.` BKVC)\0^3r;k]l77DDfYC #Wcʢ܃G.2a@J{j6Jwd9 7䟄#nt)?O6N_onS17!@QSyd"eZؾ\c{Ee#P1r.S ×TTGDMkd `o$ΧJ(a"!2;Q(7>VMLb&DfnLfbf̈́&\Mje&QMndNNrdD'LΙNv"qg\OrΓ=O}b? M5(2TMP j N!QJo3D{ %ǐĪe>ģo(*:tc xH-;Mmr'>'\ڜIa@u2njԸP%8Ew@oisVbK'dM ZV<$W VT"IEqKV'DjC\6 mWYea46qa( ?rJ.nWUV`<򍶲]dm%k`l"bemK<[Iǭ^)W>6+TX;HT;\1oelj/ZqW%mg-:v$ɮ`{ڏ׾umm.*v, "MDU;Jf#Y1ƈEAHOT*pb7'*)b4C F`L7h=|ELLI$;?VG/ l@ Ӧ"KX,~m%,>?v,CX5x0<-w]掔8v-+$&1zف%-! datЕ a 3G\MdcNW%`( Ґ]j ٢4WZ?Z{*nkp=YYoB~Amk:Zجt!bd֙vK-ef6VleaUTuz5j* N !CY#={_$f7DJsZ]X874 Bpu,fE ,9y%T-0Pϛ 6d 1Soa5I^z=,tCKϥ5c&(^I5SNVM!oK5a8d2)dR@k sG; N\4߭<8>,aJ=9$z29F籣jwzᇮv'̋wuďR+2"J. "r z,.?+D˽9é,@ϒ@@@y': v3 ˑSq00][& L)01Z L/|)1<,/$3l71 <)z 26RS(ȬCC(3CxVX:XbZb $aôતĺ;4rIl>q*㉜PzD+BxիCT u KTE<=`;`j~9.;0%"K-L꺮jti>FȼB/ҙm >r .T@ڊeLgDFsD{aPH!/G45#C-h&0#3*+˱س>MӏJHK<2s*S2"s#[7_4H|G ۱z;3@%5`55;ǘдp!60dk:c6JCɷQLq6G44S5ƫۨ~d.aӗQ+z X\Hl<`ۻA\ =yM2K#]ɼE̤L9SY,F(lL8 VפHSd+O@; ̛(=<{9OyP?\%{۹!`[#R8F@%3 '(l$'#ME %UB%--߱B4<1%S13UӇ056u=b8B8S1;(;S>'>A]B5ADEeqGH̡Jiڝ_T,(N;N{[NĻ&:1%A%O<?A?u@} ?ЀuP @$\%1\A*]),QMK /]+i#F]ܹ M%%^y=AE DQ譛cꭔǙF r^8Y[ɕ@'l h-_1^X]-ȥ" S-ucz r0 W<./խ %X2UX1UZ:J*c̤3H4,Y,C j! _<bLnZJr9_.N iS!M͕Zs9J#[)b 1Y[75{OٛOS,$Δ3λ\"=?vcX^Q<%OQ}%A|΍9QTE`8HR[}]T6)XeӘ\>]fanb6fHEdeffKughfj.j歹mmfp^p&gssVgRxyz{|}~&6FVz U^V P芶V5΀ ghi&v~~ |i(j>ij.vꧦgv v iF.ꄶF UpFf&i~ (C.&h>램6hviE0 6`lvlɮxVl6B8>l6DX :H͎ߖφgXP8z&i@AAB؁ܦn:nnz΀ɞ=f32onHx"g6gxnFp6 @;؋ X:m{ pqi^NHFr=q 7X>r:X+go;qhP2?0r~0qy5gq>> .@sx%(q7tgG"xx0 LWtNKM78X&n(p n9HoOzN9X( u(u;H/^u1xq:s|vyFiu]ǁvd:3t#g?yOhL4XH?w~5HYo#h&I?'?u  W/pX}N5Xxu6%tP(Wvg? *gwx^hr2hxyns7_z4gu7@ypq 7`y_y8y(x yz'wx&&uL/_GwgWS{Fg_ntV_~O{-g@3bW)p|ȏ),(x.Oq$`n8zvhz?zX?ן̏|'@ǿ|yP)p7#7~owXt"/ro,|z&U?|{.{7—g'߁-|ɏ/H'/0h10@ „{8 =P!=|(ؑ=*`Lƒ3@8%v()aQeL3Ti(ҤJ2m)Ԩ PJbU&A D"@!ح.DD" ^x=q͞ 1"^\I \ɘ(0sœIe*U"<90b/$GN@Ȃ,]NDVȞye, -9ҧSO5UM+.^ rC79DpB" `{\X0a!b)Ε i CqI@DD5BK0ᐄ%Cm%6sDd -bteY! _pc `B_<9X+oё-(xSh Jy a9&ey& 5l!0 e4E%N4}"CE&g0:(/xvZebj)zik>ڥ *ځ4Z*ڊФXeuk 4P;,{,pRjPPZ{-Zp-ݮ^J@..2,T ƻ/ҍ[i0p0 +90G0Wkln1!<[|2)2-21<35|39333A =4E}4E4M;4QK=KS}5Yk5S[5a=6dgw6i6m6q=7u}7y7}7 >8~8+8;PK[n<00PK"+AOEBPS/img/cw11.gif>&GIF87ar{!R9sJ{kcJsƵJkֽε֜έ1c1cֽs1c経1ckscƜƽƭ1scscޭkkkkƔkޭksƵk޵kktΔkέޭkkƵ֔ޭ筵֜Δkֵ{R{{sssssss֔֜sスssssskssεkkk֜sֽs֜sk֜֜kν֜sss|ssֽsスsֽ֜sֽskΌkkkkkΔckkֽ1ֵ֭罌s1s1ƽƜsֽs֜筭1֭֔scΔֵk経kckkkckcεkƵckkckcΌεcέkc,rH*\ȰÇ#JHŋ3jȱǏ CIɓ(-Xɲ˗0cʜI͛8sɳϟ@ JLF*]ʴӧPJ)իXjʵףKٳZ]˶۷h@ݻx˷߿ LÈ+^̸cUò|L˘3k̹[zMӨS հc˞M֯m=Cg޾k1!E/xˍ#⊁'W>>bzn7Ss 1PU0&t!|%6^=0q6a]U9t"q0GW "Re&(@9!*VN{}%8x_;]|9gH_J#YW9O:%^X&vr<%~0&hc^)C Pc]Z) eoaR-N™.H>` fKfWuIWM_m>yב[bpst']ՙZsi9DAZϞuUC?gJime֕--:Xl^#x+}w\ f8nf>nb8{xsl]CgS$~_ovIa q'& 9/_X"AM]yV7$.6wo_eXr̎c:b1WזՑ*k]+']#.ycL7'#Id]sȒoc"vk>6|;!Tﺭv |.c//?p׸E׎ؽ%^\E[䩇=6}oᗯ|6ɜ:|vJ6#ד}d0H\wg%j}]G[ixU'Y= r0+@W^2oH񳟶4anWyWYXX{ڜHd}k@Ze嘪MaXrpѧ"wy0f!oۛf3M,V?^1ͰXw1S|qbjڞ]dYi[s-hHGĢ)?`.rﰣY5/4n!fe57RFD滛FP1i[k 'HE%qs>|wJ>IpQ%2*I{Ac/xJa厌a!4Hn}Ԫ毑W$'Y|qFԪ ^S;+)Uyn,(%Qi+;?*3txiIuV[QU oKH-p6Fq@ȫ*6Jp^YHΉ8P/dv[hA1ri`Z%ˆ{:iLqԢ`!:l1%X@Qä8(JyEUiKS2x*JBiUPW%,uN; H33)=f\.p"j7YpM8 Ğ):Q=6[Z c39'j2Yg%곞0&2綹"/`7/hݎcD8yL-NȐ>X[ ;Mz׫PkΫ{KW3y|q*WGNL1 [o3{X5GLb?: f E8͋\QeU[Ȝ7!u<"C&6r}w;@/xS{,e:=Velg,Nߡ2gQRti89񌯄3֚*5W~M͈;H:PSbdMz$;t\UG`ܑ1 U-M&CDg-:uiLģ*$aADvk&lڣ阜 Vt$+}8B+Չtj΀(=MNg7[o^JEv voSiЇ.HOzS;:a:ԧNKXѯ{\ǞhenܱL;wMt~  pQ?`J#A(-/x\ %VR%P嵒OJ=O\ReIVOs/( g 7B G}~}x^.~}ïB՟~W}ʟɯely~~w/xwyا}7~Hw{ } hx#h zg}` wx+}7g}؂Wgm'7.z̐ .$PC}zy(gXB0Q؄.z )}ׅ|g|{cX}\חq8I()p|gdHyH7[؆xx w g h>H}xh}p h-4"7HbHPinx񕄗{3ȁx{Ȍ猾ϗ|t'Xz׍׸嗅{H)|+{~{h+Wxˠ( .Aːh,XzX{|JxXܸ(}َH /THhx'{x42{0{'3(Ӑ 97Y82~3X S €3F)~̘cٌQ Jɔy4XzRyl'G߸ObY0hIy:yȉ5 9B鑔ɇY_8"׋g} 鏠 \YȘv%~f8,YxxЩ |,XgX`GSy'y|MɝIyyG(~zH9zi YxӉx8p}6 Y7zɠZgx=(Y`xH )@&yp%.&H/z/:4J `} -1}z ?{'4yJzRZ')c)~?jM>zx9IϠDE9mJrEQ<}7||5w6!:{'%`j.5q~ysک:w~ZxuڪJutZJtr ګ:ZzȚʺڬ:Z*v v u:rz:r麮q:Zz+;tz K  ˯; {K&";;&[p'ױ*QDz.5Q2k4[jF] 8+s,WzA|]AW]2G;%'w?[|4XQY{I~]+zJX؀8 9Ohȳ0PړFX86yi15y* nzɌiKrk{*XȆXqwxhhy놭؊x 鋸{ȊHˉYW.a{ @ x _z0˾0K+盾۾;׿+?;ѾS?9z٘!y#yAx[ # oY)u(x{ ի8zp +Q WK, `}K BDlQJ,@ BXC,e[cw SL+i٘@V\LLfD\nl}=LklUƣeU|ųlg˚WY!YܸIIɨiW̔ XAӬGzɁli,A|KQ쾡QL?<[ +!5HDŽ[ޙI"١ݠٸ z: Ph -m(]rIE~+ ]+a=ll ZLD} Kη˶wO+O)r+iG&zXՇeML޸f<sZDj&:dM{{z} [*y[Lۿ{0m}MMݾڠ== ,M\0+`7۪ɻ۷M< ,x=Z=؝ܽ=]z轭޹]߱:ݪ}ߩ]ߡ:sL pƠ C ]x80^zQa;_@-q y +ܬ010Wr\KhG^{ك`}2!@.WYNC.ZF.L0aJʃN g>\7!5~y^|.)z@2籧>sr!^M;<нULٙ ?HX4. lƘ~V mx Q׎@iPH<  >?muLL*iL<< <ƾn"k("|0_8]^ N-!?nwN.|4.{pSwp%.Q ܋^oS c9<_i[DF%^gl >t?  x }2~Ăo??]G%n{nm.˘`PU!&B!`@BdB,~@CpxX SPC #PPry3#R,R'טe͖h?@#QGLl!ӏfv<4 bkلƍޔ6$P. B_ tHȄwHi s z9l뱧=vpixώ9l'[)1zu{UjwgݿO & z˥$äyEfD?NbjV*A0 *pؚ;(3DP C $M¹/6 @-3 '1@80!ѳ;d)ZC@#MB1Hѐq C|eƖ2 K8RQuD++t()̄ m#CGϏL4GIԏOS@3KUkӄ lVFPA%YK%׆d U#P:6-P)Β=4,-@h4n5VQ m离n:nof[ovto͌2i=:MeELb4b1x&\5 BƘrX+J$ׄTomc9rot~ʇ} k;rxwgV8&碐,c^z؊yi@.c=` vd^%kBD^;|ۧ쐼E=y)T+\A G2E%S%+"xaš(hb+ S?+̃Pp”EbM TV]AyPlŚ8 >U82# & Y?L0%O b3Y .2n}N9D9 s>O8 Dc!Fv?)$is#89I)rz D@ B֯MXr58x>:|8w;L6Ơ.q5%YԺ!.RJ  /+^->. 8E3ߪ}G;}Zů?3ѿ~Y~??$\?D?d> ; $8 6 d5AhDL`tAA6(8 BH DŠ8X9X¦A*0(d80,+C.01<%TC(a)9d;L66C(C ?$ 0ADDl;ÌÁH5;ѣɜ:)C.E20D.'PDTTTF|aS?ɭ(3 5ŮDP,S_0D2C %($%F&8EFtW=l0qz™;DY;qa .P*00E.pGxlFw0Fl=,-¡CH$x[9bb h4bnY y76Y% 5 "{m 2'wĂeܕ,8&%؄l*G$@ T$Az$Y8Ck๤Q2qrJѥ%#(J{ #'0'Oj`* lRl؁'8$hX]^؅ItJ ʲ(SЧë *ҭٸ:0:(? ͸(˖$\I4!(X)2#2NRE *=Ta"Gk&5hK2=.K ;i"%V!1󶁮ђfLɽ˻n3.iCI 9.>}^~EpUn6CJ? RոW6CDWLܖ}=Wk:~sdMXעX]ǩsÉۡE^XilًimmN戊-R._ڑEو먭Y@ne)VHm:w%nDnYξn<ڣZHȕԕ؃![ */1M!K}Sꡃ = 6I6b py#jEٕ"Md7{[Jp!н[! ]MۆZq%NZJJ?J5lA.xaS9I[^& J ʑ`K`Ztq$:Ҍ v_lr4L "oޤJ &:_J.u!b%s ^J GL;4&oe򌭄B prឨ:)cQcuP7{:+b"9+(+wx.[7ɤ&TM(O cc :hNPf}V\\SO+L6bf*cjcwh"T* ;v;d?fp+gϬycWrNC~* vAwS+cOsG3mfpZ{eZ9(ImҘu~⚯6q>aPez2f9k/M_٪c-htmy{ f:NrX1A޽E 0~ny *=,@lojaC;)ݓ1f&>0 ݕh)}HqViQ|C&5|s0O >K۔P[ҕxҨ99SvA'ZchsɑXk{Y Gk%,h „ 2l!Ĉ&@'5HG ;| G HV( `ƈSn,4r/fj4!&#6̝\*XPW׌'{S^@g(!RZGR[#RlsB1H< fǐ3HXolKR*[]\k?3m^?57Όݢ6StQ\?{x֎65N<cK-;ڂeW-Zӏi,wzrt2|] Y 5!  ݁{*)?qL&; 0rr4ed9RC`, a 3"„xǃ\dꂘ>d _?pS U;u w2E~?|eDHBi{FgC.QCE U]aF=Dwh|(p|8씵KhaYx(!&b ؙNHݳ'@J.9w 2bfO2?*щR7M,eќ1"F)&=iN>z.,})Lc*әҴ)Nsӝt:.)P*ԡS*{ M_,>J2H߈խdCHQ֜j: a H YLi8Oҵ,HQt؉P\:&BĀj]+Ԏ>̞{;bJD0QP<3 [FtIMIvOґ#$D9푒4XB8D$.ư)F 6YΧ?Uqj{ a UPvx镶֍jIKz$%Ӯvx}n_{.w}vz. ~;ނw}ux<#/S<3sB `?=I ?i%Z^ (p9ȡ=qZ{нV`ߛ4 ~Ջpa }Kߕ#9B@o[4~ԥOJX/4 { O~_/IXA((AChŜq2(4N @_flLM'xx <.r->`rID|t2TIEQE\՞hE HXu\H ]v` `@`X@T:؁d?YEh%Ģ !(G8_)!#@Ƞ$yAn$ ^ P?!gġdءiX~F# ,U]T%\X)@ 0"9" /Ah t'vN)J4"%Ab~qAB$HB$Lq"/ ARBxa@2b26#>cb!NE5L$aJb,"xVc#20 @#P# A =[(ELZ(aP!~cLD#O$#~dH'Q< +}Eo!TN%U P3 m= L%YYXV\hPNy $4^%_<D@?q%v%A襞caޓaNG]&fffnfM&PUg&NhfLi&j&wkƦDl[Vm&QѦn&foVpFq&C r6gB0sF'A@tJ'uVs l'wvw~'xx'yy'zz'{{'|Ƨ|'}gw٧~֧'' (((y6( ~FN(V ~nxg4chh((g@hJ@m^h"_b)(AiJMcx2)NƓ*^)'DdeYTt(v)DH"QߘFͩ$C)ꕶil'dx.j\袲}~iџ;ʟ~*`'_i*jɟ**"v XzV  N 6ߨ~0r:+"+bD~+'JB*xzk벺` @ A `rv6 T+E\ vkN,' p@xgn j x,wj4* Ɏ tɢv,˪ljA Ln nl*6`&RD!|!F$+B-;Z+0צlŦڒv,*X*b@bj@Ц Pr, t j pzƚbf8fbb&^"d#n c撡$b.$`.bY'wҬ*Ǣ@zFvJm-oyV.#=":v.OJ.fz!0An/#/Rźvv-wzΆ#0w&-2//n:@&0z'/c< c-=p.c긚+ެ |,@q n֪/ H*#6oZ*_#PI\$ lc$E1kE!0j @ L*! Ho Pow˒k#,</n *_&h(02*$prN 쭚lr,Κr0 3 FeUN35KU1w~i5osU^3+28h%Z:ZeXi,]%@t_`o?@'@fs>?3VE&+SE(FCG[Do*6ħH1IKiHL4M'b'N&Q4O94PN5QKO5R'R/5S7S?5TGTO5UWU_5VgVo5WwW5XX5YY5Z5X;PK>>PK"+AOEBPS/img/cw7.gifDWGIF87a-{!R9sJ{k֭kkcJkƵƔ޽Ƶֽ1c1cֽs1cֵ1ƜcscƜƭέkΔccΌkƽƭ1sckcƔcޭkcscޭkޭkkkkkƔƔtޔkkޭεkֵkkֽkkΌk֔޵Δckk絵経kkkֽ{R{ssssֽssssss֜s֜֜֜sssֽスΔssZkֵΥƜR{ksssΔ!!֜!!JJB991ޥRRssֽssֽsֽss֜sssֽ֭֔֜1罌11ssƔs眭sֽ֭֜cs֭kkkcckk絵Όεckckc,-H*\ȰÇ#JHŋ3jȱǏ CIɓ(5Xɲ˗0cʜI͛8sɳϟ@ JhMF*]ʴӧPJ)իXjʵףKٳ\۷pʝKݻx˷߿ LaUò≮ǐ#KL[Z̹ϠCƋѨS^ͺҧ]ǥaBeڶAp3Mw}KނqwNЃ췰7=`r6; D?.^G0l z\T`o_]}ul ovV} !ec(@ Cyu@ py]3F]z症ȟ]B#VG$\Pp4$|(b\!x; b[:)V,2fɜ?2]89#N誇l#;[X^s8 yġbm6@`&izt ={C 8hF,k?\%ϓg,ن~7Iѯ@QۓdUUԐ&^ui `,ةG.]\E9z[V>,|ˉarC OWyj41w-[t)F:`ڵCDd D|_Bq0RoY s yюr,O e_'5> 0@l!??Ze %A0Jwr!=u|xAv .PIG⏋si+w߲>H]1a'\z #Su.RH~~u j#Ȣ? 4C-M.,=R7tҭi$&N3$<4b{ +~kSb`i#IϤa~ 51!=u4Z` 9)MZ`(R̀Tg4ƩsF_ť7E' d8%}+mg N3$tuߗh8fG)/5 ԡq MO@@Avp/C,y~ChE+{mUHlfdOb3]uҽr5ܸlv_L{9 5/ Z t ;@L|+a{#{'~/yyTGNׄg{HȄN(/z[}'e}yGfy.@ yW}Ђxv({P|`{pG`8wN,!R~hyvH÷저zyQ^hs%G]( ~2zSx{(}W Ћ]OHxGyuy`y͗.{ȉp7` з`yڧ-+|(džֈ^WP|G а'/8HY 9+Y%I-9y~H8rJ8NX(y'0! Y(598ـ0娆MzE}0-A  twG9cxeI)( p 9jKȓD;(s;mɉK ȓX8JyǑzذyehfx/h p8o(qH-M{hr .+r $ Y|xzq~ٙٝȍ]()99&z@GǐI?@y (η,AIHHPמ,Y KؒǛr `()예ꝑ'ɗr)]Zy+ڗ (ʇ!9&ɝ7Fӗ{.{|珎`Jy6FZMK?Y w^ |}(y'JʤZ*zg~#jJ!9lxaj883:ܸxRʥ"yu {HyЇјJ|ЄצW}yye.تxڐi9Kxٰɫך7|)S*ggyڪ XY *@ڛZZ*+PHy⺭V+:yzsנ1 uQ9rbsCZx31yJgysx9U u_9ׄ#Aw`6:r8>4@;{'D{tgHkLbP;[&)pXZ\۵^`b;d[f{hjl۶npYqT[z'vLz۷EǷ~Eس[^GV۸+Ǹ&[Ge۹^Y[RASۺ!B[=A8ۻ˺S[ƛPAۻۼKsH  ˚{C71`P@87:Zp/1@. ` g K0*h0D!z0 K Hh <#l%'lV@5A2 |z` .L 75 >x@0 3,I& O-a,<P-G ` H\=jh?1 ll|P 0z b \ 0 קi,-=L!,anHl-syƉ P[ 7@<ǚ Bl !,LLy@ ܻˌ yÿ,¢4ƣGEp;u9%.𾊰t +.sl +1̎U0˸|L| -T|h\ M\<ͽ LΌ0Ĩφ׳|f! , >mɟ,H,72: 4 Q=YL=qE 2{Kj\ |ÉL[|ˈkɧK]! |}MX_jժ_}M ԅ}Ձ \~}+QnفԖЬՐp[}"`Ԡmơ}ٓ}I =`MoMȷ 2Kǥ Ӯ̽ ɽ׵,C2ݾM֛,M-Ɣ`m|L=K]݄0L `@äsÈ@̽m gh\}. =r- -Mf<~\ 冢@]ۍݷ8ʇ< cӋ ݉ FgEnƃ0}0^-A>5,á U 3WXl xdNlFݏ7]qp͍$uNׅɳ[ӃX=`\> ޛP =Ma-y<,ޣ }<\/$/&RT^/i?\8%֩<+so h'zȘ]qhQp:xT0 $_ku,5^Wn/c!M/u;ooa[=a6 WQ?/_ _yv<m ]@9!.AMZ,11P#G DPBN"-Q"†'^Ĉbƍ fTQ%I #@ `a)U)hr0e&isf͛ sYJ'NLbQh1*dTUR9jћX!RB.h()INzvSl!JȠ/(3ʒ/M9\ [ue6Q*#uAQ;V 绐%8Z"J7V;/J>$@`C.}8v!E%BF`#M?x4w+G$p[̭{qa'E:Z>,;(J? VjI0޾+j".I8HNL)M>r:` X jNw>JE)Jb2$CIztHv &/J\ʠ$Dj0W2=~ H)(G.e4 RD봱N`PɬH"%TO+čQ,IB24v;2oE~ZŚPXEV8Kj&jQѠiVxWr,.A(kQ6Zsm %)ER`,\M[J6Yayr$'gnX6r]Xu ZuU!Y*)-!y9_IlfnYcA>8gMdhIl0{-8g}s6}!D|U8vyҵrZNZ!K *>`c[W1-jjZb.[+wpAIrU+c]N ä;v)|/)⁸VEzk sgمCwq=ܣwy. ~r,~N;>ry1;'H>Mkg>g]̔<Р6[_(6!w]^1?x"ST'A݈+rYeB<ӫp)lA]z8QD\“8 MVja qrďTb թ! TLg3j!" q_9Zm,lz _]ƨȰ-rMUCQ8!C*ыbJVȴ07dJ04NhVJX|e+e9ˈ `e.uKҗ\/a:NǼ%Lf6S!tf4!LibD9{5qYh<69NjӜDg:չug<9Oz%g>O~겜Nexh+DKvg9D#6$xUJ24̅ꭕ5@o2Mq/(苠4Bbĉ4!3IHKFB~ڛT^.[S]tu14Wh2fˠJA饕P՘B*QZhZgK]\yBGO05}qw ':h* < "W?f- :x.O_wX%%Ng'BsmiB݀CֈU9=w9E&uNK|̦RKxR;YWwZ2eD!$)p.'=G#*Q9M9FU[x$1oTMӗ`?b `Q;ىS.?$ُ bjW -y15v8lc>Qkqwҝ7j?E̳~GB>/ӧle/$;؜=? E?|?7~||"χ~K_T%3Ӣ湐ˆD>sf2=%:ޠIGZiV4﹔=c&& > %Yb@o?yBZ-P Ղfx*#ᰮטAҢ-q. :-%-"-Έ,p Ԩ--*-p{ 0Ap0-0D-[,.l ٢$ͨ-Ǣ,J̬!Bܑ*DhC, K ,1VxZDT1z9H챾#!0گd  z%9DWۑj/VI,D 0^ðɉ sM0j1/;UE VU\s- rA6rq4~k:qQ:7ײ% ј+#˳/0KZm9ٳ|@Ǚј×-;+q1G6ӟ8;l1)Ǔx̲µsl2ɂ`,#DZKm+&mu6DI?b15,C5iI cKHX#=ڴ1љщD2T;+ sԟ^k5I iɳD2G8qbx20Aɽ<8{J)z7칝178Y +8}gx07 Z̳˾KџŊK~8yD,7{.Z;BrJRK. јP;,;"@Pң贻y1<-0zŊ$TϞӺۻJ:HdY<<4#: - :!ʼ;;%JPۂ8TNu պH6p'HXx= %&[hB d =8KQ DOx MQ^Rsz2R ݳ ?-$e.ݳRxSR/E4USY25u7}69sK@㔦>ӉTV@^:T+T:SR^ @Z?JGE 4ڿjZ*M#PH%4'!U`j^BD A2(eՒ ^[pհRC(e܂!\"#2\ڸ ös찏0%1\n%AJA2\M4B!jBۨ4]8ܑi|A)l"=TB[y[,N, =JIS!39EåZ)3^pZ[P;;K p=2[E[L[y7\IJ}lʰDY[ʙL\[)5"I|5m+Z6QJJQ{Gޤ˝T6]$HM;b^-!D^84UVD$;37 7}~2Zwͅ[9í \Š4}ҔӴ3K0d `q7~ץZ7Ӗi͏.=6P9z'jѥ;!ϜKPºR{"֬Ԣ<4;$,H!$~A"$7OBZhb+: U)洺b:@bϚYY:EmQJ'mݎ"cZRK[Q=,QU pZe[]V\_f3`&bF'_6dVfevgehiTkf)lnNdpeprer6tdtVvSvvxVSxzQz|f>|~.B!~(|?5E*VaS"cQl"}>%TM+#2 ]e#w(\V𿊞R5՞JVԡ͈ii lXPQXQ@ e8jۃdY+`퉫ZRC@ՇɥCVh"~O^p⎥Nh(X(Wp]}cdE,X!z-,2,GhAʶXj0$,3Xm-nݭ։A2mgXCr?,Rd8#:Vq] iҶ 1 `BEXn)YI9EV{"mDj a[/cŧE-i-RCy6-ū oHyYV 2obD5A-Y`\FJ0FaDP/_}oE!fv *"Zj >kHq\[2fjyWuI`ME!Ç( ȐH~Kݻ\5q9F1#ɱL3e3]B6sK4W[润_بq1aZtM621JL˯6F' R+ڵ^Vr[I]&,2d^4Uj uٳ\C?Nsh eq -aaqv#87u#oǂסm/LyCfcd|.rLl`~SvV`lKlpMSG*jE\`7p_wɰkR 1;7~>̻DGq$YlO.dEv 7#:P1$c(?dO*dIhh kg螠&gh$Ut}(?}֛ƒT~餮ԛ ~.}k*Pc^xYigc࿲jfw ~b`"(h „ &! lXbD("ǍE"3A h Q82H@7sрCb :4A|RrP=q:i JfjjR˥ꄢ%D6 0@̙5 *enBc,|Q>MVbӂqikPFz ypXoPQbYU^E%NiT} jފG=ܻJןgny6^ҍ@II݊6,XxXa/4YZ?|pNcɩ6'I[4;ܸޅPN9PjAudvF=XIX[F[&H%7 BVuc!b'64@>h顅#z@ɁYQ}2({Aeb}э9$r~fe$FAQ#D'WDe `GT^GB|ٷxe(JE("j\ iaWɢ[*ц9fQA!5cED%a 1jR& lj :h-GUJ]wVt`{JғRI &Br]/u/Bci$r6fv\LRĩmX*. Q :\1m`2fɨKН?Xt|Nt+Ŋzsҳ*, kAHd+fA%$B'iuIlm3OʚiAj:wAb7s(jJ;6r?"ƃO~B~RmO`VyYVu]'BYw⩠_smyG^yrUK{տ'={›!f-"ԬdZP>UؗwYOgO^K'1QF֋/gc0bL6_N4})\2`\|/!On|9 q淾:q` 0,sa|b찁 qDH87qB'*HaEp{ف!U5m%^"cŘ0*GdTΨ5-XB9ұvdc ;q!rAGv8C2I"Gڑ$&x@=Ē$(C9P<%*S6r|%,c)Y%.s]6ҖlK,_'2#i%4H_DfDxf-`_9G*14ө:R$t(+Y̅sJ&i ;NkePH:q*Tpq֩} &9eU(:%BG I4/CZ 6B-шk0DYG* Y^RE -aOkSO$!)˧9BHL^j$ӵuߪT:hŕYX\B 0phbIBuZbѤƨ\ Djnɕ[r[3 =6&7Zc5Bj"% PT!rQUnuUBvFsYci%4M=,rթSds뭂߁zAQK"FgR޼E~Դw˂yVJ<7{ݒ_hJ U@@PSD?#3=p]~ h ! !)D44S!5#&t`fC PJ/a41[gRx>IO ʽ%1L~2(S1eby^r4 1Yb.3l3n~$,9t3<ٳh@ x&fD+hf#eHKVF%32/;6SH>blڕ0javsڐ4ȯ "+t*#?yWMpn~f['v|;,oft?D$6e<} zZCh sIH:UC#;Xɉgd`t>ma6ٍG)sm%|q" AE-BYȂ36!aE&]UB|"2K'鮞stBQeJ#Q9YEMN)*"MoSAtֱJ.;Xd+qRY# 'ꩄ$g+5y)>zQ">ld-H;lZ{MԟU~ZKy?,?&}[Ȃɽ 3ڟmܥ3m8y>T Y3wvի(GαqaepA[PY j " t`-ՉDvцb 0_MR@ L_$22O@DWVCtbMdGyU jDJ׹xD_%M0_"G F !X1ElL LB DɆ 1 R "C2 RG  YMɨ@0{hUT'6kc|bҎQN)}"E|=ƀ㜢b"}eI̩aw]|MD @cG23֏H 6$ lR xT !!؊i Qc=Q=PݐW-Y,PD&"]ŃpM JZVګMUڽ"\gƨOp]q|W\)$|d AĻYZQڗaV" WWj&Ed SY%\[%]\%^&]%_$%`F^&a`&ba&&cb6&dcF&edV&f_f&gnfv&hg&i*h&j:i&kJj&lZ_&Ǐ՚m2R9nJqڹҧ9$ep T_$€#=tVSqZuN^t^[x簍w:vw>:B [yrEwc#XF;fg'Z'۪%qj{~QD$V@YvGGTB%uHX[B\R5\BA9BņuJP6 T\yK \ƍЈ6$|GxKG̑_QAulTvOJUCgDD-ˎN(tiͭhV%)}`NI^L ]^m ^{^(xBO_s4*jݝ ީQO^Iቪ2*FA V jOMPݢRQjDRAIPH"ާUjuV(።R(t˥hU  ͪUs" ӭ}3z JHxֵ_FMS_$^+F e-KU_eAf^ULVֽb_ke%a.Zcr`P !pfnT󐖺^qK(nKba,+R (at Ȗa^|FҰNXh%B-mkav&+aB0gIӈbHWf˚'D-"XsޮM aK٪N#d"ٖ\ty-Otl>׺D^s-.< Muu!vb`'v+JO|%J_ OPO=@ԒQ ~@I!DJ&H߯HOXc.$?$b+_Б$\FTzG[BЂ5X^cnV$(|kҥR &/]h,bŮ00 00p!0p0 0'ql.1?qjF&Wqh^1woqfvW&qd17qbe)B)A - q+B * 2!3bA(2#;*;YzQo-(%%g)O2-)8".B-@+BTyDzw{2-&3.B.,A*2~%h'5X60#-42..-D5_ihH(LjQبV[.RNQi\)ñ>28!;r-؂-,4s[UVAN*m>'d*pz*ݱr^*C{+# -̂D*T^hU:k_@nkv"xlۆ,D4Y*24_ҡH5.&V`hean5O5I*F;$!OI ݍnN6BVVn{LjbXs#+BB*2D [rɘ""1M#2]Cрqho0kk71, _w6x Gywv77|;|Ϸշ}~締77y88/80GM8_51w8f8z #*R8(>D(<$xR*Hc*?*1'HCoƁ*'ۡx##L_/w+B'OŗBTys gUfB9IyC8, g:6'5]hń*/ [3㕟7'7ᨈ'{󠺭-((P4儚33ɮzE(dSS9` Op)D}DCY%Iz$`)>OĥF `G釺FŹ$ y٭?/Dʞz)R^VA"I UC>I !Wj:AMH|>Fj́tkʴ-M'*jh 聪QR)H\nOs >,"?SHٵ߮}z߹|ys1sǗ`JSusK P#PSm. )AK 9A q: E,QLQEEZaQFITJ"ykE#)8 LRI kLJq)Ҽ&Q,Hǝb F5 S1OĂ$C!2ጓL3M, zR=L|&>CaS@#Y/BTR )٦mOQI-$!MMUTE]WDYiZq5[uyUac0dmeVZCkɃmՖoqs}5ukUw]uyK{=}՗xA3NATN13@@ p[NA@ <ĕSH!X=n9:3MFY6T)vj"_kAP㮴:R?Ʋ"4_H&X `:3v9Qc_<ŁZ^hWNH,yph)KK.J?hH* Nۭ$˧D4Z쳫aw%[fi#@P!}1#J.)z#NΧ7}S_vFd. Kntқ[N%]le6 ɒHQh j1< $I| '6;M' =zs0,6;H# A0C!R"wi'}$6zneET:EOƄ ̂FRQ7IbC&&w;V!7qb;VȂ}߆g B$9!$H2vʀp@6ȍ*A$ 04?$F,F-6IiDĜh3Ƅpk$'#mD*6ٮ, tZ咷4ƨQ$`Z @,\cNOG%$'<& #)av|';yO}(r9;OaSMA lS BQjeOD-Q`TG=QԢ#%DMzRT eiK R T3gMmNt;)}UfC<ְs+4h. EZ LeQjeu' bͯC-wƧjj͂($q< [㓦sя;׃<`EYm&G z$=I`#+5t}ą)im]4a(qXFs.CaLF4R6-k*[~-#Zv<c0vU#w:tqO4lDG-볞S^>Q S0^%w8zoGށؔ fwG ^1E0%kI} $ň$Cpv]q,bC`E$@ $ĊD1LN‘t 0ʛ90GBOzL$1ؔUE).rY$K'F;[~pĖp(Ew\:9R3aO#hS>`h;3bK!:2 bh3껼p'4g6 pݰ32NbsU%;7@,Ôooijҩ~AȜ;ZWvM%Qq5̗Z\77@nvVrYv'.bބ4qMWF-Gx=)-ᆤurĹ7Lt߾xw5o%u0,#ƳAd@[Xll`I Mwl;7U~[X(]zi۷O}Kj #O! .`lACsNszl\D(~Iz lǐ~)4qb,ƒƨl iZoPP]>0˂M ,uoP!D+ ˼bH D 'rX I¬ ƌg ќ050ސ.iPȌ Ԭ~MѦ 0N: _D[ J+p$!& SdMGO0L!~Ӳ;">-t 1LN H6I$ (DcLRڢ("ڼыJ#13~ 4ژ\װz C~mئڌ-0#ٸm xMɑSQ)72Cc("ۅ"1a.r#a#=2^42$m$Ir_@$M%%UTX%A%a2_Lr&E&m2Rp2'&y\v'$(2`|((!))2*r***2+r+)E)I,-䎅, -(E--u,..qE..GG/i% i>K;t@e #>cD'>c&S$Eq@*b:SUnn "b4R33 6W21c 0* tD4I68]6c4pQ!,7#_3&>vh  ˶0#_ʓ&/Evo`#:+<q!rñ8^ \<A%/ >˒EAEBA9AB+9C=CA4D>)[FCMtIP4E>YYVE$FeGhFgFqtW\tGG!FGztHH.4IrI1RtJJJ4KtKKK4LtLɴLL4MtMٔJO%J4NNN4OOON/NPPPQPN5PtPR1Mߔ2StP `TITMTQ5UMQTEUUeUUYU=UNauVuuTkV}WtS;XU. a!X=YuNUYcZu[1UX9[orMA(Y<\T\;U]5Mu#S& `^C_^_``t^aq_?; #Qv %&b=b3a6VcbddeKVJ>֠fISotc9bj@b]v|deH eE$Bvd6fgVcGjO"kUkklݔ#HDJD@T`Jv~KC@h4oVF vp p  l_@ ڀ@r WnWqqT&v `L@,Ket5Vj 2ri7qsѶkkgmgK=@oôxqqoEb7$fuv] ޠvscJQq#v͠y'w?yu@suJu` W`xt~7Ku`qa q3+x owwѶfNJnW> gBBKAXI8g~f?nf>mxqp d`v  z 8eJWc׊8 `wt K@*Kstt˷P}؉jwVf9Xmm]@I tx\ L6,@g17vaX~6(S Jٖb yYJ.Pe"W(W wyJԘ͘JYך@~( $J9 yC" |`.H`{9qVC$Y1X@J-gaْ}6LQ ;Yc  L W999m@ PڥY mzuUWZ`~vw HJ J{Z ʀ @lig֠?mZJU` m?JC`I`ڒzV,٢iJ`Zur   w-[陳xڭoJs@u9$f TԷi}J BJy{yxzgwI涆;;:@wg[?Zet!y#KJ@$9ZzXz [J@{k[$ x<\~k6.ܙ+;C{7 @@Иul`a{T`H@/yMw=@əf֢;Ws\MۗF7q[f(~v鷫) &O\JZ4w~ ^%`K>>ʹ݁]9^uAK VwuUIQ~VUEtXKi}V~UyJWB=cϖ[S>>m?I2!굞U~Tt/l>~پ>~>~? ?;PK}sIWDWPK"+AOEBPS/img/cw13.gif DGIF87aQrrԛ]$W!UnpԛrԺrrrrr[`rrԛԺrrԛrrrrhԛrrr⺺rԛԛԧ꺛dۦUznٛ\꺺i̘$$ɗԺȠҞ*'" ȗԺMJB?85!!&#꫺ܦUQC?)&fީW|Ժ꺺rrrrrrԉ,QH*\ȰÇ#JHŋ3jȱǏ C. @ɓ(S\ɲ˗0cʜI͛8s$ϟ@ J4(ϢH*]ʴ)УNJJNVjʕ)֮`Ê+ٳhZ5[@ 1Nx&έR %n,s/λyo5l1K,ۺ qgHW/`>Yap$0B⪥ Quխ_׌딸 C1` HTҀ+mNmspO~2Gj螺4o@<)ۏ'}@EFuzsf-W[P\IA{`s 1؆ b~xY\Fq 򃉃ab"Pt#m6BgҎA>b&帝a9bfDBmeqpC#ts4v> 7ds͆c YA h]'zMv(h &v0 0,Hz&]}VgXjIr*c>VzxijtjҕPHrqrHx e?:lj4J:PeT|m !goh /J v8 0;l^M\`cպyg,}f̬_5f3k3y嬠qB /\R8 37w/R%\ҕ/z`\u^K#]C2x Bq1(4.h--8+o1o.}8rmiGtsn1ȷIdsq@qI\Ң\9]Ey]>0*}FJNjZ[?%a&`8V Y0bBD %BLD_$! Q`Ǘ-UK@?/]mRg@K 2^jI ĆiI!%@f~ )BLZF$W )JV̤S0N&2I( LeJ@8x8eXayn,LT%/YSĜ TG҉ʒVZěA!zЅ, HIFSpǞ3My}ş{R aҡvD0',%+ ?[R3&E}? T) P07#%EpP0æ 1$@7.3L{<ECFтJh2 Il4k2SߍZd4YL!9U1 e0P+D'q )uh+Pؤ%kLC0[Ƶŷ;GL mLpds4Dۺntc 8lyp9NA#,SC?ךҍ>܋`Nx@[R%ᩑ\.0~ ҂rZ JB!3soE ry]9!PZX<*bw)$)J!j}:DddMiqҘ^ʤ3MMs:ў.C@򔢖#A6pri4 K@vp|³6䦛k] 54Ql-J:jq PBwM% =f&wd tq 8Dt0 X%Zop.nAiP TLZɲ9)X$p*&^5rDeY=xWT#ڔY`.\% ں/ʫa;qvGWgSE-w[:g%{ʊ_9˩F.WĶ P-mj z t;̥R>ul{`ȩ_ύ.J3eˋ4ef{3 ׿ROpr\+/b_Onb?w\2¥8VV\Pc9s3w2؟c _twWJD@h-WgU--f!$zV,r@_5q=7@z%gg?7Aiy5Jy\dhݴh8aDjli=ɤI044I6xF:؃&@B8DXFxHJL(;PKP PK"+AOEBPS/img/imurg001.gif4kGIF89a򲲲???@@@rrr___ﯯyyy///쏏OOOooo000 <<>>^^^ \\\xxx666%%%(((kkk###ʶ555 XXXYYYVVV]]]111!,W H*\ȰÇ#JHŋ3^,ÁFIH9 ˗0cʜI͛ 8r@N @Q*U(VJիXbPE> ,,Q J98pBֻxw*U* XL3 !TN`P&PH̺VI0taJ|!*#NNq"BV%A>@knUM$0[,0⧄Dpᧇ'@* F B Tf*WB T(]$Ж!t#"٥4S(xp<QP -SL&i#Di%NF0)J\l)fA^yA59igwhyAJAA Jh J6P:hR:ibzi)) iFRD(ffD B*DJ*&zhlZꩲj͊ђP*b;fāa V UT .B@U⧝k(Afm^[, 0 C(F"C*V+@@ﶮ@ ePug!+ƀ@+ e i[m1M6=ʬ @@թlZh4A+{e* EXP7c(* нT7ǦdC xf;}y]vPF Fo⥙jLf*->N?N]<ǷDFɸO{m; p@9T"7X){ߞ R[PkO|Lo;Yb[Ȳ z*˴-%^c]*xU@[ѺH5L F+"0]$IDÑ "" XǚFLp$UԬb'cdIPⳛ5O_K@B{ G=.pmBǽ.{BюNtZZݩSY oARŁ3#hio[rn oMAnfS g<򺁙振XV?@vLv9Ag# _5[y|U'$2Hz$ٲ@dG@|%4"vnW H菟 Bg+)gĔ7:J )ɇ4if 4}yaT^Wv`S4}!j\"\IJK9 =@CdN3Q0D{ӹ,BSI#`@6csʫh$y&X$SFfHVK 9GxX;C})4X8`xK4Lq_էX*i\4OH~ԥB2;zݙr^6j}X"H' dr$Wa[ Jɩq}n ThZ/%].X)I{s8DCWCJ@{qqIx+9wL3lddnT'FT4l_cNASup7XNUBntWCLH Mxw#10^CQxyeDK1fj-ِ IB"+zy*bI1*fЍɖAW0”)+"PpB(1G9!i_s@`7 ( p)Ii &A8VXzP RIإ):܁_h4ꂤ7)PR T/6#P 6)#3FCrcA8zg_U\gjnxI>Q8hsIj|q7 j}Q5DG:l& p/3& B1i:)6:a Cxj}U9VD%i1ʤ)v٧&1# *D38yv/\VH7W5S1!` ёаbuI~(YUc%fF2=Pp xp1@k23$f1OfF[yzH.?[7aɪ SiZLyqAq!tKYXJauajA3Ax$y1ajh/A<`US tk`6b;U`a4pY0Pi 5 1𴨣 0 pja/=Jڵ XApj!θ K՘:tiu{B2K3>B{/B*E:ˏJiqtC.ۃ,@櫲^ 7S[˫\{Z*D ;fAjy9&sлd.CЉb@F>++ =%*""AʜF#.p/QEKQv1xڽ&1?l)+AYc{ qpkԃp;;D@ %O& \ܤrr/rQDQ:x Q1A"#])A7{@$H+pSb $93?ڲ{~DJ s1SgR+bX= L XI3?Ao@{2zm5|X S"qQ4. @q3AA$0 k;lhIҦ̮Q%}0:,waʷיѰ"yX7|}‘wł}ˏԴw60ػ_iaȢoí~k#mN}͠jT.A!ۙ\ܞ6͋0o-<3Bܽ-݁z53=zrx!Z}j.M*/^K=zw ~`ޕppjz+V{3*'PAa3 --M.˓2LPK~2%=V2d O./~EClj/p1B{@7IQ~F7F>mjKTt[ #^Ra2 6\,>qP'7 A DRT LB|}+I1QO# "*{tí>x|X~/1&홺f.+#.}f5?c=S1xI9b:7_Jpc.%ƻ13CPr3 q58F*+5B0K p(LfS@phV?Q10m:$:] %,.= @A PU`U"9°J/Z%#:p@B8 qÈ9 YԨ.` |"l !BIx*Q%RͥvU9w3hBژS0BX+p' b1… V!PLmA $(XJFEX,;f.>5taMMGF+ FX@TE !l€!Dܴ+0 #Ȑp &_R US/= )#v˩~/@# (A#IV 8*2`@8h<>< S?*l1= :pɄUm. q(  .|:cDNM-x NSN`Ub\P7,Sb(A$S/'B#8K/с<*GSuB.ysTI.|rVZk5<17Nc@"#J/40VUD ;YJ/"ҕ_%`RTXSB:THhnK\-V1m[$ԋF:k-DLp!e&fݷRz$#2Xr:.&xIt]VU}_kVW Zo!l6hVziϥx@9%4a꼮1Z$F5>A=h5_{ȃ ȓ"@*ľ5vIǡ3n\LKXs[qokH\Sq?*` \ D#Z/9&Lf|*#˫6UsR f4ZSʄu *w< (2BǬ^u$[Ew@'TvY8CA1TbLK R/=d1 HMC&0)`Y&.)q⣿ͫ&p@ ϥ,M $ ',@,1d>·H Hա(\`xga`&=++@ȌT %x`@8gGwɋ&bq l8y0 KVԒKrIY*,DQrb4!@&-,1b2z狫ft=QKd&0fIrSf#(D]Bɠ11i=)x)@`ޙˈȳLOt"CLd 2L.D f^RAJG.*BPHq*kpT&UKejSzT#st a_䙔lD@6ʨOGZi`R٨6^@h- x,AŠZk (@ҀFId#"A4!&5>C6,AK`("!,7.,TRdmk]Z6WE<3P H^gʲEJ";R^sR[6=!X0`ӵ j5Lnwj1!֗ڀGvY{pOL2Jļ.AK]C {`6-}g> pNxGA~ _a 5[# Oeq]>=7pMX@zG `61`@ Hx-gd(?gP<@ ;0G" C p B`*#r;@( ֏}dAz>b̒&Щ*1vOl@ް%`.B*40b B^ * M H@LZg[*KٱXEJ&HvȺҗІ u@ LjUհ5H%S㖈:f7#ub?:!$G]Wƃ@e/@A`f4m~s[$ $@x9^p#'yM~H(x4tGr\ Dvs5 X) ^|t/ }VG]H**:ug][Du(1s]kO$vûwFH|N]^][^8AvG` eg^@@yЇ^'}M?x`xF퀟|^x^(x_W^8<@|G_ӧ~Gs]5 @G~.2"Y_p>S`k'@>k20/{@[1<ˉ<=3(@d?F9!Q k@: ; PoK t@@|{ /J@0LA!$<5@# ,Lnuێ#+ B-Ux0\'+"U!A TB!(((1Tn'|#5p7B­ 9HDK;;D>C%D <8 L+-;UcdVRVS0 ( =OZ@ H*`!LxUV!U< PN{O!UMiZ V2X%{H-se%>a+Wz {uVRhudM*4, *D-mԢ8H7sX:IX)O XTJ,YgP琈UxU n]T `TpX2Ё@Y-M 18 $=S=ХSpKU4Q( ES͉PJ+*X`)EeW\Ǵ)- ҤUVeZ\`\J1ő=,h 0V%U]-uںDYJTGTa{٥[$BtޕUI ֙G^}_CM޹ {[]q޻e_Fq_ `-Z1CZ eP$lR `O0|?SـVfFPɤ)` 0`0VYa' T V}La Ua9_-7D '+L&Qxa؅bvTbTR#c0 /nJ ͝b*6Ԉp٘ecS-U&]âM<]=.U5d'RH!;3|?d ==ވfN\dFdAIŜdR`;U.ZHm^XvАW!aZPEUm_~Yb^MBe daGƜ#jF.]n¬XNdv~gx5qNǹQOUHZgdTB~ԙ๫xf6nh~hhhChHgɝxhio|U<f \Cc/h7Jf NF阶nFu2f*Diq6j^ii h(6&SjɥY+n_Uk{+,&jdjpj1. Z~_6if`kk.>.V6vR뙆l&#^ʾNlPh.jmc~~:Ѷ>۾Au 08]͇"99UP| (Ķ@ߪ9Q :y(W\ : ": ؞ fmxCn>XgFm" Z"xeߦg>mնmI n^o p؞ o_wqjgkl1Ќܥ@o^3evm4H ތ"@BqhDnrނ$;r7%p x YpU+o,q0 1Opg4sF4Yus^ŰCTsN~0ִhqCODDqE_";U8 pA_lFG!| )_LjMh rОҨ qC,u!?pۜUҐg[0 21Gbr ^udL (J NZ xsv +ΏhR6ٜ nGt~hn.n!ޗwfw}7o&zY/pvp'yi/ ( fwbj=u@x$-ܶt3ɹ|HîW,`VQ76nE"&!l1̗ jy'_bG6v\p9#\rXHW:x3J;+L.[3VG0k\L6FIiuEXbw,wnwvei#vDzx/5M.-U\ gj/`owz3|qK>Ϭuxn;Gxòݱ^#(_=lX.^TOOuK=]Xno^Q ?A+Rq |' |I:2 $CRT KeP"&9yӡ/&!Z:jJԩϨDϩP`RddݘUCpK `: |UTϊTzlakVa, VL5,B.kfmlgAي1kjD1W-"^P @d5pDA|W#-HqpU$w%n[ѵ.m`e!hkD34Q=FV2{k\*νnp\2nu;]ϗYwڈv5Oak6@ÏbAaц#lqhQ<ʦ+7kɊXi"8=@b К\ N~re $&h"0Bf6O|5n6@Uf7Yi&;PKe 44PK"+AOEBPS/img/write_metadata.gif3vGIF87a-l4fҡMg(kX#)I{M ഩpl$S辛ZB$x(9U[ry^&; $)As$V a8&L H!Ms 2 J5IO`M&wxfseԱDEƑB aֈT8)%sGIDlbɉ&\ %p!$4!RH56R8UX@8SNMmL\( /+Dv&1f= (9NM"`Tik5UKkTlmL|>1(j[ۜ*0ptsy6`Y̢jhw.0V5n\V8;^RktA\:"I npXS)agƽ|kˬZ)9lC܎X*LmZG&`+ %ټN\5g9GȏÑ`nL|#9e7Rʆ9BBE7^'h^e1Iv&ljRlYI',eL9CJ;Wd5<‰Tf3cJ+`p\j0nPu*l3K_i$&cҖgJ-LICgDrb2/|GB籴ūl mhhY`JD)iC˙.t]6/.yk Z9V BN愹YϵsoRe6y3[l\ ɎXB%LT%Àm; J<3Zŗn)/ w2Tȴ:j}BE06U'4vV53ev5E\I(9>`q;9ͷ |jf+?6hܸu8&!|DEEեO{K婎 Yj.O;X$aJwl\c)2|T*s'*zE8q;NTm*eri+yB2;q˱c8gV a2{ЉlRS&lY+Cq$Pvvi=JE[sXfF=dU5^?&(8(K;QѾl9g6g:q3KcBW7mW[rG^{yV Kq3pc=Q)[sm܆ #4$I2n&Pcw,w^wcxXV""@*a"RWUS*&\Au3+beǂXjRj$5aL6cTbNr7*A!6R542S2X;qUA{-g3>B7U)cjg]DLS,C!xxp>t%x@h?`#U&(c:q!0Hh#=;!HB"R! ,- PW`}vϘ)e҉frIdb02tD޶e*!c:RO",h-2`fV""U{h/CF Y:Fm5U&#*Q!t*cy trk$2Xh-!0@5k!3ڣ7 ,=Jj0- 81+ʢDҢ=SDqA!?zp<JS ' 7@fJ UZ3jN8AVJc ?h9/Jcd 㱡EqGzzNE;jsZ>HZ*h1J*$`@p;JY:^Z3 -J w*Zzz0Rf"zjj@Z_j:1 k;  fQ6!    ; J! RM˱ET23k K*<;69X6Qkz’@@J݊A yD+ڭA-x:` CڳjD{G7a `3j sO*:]ʳ!:0${SFy+-$[G1 j|Kk=kи{;F6Q=3:xƪڭ)ꭁkZyq˨ުʩzj* S;8! )-Dsj$[JKˢ@1K<{?q+03A@+ڣZcz9Q3ڤRR bk,j6Ջl+ 6>K;:Lk8>";KAP";K<<,`M|kZ 8c|"{^K+L̰T|jG$g{u̢C,/^-+ +~!YJ f$'\;):0 ߺ"̨[91j @+ -[P- {i'lʶe`Yj?nR c!J0LP>e۬BNH~jF :`@ 0=I)::rZN'ͱ+͂CЬ<Da l)[|^ .ޫB̰K0  ͙LnF\^{:[˼ΞмNҀ^ ,쑐ѴN.9ޟɞͫ# ٬.龞:7/(L< ?6o,?\;s,.02668:^;@US-C*ؘM:iPlBeŞ(b'e̜Eɩ6] 2FXbƍ?ZUgzD(lف8'Dڊ\+sR tZel m4w`  |'d͝?ݱ䟟<]ڵSfM"^g .Dm[|i|-iޏi;ϴJN2$JI?r[p$Aj0A'|p"T0)??'꺊@D^1Fg|`$Gl$!O"L֢K2 Bꏾ O*%bqF/. K I/%bK3׬U,77)ܰL0PL LSL4RI'UDM3ᔓ4D =CHGN=u" ZU4I{C$NK p$vMls6Ih3V$aZj́8V[lA` n5mm}o4L0Q:b]umNt4`&1kK$MuC"PCC*>rU!J'qK.-6eS?7R%W?iZ53C \yfwgBYN j1DBN2!MFEbGbUS!<&dD8d3g-ED`il5D h,!?pђ&;0gnY5g2Ekow2dCP$IKĒ->y1FȄV5)üe7p4-_3|9N7@Ɇ{o7&}w#΂t,u#9&qF`X$ AϫX2FYnJHehTR; шGԠ:(@!aX 1)NkC5O_L?nOԡS"!12DO8G:)k9wLX#؈BH}O-:"Ї9HBC8Q;c(E9JR9xG?B;hpCox!Fn1tDn9˜ƴLB "a(M9MjVӚלkUx #0l -mg =Ӟ\LhB [ ޤDhBMQu?(k)雍rpf~4IqkfGEjRP78tN]p#< K^Zuzh<9a k1o]X"4@MJ5!.DJl`KmdhjS*;a*VpV7 o&H@B!q-jӰ:A  A"@*6ÙKvj.{`;\ Elb; >0pqp@7h6Oͨz.,!nCƐӮvҵfT%"f*pM(^2*np|&]oXr0{*7\WcpĀ6A t8,P;ȁwX 8 {]NsWr\v28NK.g2nf_.qͮPdx8 nHҰu ]i16 <{ MnvIʈ<%Ŗuj*3txt40X00 C0pV7Pʠ,d hP ,!./ <-\r a8x _ \TfzɈ6|x ki&ֶO=oz,իfKf}0A hp2d e84CA p. ?xmqt쎚^?s[iҪ6KoF%G8s2*]oRx쁪0Ta= ~ Y WBʐ/x ?~S_ƹ@zڈbFe*rP׽M.[aʩ=By/<ޠ=:pUg5P*Ta Zz}-nx\7 |GHe?{[z0x*#0DC49T4$D|AdDA\ADG|DJ?M.# #vlzklD~#>^88F>>@ANJHQ£ہ* ȅt@?@@+t[ѻ㿍\IH/ɩJ\Hɕĺ@ylIʪt˷$||ʭ\\@8AxdJH>dLI\IȬKI|83``Pa-CcLeԚj 0i^U X?V^wecY-bÀ c#$EfNvhf(hjlv#ln"npΝ 耓tfD݀EuQug Đ(]ОygIx؅ԪYZcڄVNug0Ѐ6 XIW=">h{-}R!G mٗ~^ >-`ZQ55Q<_)0Vu7;nQP9hf C(sZەF฾Y/ ةO)l ⭮Łl 0Ϟn5!vYQ-Ѷ 2f&)~FfnٹIUgeR#kNdŻ)KUPӦiN#nL;b*n kM)~E; ѦsM|]h1;PP&TV?&8v9:c3p`&p)T.17oKqE^oKN2>3GRSV2)``e;&Wf'be e#ϋa*$i$wrJa'*r,rU.s0's2GsѦr>8z4?(xgRoр{|*h 0̀ fZe 8NQWS 6 X`XhvZZ>wa] @2ΜBv\ %sihEiQfGzy2j/sڠQ(9k(ui6YpUUOηh"612|WlF"x((hrrxĨjx^c_ޙ/ _(Qk+ԑF4'SN# eXɭ@AW`>-?ߵӜqhjkx } Unof Ua9ow;'9w t+nUzbkU]?vk2FzFbD Ya0ιaCbz.pG^(Y:5aymUROGbOmt$ w{<{\I2¢g?wR80xwϦr0(X .4`!Ĉ((P"ƌ7r#Ȑ"G,i$ʔ*Wl%̘2gnH` 8$E nI(ҤJ2m)ԨRp ~bǒ-k,ڴjfj0l t p]wT BlD (1d&Sl2̚7s3eG.mA3Aokzמ, C.n<4+o4"zu 4`*9һd=Et5p]yw`Y!X :`KѹLǚk0Bu\j\yW 9!˵(z/8GpV!`P@C!\"&@$IdE#'=ؕWPy<ԛY7\]FdA+yJ̍eFeџ%Sx`5&Nx(%(b-@hM"Z)y-ijUtTqZ)%+T1AYTˆz@=WQ:++.K9j+j;&;+q*<ں ; ӻcv7prWvAD,( c>|.+,cQC7ü bd3tyEl,;=tBd<mu:;{͔Dmےy__n'f ᚈ!Xv}jky Rt͎leXbeJ_;84H]ZN9$~STv敯J}Gl ; _ŗb" ro؊m<[o'~~_?>G}eo`U??]I$EdP< >)|K Rn3  ( Sסp.|ZҰ]2!sx갇>(!'D<"c$2lY(E@qVR-r~"Ø-f5nT(9v3q Ar!YE2[#Y?$&3Mr$('*LLB܎KdeP*s BJrfڣ]MvgT겘!lfA1p^jc@*)M ®s4 WsNy\N lP;"Ov“ yg<:鹪zC)62|(Fި"'>ųFz/m ёx#Gz"4CJҙϤo)NszS> pRmOj=DER;" UUխj\jO*Q0+ZϪִunm+\ `ҕ_+^7HƼu~{+`z669,b2},d#+R,f3r,hC+ђ=-jSղ}-lc+Ҷ ;PK 3.33PK"+AOEBPS/img/cw18.gifxBGIF87a{!R9sJ{kcJkƵֽΜέ1c1cֽs1c޵1csscƜƽƭ1scscޭkkkkƔcޭkkƵk޵kktΌcέޭkcֽ֜ޭ֜ޔΔR{{ֽ֔sss֜s֜s!JJ{klssssֽsssssss֜sスs|k޽֔kc֜sss֜k֥֜kƵֽsssssֽ֜电ֽֽ֭ssssssֽsskkkckkεkΔckk11s1ƽƭƜsֽ罭scs֜筭1֜cΔk経Ɣεckk絵ƔΌεcέkcέkc,H*\ȰÇ#JHŋ3jȱǏ CIɓ(EXɲ˗0cʜI͛8sɳϟ@ JhNF*]ʴӧPJ)իXjʵףKٳb۷pʝKݻx˷߿ L-ծ≮ǐ#KLra[Z̹ϠCދYѨS^ͺNˆʵoECa B2pፉ>GlňوY*@ۂxs\+^[僝@oyx+9y!! qVW_`_`A݇\RVNql7l1`W׀Umխq~蟌E$^2蝎maK%e`Agc^Kʧ05b ѣ/ I8c9Ҹespܹx<"aU5IߔtVmXn^c_Uhad4Q)s>Z s]*[R찏F]ߙ%ZgsyMj'f%2װh[E\({ܖNd.vX]mS`|'#tݺ/m BÏ#}]zw޿$ t'ti<'"oA\I;&|;4.Q+o\U:i+o+Yfd\C|q"m P>؊pG|>p%Q|}[υ8yl6hs˜ =`fojyz w-d\-rީhx򣑿L7.s:)%ŭm8j c .)ZtC"olu_\ı:&vD{HF~bEvi_AZ] -r :}U 27BΒpѰvqn[61)SUeȨM A&mpsRBrP{n>DRdPS wA ъ ̡"4ȉWBĉJ/#澈#ZΆt"L3JF:D#Dٙmr"XFh.Gz@uV'Lj39Fif\F%O\y 1:yۍnG !EA="&u^X`Dtԇ9*qщ4M/ :$yV8YO^3Y*[h2Ij5t(vlAyse%&#$W1(|籹G18NL .}ҳeC6ҤVzzx8O,vҟ9s:Ŋ)Ԧ*UoI X8iR&TBZ,%:R-jlp/0e t2% +, k;ƺ#2 BPPMqĉ}}!JC:<>fI; XѾvZ~ӱslxyb"۾P- KiєW4fF GԞ;Mzכ}5Mm{KW2L`wN!;\, [07FGǕl6W&V^z*9&wlu[y^C:RZ},eЪ({+5d6w~V Fk9AM_piB3 C^~EЍ`7~M_'P<7g%U?yG q0/1yy}w~ڷ| Ѐxܧ @- { x XyܗP}뇂}((ٗ|w.z8}D $pGzt{wNY@QX$ y`~YH{Gga}(@(؄8'{yxyy@zwqp}G}۠},@z,8B}tqp hY r xq0vHXg k؆oX}hwL}8|8'z@{(8yȅиq0}wq@'|(ph\ȍ߸稍/||ܸ(Ȍ'X7xzȍxxz8}Nȉx+Aևw9،y7x葩7y9(g z5i~՘xɰyxP0 (({'LٌR.~,ȋi>Ryw}7)(W(9)W(Ni|#y*z)Y3AYyi[1W ۰J[f-G۱[8"[3A&.*,۲)0[2;!y r#=*y=kSarw}; չ{ 1F+x{g>Ѵ[|4X1P+Y{׌]kXzN؃Dxn;;{5L[>xCx$jc,x8D YIi[HkzlJHGnx˺zH(ǫ88hy3I}/Aq zqm@;+3yнn+;0+拾˾ kk7y$)HXIpiNH +ayG9v`ڷGw@4l0v+!r +zt`C\> ۾?y{twF x|w9=o),Fɤr#:{K$zi~D9{)$ (Lv9~,-4,<Öe\RU7l ęy ,ƴÉٜK ;,{~-\ʋz{WyLX¾ Ɋl2ʧڼ{ͦͪɚ(y798ɠi!Yީܡ쩸ʡx `扥-瑫{*0+,|+1|D!y^r"ȺW++19[e:渦=$*xF*c};Tz6Zڦ m\@a@SyV}/*,LL0ڻS-'w]iMت[ DZ {LQEMJْ ;ڤm}ڪڰm=Z۶ۼmَ]YKȝʽܷ=.ɐ@OlPrB=s91Ĕ]Kqy} qz iߞ= t&p`m-Ս7`ލ} >ս)+N^/,NN27^ħGzN /L'> dQrx ߑlS^{z<3/]aH^e.g$ge}- vP䵧m}>yG'~ݎj>-w`嗰 5 |npn9Ĉ=`/np~z\x蓾ɨ߬.G \K~⒞އ> 點E PE=N,\DQ^0l궎@ᘮ}ٛWnݯ,9/~ p/Njn-!Q> _Lҥ^{Kw ɨS~y3q@+Qz~:wp@-^_] 79FO*=獼+! n M?0^[^TwBSos;_{KO*[x1 ϧ<=Ol |i~Ig `>p Xj~ UŻ7pj .o~zkL4yo]o|e堌r;è|\OצA'@ x $'6z  p`yPD=~@$r hE:,ܙh,8q8h%!0vlbAy8t6FqfŠq$FcUj4W1,K;"%drĬ[uZ6!˝=j.GTU2cd kƽC 6YrmW E;42yN Rn#IvlS3@8/aÛfjaQG =*SwC*ASz N]~bv2J碛Zi"ʢ:y/@ ?\Ɏ ϾɳnؐkEBB*Kp< ?/A"A69.ޞȷI(U`:t CD +r̡8~"h=.bS>l>R;,N$/r$;OAkJθP2ݠR8AP˒GJOLӑܢE'nJS1Qq:QɜcRrNlvUYcU_#3rTAHNOJui]w߅7^yuW' Pzw_J_V_ a'rax_},&Hʸw1ΩNq˸aOFyO ̔;ZYߗgݘA-6f:h&:螋F:if闏v:jjI<*w68X:D,$*v4$ zߴ=Hݗ&g<4vnw˾Pdp r0V`'ץex{_ 畨cCZV}^gx訞E]9M؁FgW$"UK8<.?pgs(|t8&.YteSSt ( „?{,sf C m 8([iV>* >'bDQ$UL!}Qi&gW(NtE%[aSH=aoK  Nz)YS8DoNF9 qG$S 8 &=i3 8nBG:1-)cAF.|H/e#{]1A _R4G'+FT'HKH!( ODYHT W" =S$? o t1dU1eÑ!2S&Si 1suDI s^btr7&8k#)MJ_ӑxG>U#RD)+Wy wlgjF We!Y1cu=#&R7ADq+ Ԇlܓ(H.KJK~*/Wֳ,0+Ta԰8 p#6"7hەYVH  Mh"]QvZIM !]4#PⳚൕ itB q(IyOg,<%1,Cu]FKN{ՎDF(xpK {5WA\dς-m Z2L,W^58OjT]5bXkSE1])VZ)HdXdQN2pXTAQ|N}Yls9࢖c6Fh&DˁI9Nj0csVr*Ufku 2 j7iJˍX+3matE3 H*C-iTp¡-QZַuu /[׿{lbS;ZD#>Y^[=mjOj@""x`r=nrڱeϝıVׁ=$rT"6XšTQ=q RC2Z ;Y:IƐlc)t0mg* ފ^4'v0L4yk;rg"j+tyy+>Lm(H9Xnm5plt.OwnmPk\de}0ǏW|F͇>}Ǿﯟ}~~~Gϟ~O|?{Pg+ٻ+(8 L`@04HQ40|Tha@A2.0b A! t!*,! ,/Bc&=6'$zqܙhC;.h?@2( qk'Dyp:D?><.^H/ @ST?C24DwADѻ2 C"O:z$IrY V93 K92N*[&D'lH%`#$__H v0 *:p‹~zhb2)(J^ȥ,!JpJ聉 /xJdJXFE`7L ȝRˋPJ*<ԼKZj'4@\H^$ F˼LuAmYa K[Қq@4>-'@@B]B5D DUFQGԓaHmIDK-L@NOU3QR5DTUejtW5X([ɩTA.hCIÏU"҅]E VyCE(aV{֏hy'֎6uaxӞԋElVoYpҡJuWĖ{Eym sU|ՙ)Wu#>{Rى:ܗ]"([MEX,xqX[$_m =WTv%" ,z1)G(8A1XwII) &rLXH2<GG{D )+s% 3U)^9OUZEIݡ!-[١DŽ/i[H 'Y!9E= fqӪ=%\]@ \! Yj@$Al#v;91"%!;nؿ*$#c YY"Ac ܌ȣ͟eI=$țt5 I"YM~] ?\W*Iɐ$YbЕ I\v"$2BS^?+} WeDcSҪ⺣Cb⚣-0օ`:)˾L3bߐaӖ\ˀ(E$YY`c,_;˻`aUˑ3FM}h%klE v+T ;b%p&`: ^a%`H+z /ټ(a/".`iË(0㳢:Qbĺ>={0aE&/IΤݽ3.ߚby)dO.; ϻNZbaIv(/J> XeȻOhOz.;)=V[O`^0H6b\p }j!>C H2+u%C1J 4<#ӱ.)C9p[t3W!&PWQ (!e!'1*#~<&s]: KZ?s@#6grh7"Fi4gC=gw޲+M=T>EK+Z465*Q#ꠞ\-i\&ЦꁠթVj\٬|jJkY걎S`2+SP+xɉ<뻞 C䙠.I~D(2F& թ#&~WH6LKmWʶ>m:l׶bD]q2$= i'̅n5fYHq9Xm9ӾZRoInl]+.(=L⨧߾ (n@nViU`=Wޤl )mL O=; '^. ^F&"6Jqp?D 3㓕B+OBq)k&''`>Շr=+6*s#23Gs56wP8'9S;W?YAB7t!TDEgtsGHtأJ?Dtt)m w&QsD 4)?Ap9X bld]u|uy ;X)]nHu X͂odWIvk=ؓsh iOfuvՍ_Q6FNn]f:N. wWWϱ}D8Ti' XA6Px{ᒇk3xǩGp*cӳq7o_xgD8ShaA'gH(WHP~H9k/o3^8IpH<նWgB B; Ypz|V a6 Cugm1{m|ʇK 9tW i} L9xH{Fxݍ} D\m7ERҡ|ʵl}g?a(8-̀(W}ن}9:¤r~g}mo=&; TP:DB;ȹD 5"Ȍsl aDL),h!$ȩ&R?&mTdziī 9zB2[.4DvT=3o{rE/~z8  TvW>_ǖrMhaJr!} x")8 q\a/`x#yK#=#AiEy$I*y#K:$QJdSZy%Yji_[z%a*٥ey&&mR:9'uygx'觠z|"(J'Zzib)_j)Fڧ_PGa0b}(+_S6^yI[*$(@p 1"k;G =+#F `"u*n-BmkXq!lRPSMk.N *6 m(ԑ2$pA A@8* g2z-O,6Ss]Tv۔$] -?|"lqjn̑$Y+"M nDx\R٢1̘\S_ŬUq*n7@ַ)wQ^0qH7CQ孮3ߧw93$4[M^EX_qr'CG^xw>rVawdpV+D!2z-Uvq{j!˞UTm.JImt Xb23!HGP\̼տ !d?͊"U0ZY7 `zwz`8,Hr@E"' "`|%5˅H.!N!* PG8Er׼>< HyQG9"zNNRs|g,w~kjj$A @OXbV:H#*EPIUfsKݡ ƌ*)ijV"guH3ͣ2 І&EJα ĹhM-TY%V:3Ng=yiIU\L EkԍNl&`cjM& g "e7 -I6gzf#el4E&07jVx(vL[Mpnd8[.~\ . ړ}D7x*x^oay7 mz 5VnUa>y \04M-Y1ZbX oM $.* $:D?2X8e 1l۷A1uS}^G ^DsD!ׯ'뭡iobV<+/ѡ)IvrNd%uH+ wY*ҁf#GZ6t/T~Rq7jgQVnEy:T U7/RD%Ē?f_xW?BKsJz;%JhU_TS&T_!uq_o1k r m\iE U] DMP 6m`hqGq\El,J e &4a0  f!J(Oix9 EqE{-Xu׆!ZdƵP"WHzWFܠEUE)^0%Xbs ~" "TPd$bD%+"l"p#8ILI2.T33xL#5BW)6G7F6~#5^c؈,:[;<6ͭ92D2#?*>#@?$A@$BA&$C^B6$D:CF$EDV$F:f$GnEv$H"F$IjH$JG$KJ$LfKd\NN$ OdN\A$M6$R.%S6S>%TFTN%UVU*B\A W~%XXze(dF%B )%]֥]e]e6y(a&b&fb__``"@aHa"@c>&dB <(Glz\ffj&zD&9.d(lZl֦mf&fQtGI8DT DBt]mD)b iPӉ@lP)DPPEg8i/r Pڀ e|ꀣ>oE$Q[QcEP+ ~"V3i~N iIXnıe (kv&TB%) N%<.kɲDF 1 fNRqvFA((LdɪJL  ꮮGLl lIp /IaFu`Uhۀ#Ԓ^njJVJ,+ٖm lx(bE,` \!6(ܲŶȗ}sbK@ubǕ>'=hr["@$f沀βPDZSd`&@ʮ.붮nxY+ȑhn( //ؙܣȀ.DfAWeY%p%j&U/T*dφ//JI//r/*/00?'0wc60G0O03_0g0w0W0 0 0 0 ǰ 0 װ 000 ;1,171'1 'W@go1w0g 1Wn/1g1Y*@1q#۱ 2!7!#?2$G$0$s | &[H'%)2W2CK +H,2+./r2ClA>uV^f4 =[6xGHe@X,(6j5o6 \6NG( Xq`d @PvC@ sutOD'7b @ h@DsZ+k6*"6jR.*) rLzi*6ҷ{GwI? 96^r[[u0s3bs8[0s3uctWG1 P880- @ (k˸Ck8GyoK]u 04 _0,t0sg8+t0i@#y4k@xpl@+v~ Wotc@ @4N_@{zcOu0788r7[wx  0GG,66z.;;[:4EL 7{{sp uNctǹ;z;J;W;2_`yd773<+4^]6wDK|P7@_7]{@7 @wo.˷|L{#¼γ2K$P==W@$|#=G+=/1/4<؇؏=ٗ=C@4 sכ=ڳ=*|+ؽ ߧqY>'~)=@s<<C>觰M0'>>oy>Ǿ>׾>>>??'/?7??C@;PKٸ}BxBPK"+AOEBPS/img/search_album.gif\%GIF87a|~|}y995ZC?jVTjKMyTIiF?yXWh=;vMGXN`Rm`p^yhqwxlmewE>ľtuq;%'Y<9{d]c^bU%'$H)(J32H,9dc]XKQ5伾W43ܖŦrhoL=?U,-QEؤ̈VZk̘wžcR|yÉyyfkÈzzTVPe49ytԼIx~4f{Ѥ>:q윢ʼŵ{|t{Ѥ>,ط_pH*\ȰÇŋ3jȱGm}Iɓ(ST2ʗ0cʜI&ʖ6 iqs]x팁.7Ŧߠ3T;e]Zg̝wmP A1ǂй.PЖ.]t5o޲(ZD;_ 9ZLBR5w\5Yn{gmy> ά\ۡ&CgE/ǠhQ @[] 6rm΁,z/ɶ#j)~#hIgs-:ہ|9ߐd\EG8Ks a7bMxh^XBmaD \`{8| ܬd $ 8"ANtiAPړq-؍ k}бx! JvCYv"Pp)8EjF1 9 jnƵvYPz]~cbcM騪7|.~z%[Fx dE+"ܳF-4u.)JlPm8]g7(jmۏ4G^>u堐Y<)Ձ\C=yoZżei[-ﳱ7ūк&@0GV-ǽgQft`~֮\AM֓ʂ\Vn S m68]4M!+Qtt28DYa@]-ErhxӖߴ5_plpoxۈ-p1ƀ- 驇w7,dx7t6#O)t:u],nڍ:l0:@F\u$~FG ̋2~QtNkFg ,1$]t1G}yzr]T/a:Lq\d VTh pb3@gw^siť g!Q|`z,%>Id㸠 (ϡZ rT+΁G ϋbPw Fû*6 Z:xo|1f^7 3GP~G"c4o8C ܕw0+w/ H@ +.} p7): fgG<5~ .N\sv=a3(QX\</-/q;7f'tC!No$ozuAՁo.Ώ@) p)[ |h[ŒHzP Ԧ_{bS$2Z?0J]/{)v$;gT<YX#X}ITgo 9?2?ϷJ'a)"d'VEzwcsc&2 Apr.] 1RMl{Z9U9`32ע)g W`&g<%<w%Ճ>U聂vRDPj7 M.(!0t!YGPu\`&,wxE g`(01?(-@BSz7BH `J22bS8KKl!;v@>+]09d;(Gba3;Hax@|s}$v$%h8.AjatQt6*֒i!XXUP#g)49!oe CG"K0q(XZ Xw>R]ꡓdࡌP܅nHY tYvɖuz}ņ|96y0"٘9'tyɗv=,GryɗPyٛ‰ 9yșʹٜP9Yyؙɜҹ9䩜Y虞깞ٞy9Y yٟ:Zy ڠ :Zڜڡ ":$z(* &.0-4Z6*3z:<9ڣ@Bj?:FzHLڤN@0elXz [O:d-16e\ [ڥƠ`sZvz 0PpZ o rz [z8Z[pnڦ0tZ[ _ ni0{+@/p +0`<Y`{ j [Yb*}`lxPj Z Z Ӡɠϊ@ \bOkiPl_S^l tj@ JM8[Z[ ;Jp\J[` j kފ'+ k q 1 z5; ) /@ڤ)k lJmtj`J]Z0lд괺JSVk][s `@p඿њŐ + { h;HZmj i[۴ne l:cд *V+ a g: Z{. ?{ ͺʺ{ k[ߺ ۷|Ksks[ڻ/K?;;k!Mr@ 6ڹ۾˧P8mKie۸dK#+Ԫ|::j0»;г \j ll %ܳ* vڲۺ,l !<=n˽+{a"+k`j M;] \kepWş+ ĹlΛ;« KJój[v|o Ǵ˼J3nLǾC|ōZ0@mz۸+[+Pܪ_kš h|gt@{Ǹnj<Ĝ\/̌˿Ȼ`Ə̣ߋ/0@S Piఫ:M+Sl][{ 0Y^@@"p^^j l]ܦlܺ@l=|).+n*M!]+}-[5ݲ1; =*> &|3;1mjzKڠxK [}6ZM`bdmAc:=t]v}xmw|~w-ԹӀ]؆g?mo؎ؐ=ٔ]٘yٚٞ ٢=ڤ}ڨڬڼڮ۲} =۶}ոۼ*]Ɲ}ʽܬ=ݣ- Pڽm=pj _Pi@=]Mbp=ꝛ<>^~ _Y߸)_@ "]&*>, 5ɰվ1~(n5 ,Q{e>: W C T~G_<?a8eN.(,pA 9y*燺=#ŤV#5dngS rN@ }^ƚ$b Dd~MB簮 ؕ~xj@ؠ5Ql^APN5TAYx$5܎Yp|~qA=\.;\ОΟ N^ .~oُNnϽn O! nu>츾%{?+x*49n^Ao NhW@vP]VX6>y bcPfhji,p\A^` >Uz|~`>^@Ps_^OOߡ_ޫՈ?_ȯO_oןϠ䏝_?ϝG_%8HXhx)9IYiyi @Zjz +;K[k{ ,N^mO_oo>0<0… l1ĉ 1ƍ=2ȑ$]},2ʕ O| 3u.gڼ3g:{ ϠD9ҥLA&m 5ԄOZ^լ\zرd-6Z\g׺} T۸t뒝k7^xk/q .8Ê;#o4`S,2, 4-ѷ0O3 ˳)Өuάͥij]t*g糜QYؤ2.rYƗr> z*ċ[WU{1ϡRe][VW /yسۧT_L{%px{)w\+`Wj(o֡`8#*n"afw@]7^a)H6H4(jaْ*d0ʦf!jBޘcuYl\ji-ZQgaK86i Jhclը#]")zx(Pۈ!bIYi.iuy]~b~:utw몼)c6 2ZkVܳ6j-^;zaX~ lI,f;+W ]&x y*r+,s*奄'Kĝ.K:孋1,%rbjpΨ˟%_p2*{2D/Bi=U @zڊbJ\u8\vSHٜ9*ms}Nu\Wl䖀w3U lI* ',Б{OU N.yo{63uen*-~6J_sq=O˰Ա+FO/.kq(4{l/;=B,*"or @hHT:d5$Tꗨ@r >L8s,tu+rŭ`*x>\q~V 7aq:JA^LC).h3ʆ^bp(27""gZ(JC B7|cp@ %!7"rt" H㑒%SKjrs$'? Jx2()OTrl)C ˙Pny-2 / ` s/uyK.plKfZR$5M*2 ȼ%3 N@Sf5trYf89q梜Zeԉtnӝ'dF r3D>M*"ą@{IPl"eBQݑfD9QRhFOJ~Hل@$IQSltu)McZ*! @Q}TLԚ7ͩS[l/}XA:B&5K fSV;S'YV B d|1RCjִ 7kF[IV&D0r|.@6X\`R}iU*uIaqؑ 1eY0(h(` x $El֪-siwl֠okX*@ @(`@pJ @ŠԉUϭiw*V7Ho\$ x 8 :@cT"p6j5$o*$ fF0x#`Ѐ,譂]Xbm†=d1Fqǚa" $,\ 7` xPR^~0In34@\&'cBQT@;@;L`LY(#y \5 @OTBhP*@ea,cߘ 8=@Ѐ .P;'͔51L Lg:ȵst>Wv3F J0\ Ȁ<Jk__;A`dA@_93070]#5.~,msn]kM( 3P޽/e  t!~?`y?t?k `Q>={]t:b6h:Fo ֖qqHfP;2}p؊"~ qvlspcFv)XijesAsoH{W)׊pH iXd4 ;p*jРQ*ѡ  ) 'J @#z|% /J 4 6* 8 J`:ꣵ;Z2 (I6L *KJ'ף0@[?`8UjF 4`ʦm: dfzjoZ_J{*tjpW (:KMzp*ň@JJjZfʪ **ɀʫ꫿ *JjNJɪʬ *Jj׊٪ʭ *Jj;PKTa%\%PK"+AOEBPS/img/cw10.gifZ0GIF87aA{!R9sJ{kֵkkcJsƵJkƔֽΜέ1c1cֽs1c޵1ƜcsscƜέέkΔcΌckƽƭc1sckcƔcޭkcscޭkޭkkkﵔksƔƔΔ֔kkޭƵkkkkkkΌkޜεΔckkk経kֵkR{νsss֜sssssssֽssssss֜֜s֜sss֜s֜|ֽsssֽスֽ֜sֽsss֜ュ֭111ƭƜ眭s֭罭s֜ƭs֭ΔkkkkckƔkckk絵Όεckckc,AH*\ȰÇ#JHŋ3jȱǏ CIɓ(9Xɲ˗0cʜI͛8sɳϟ@ JMF*]ʴӧPJ)իXjʵףKٳ]]˶۷mKݻ@˷߸aY LÈ+^̸ǐ#KL˘3k̹s᪁WzMӨS^:5h-[˞M۸s?~ N6oqy 9S_m;iկ+i' I[<_X]aiF~P]~ TC4 `6IX\` 8Y`%q`;4 i6Z? cpa5ͭhUVGNX|OƃyؙYݒyFIXe Pk-5$f:$ChtUϕh)h.)a~|)dH%ejbXivf ݠ:yd*'yRc(aI<ϤgCJ!:`'Z"J=; Y'(ʋڰi-W ߀Gݲ sK 7PyM&rT8݁Ecr8@ ˈI6hXIC)ܲps4#%A( 4/ 8p#&yk:;.dhg[*=&#_Mw2os#^zd$^lzY;$Oy;`޽5tĿZ#V>y5̧eN]˃=pcor3@lg߫dI(F2$A*3"j}~ {3ߟN Jv% Bfr=OJ<`R@pfbW}W`YgfTmO^ipbvv(*y1 NVAq\V;{V'=j` Tn0 ZSa$'@lb_aAiQfG-1KX\R'SFD>|yt(,&>@@Έ;XQPLUTH'Zq+)%u-1J%F_W- Cbk(A)elWtH@9*f14 ԣՋqfYCnC>ɾM( fxs2k)GJگ=+xrfhFE#.,Ck:?1L|Be\ qK80bҟ`2r zII JHfUiJ-̈iPģ lNX+|LiS XL6A p jSG0U`*P1uDL,bOFǢ"W+[v@!6 Asr̬gԪ]xdytf{jJ!k$LΖN4G.bqﯣ--}uBiu(s{\Q{8>7kXquI]*;xZbaխt[5/uZQ,p+s7~8*qD+V(!~oɷ8u b| sisgN;E/6Ϲws@H/Kѓ;*KԧNDXϺI{}Whenܕf;׽S.>'?3K3PL?Kd? $LyF'Qd>(g=.?"A LT{Г>'g Qd߉{]. `L~:M՗^,п d'{)dw<,A~.A~w  zyy -{'{ h,zw|Hz~+yw{) z2yG{ȁszz ,{̠{gyշ'zh-aׄ0y ~L{ɠ{ް{Gcb7yˀ,It؆, O}" NPhy{yzhz , n(Cs83Hvw ٷVS~/A|e(8̀ "hy}^h `y'|އ}w|gėRx|G8 WzH|(,sEyg)yЍ((0ьGzz7`  g'(zׁ8hh=̐ٷ&HɠHz&(,| @ (hy1yhXI ȍG3'{̀z `|{Q' -Hb{grhK0 q{u ؓ jaidY `-ህx|Y(|Ti}6̧7}p)9zh|G;,ᙲgh"x{P (זyٖ#ny',ni鍯7) Yw;gy} x홞Zx* `h'O:H'zAg : =pڡ ":$Z&z(*,ڢ.0sZB6o':ڣ~>yǣBZ;cFxJڤWNPGRZ\VEZڥyA^MbZ7Af>jڦ>npm:tvzez|ڧ]:UZ8W 0 @ *.q0a P /qEשpj*8I01 0Ɗ4 ȚƊ-1+ OSk,w ;] Ң<={ʴ'A C].zK\=0p{3ax,sk 2{ }K Ǒi<Ʀݧ>ْ]6z٘Mٞ͠:ڤM}ڪ͟ڰ=۠Y۶푸ۛۼ۳7zA{ѩp;м*܈.Njo# `kN_A>҃O*:+Iq̈>[?<}lN ĸ*ܴ,b?Ξb˜yZ܀<s|B9][0p{ok]ˁo>@@ DPB >Q!$^ĘQF=~RH%VhRJ-]SfI3męSN.kTPEiV4TRMwtUTUB9@J!XOtlZw|<ŖVx+X* P %E~ t+0w;>b] ~ X5i`qdHrA ix'Xk?B:+9輱 *or K}Z-\1Wk-;Rō+ݕ,[|?[, Oӈ@37ӫ+LP. B9лlBQj۰pF?ܛ b~HnѢg(jm-"+c,W66fKhjW`3Ϻ N (d#30DؚP#H9G5\TP= "&H!EoC砓NGXő o;@ KcTz$>W+[kNM;ȓ 2+:eEXA26Pa[tDIbyҮx4J4ZT*n>E;/\sVuղ6Xoms/M|Ta,XX:TXg r7t2;E-\}DsԔ#6Ncy,zWƷfo+c(%5Lt6z'TE=59;p)sԃAw?$p"sFGUD'JJ եH>Y: Z׀U9~:Mdf{:9;dkD6,)9"`M*I 3.],I0@<ᶺה.5sݻ,޸;"A&U(l&GEϏtq*_U@$ ﲊ@Re `%NЂJ*AvЃE8B $%Da 'xBЅ\caDk#^(3Ї1 =ܦ*I*_^C&$ q +_8'>8@ Fb<6|rVnE2wjL1Ƙߌ221⌡ j94{ %|Qu8Ltӟ\TH Ѓz&dhDQPVԘhF)QvhH]R$e"7.$"ܼ cDCe"L,4.h^,2;IPgpziˋh!^vx$<(r-H5&ēBrjP3rI5((=X*I!LbK4+|+c9&be!U(+W$Zƣ0,h1L\J1,cH[Z 0),y2POgFlTt+ =s BبVh)U55K e#aHGRV >ܻ]ϑnMlsN"+.h)U*l*Pӯ;TZa]Btz0-psةR䫣iɬf-[rILy;s%*5 US>MsktJx )Z梳hBhSے3 ^ܦz]3oW6e&ǎ'ZscV-\8,NrNHJu̙jP)8|];sx'YSx g,C9 N7 @*gZR՛RgjٓIx!?HIm,vwoy;*wo}{(wyp<ܧ ɹJʉCQDhU4]+nh(+#fk(`[=S\&r\kv3XD!]A \!5KnQ'%c,JF9gTRr5Be0Ņa[hIq'NGooD+γOg; n}2@"đ+Ip>4KY[PeSʌHu^Th1/Z޴E2䢯 P|'A?z kwzhߵp"U_g;^twr, PYj(Ud3Y"DdwL?ۑ?R~ڏ꛳*(\C#?191s'ò$k D3@3 92$Z2);ڟmB#C"X i\@i)Q?*BY /j<:KVA.K;$&|2' A=+$,j>,lB2d9’i丛CmmU$ٱћKa BlxjS[K&*v5U i5nDةNlw2 99wz5b3;I_乺Qɰ@C+ 6E'] ]E ~#5 ƣcTetƥgFipjkFQ'hˈT ٩ [c=ɩ; m9hS`I)zG%z;u|n܈ۀ2HrNSX"7A9IS2 s;$q\Қ4[yɢ2-K<ʧAJ"L6P K;&ۈJ1{z|*"aȧtH[$V*HJ3hʼn˺-K#$C;O) Kt/G=3ITɢ1Vhh0T;TTa90ؕLMd' C %{JA`:$̤ɰqˉNsIDI2$)Kd4 JMy22ܼ+\T OJNJ":!FNIĐ 3 #\3b& BP³3l24H/$ 9𰥗QĜa˒1HI3dM٘EW;AEMY<'ɰ^zJD>>~Zbҭ(g3G6@Dm~2g,%~R1TԲ$mtS j7SFze;u-9>7@A%k4CQkSRɗRRr۸Im8:ϒϑÏ) DQLS݈J˄t93ӟEX'T5\9F@:ԌM;-XrkVG J;FYA1ѩJoy;J!fcWn]6ʨí׍ծ|=$#⳽ý(;,x>{cCʋ=H*#+⋏D"?QrmdM ̛wB\ kN0,1D$A9SY;bKZ} 5@ّU51,,M3>;Z,$ۿ U@jOW)ZC,3V U순!BPXmP,(lTZ'\M3\2/T\7PQhҢҵMCADET!]|T0S MR\S|e;6[J}]( ש'UKD$J-eR|Eb RՕaUTHbmb4_@ u]Ӿ=_շߏ_&x3>VPc ` &6FVfva. a  bN"6#Fb#&&$F%)a'b(Nb)-a0>a&03F4V5f6V@ a26c7c7c9c*;c<=dANC` C8@C 9^FGdDaEfddL.dAƀ((cST.S. W~Z~P&[b 0x*`e(cfh)Nf胊<xAfa&@8`lof @Xgcn|gN`~ph=hF~va^h@@Vii9nhV閦im.ii|v0`!a>Xhj7j1꯾;4;x kkj&ap  (aklNkj|j0hN^pj^Ϧjjj&ֆfhn>n&jHFPf`f oflnwFji$xj wm g ؂7 G"Fk $g( -'-jfqk.P`&wr&qq3'r$:pWVo]lo> oH8s g& X%@=o?ts op16p4_'pHqM`(qQ`H!OK`1pk, uOq.rVuV`uxrV 5)5'`Xvv[pvvvQP/qwMu5_Zns>>:w^A}WWzr'X}_g̞wBn}rv|:tswa&pÆmY("zW[?ng(hmH` Vp  & 5fѣI LJAN^ T\Y S-j(ҤJ2-Ӝ9ŋ!N0X"%~ V0` U[cI\"` mte) -XQX YH$CCܸC$Jn.iǐJ:6ܺP U<|p"A"zM?Z(>HmO0~#Zl?kl0ӯo>chLt~ T$ 4 68\PA9PZA;A<䤐نG8 n-I5h#=#A`F8($Bi$Ud$Nyd]zɔR%G5D&m&q) Ag)'ri'MMYIz'py'TP9:F`j)zwjjjfXFiA: +A 6* ;,{,F1;-:fz-՚{.骻..;/{/;/ <0l/+0 ;0[|1k0{1!q#|2)o+215|393=3A =4E}4I+4M;4QK=5U[}5;PK_0Z0PK"+AOEBPS/img/cw9.gifHGIF87a{!J9sJ{kֵkkcJ{kJsƵJkƔތ罽Μέ1c1cνs1c経1ƜcsֽscƜέέkΔcckΌƽƭc1sckcƔckcscޭkޭkkޭkޭkksƔΔ޵kޭƵkk޵kkΌΜ֥εΔcΔckέ絵経R{νss֜֜֜Zksssssssֽscssֽssssss|֜ss֜sֽ֔R{ֽΔ!!֜!!JJ91ޥRRֽֽֽ{sスssRスֽ֭11Ɯ1sƭ1ƜƜ罌s֭罭sֽƜskkkckƔkkΌεckc,H*\ȰÇ#JHŋ3jȱǏ CIɓ(5Xɲ˗0cʜI͛8sɳϟ@ JhMF*]ʴӧPJ)իXjʵףKٳ\]˶۷lKݻ?˷߸a[ LÈ+^̸ǐ#KL˘3k̹saz=MӨS^t`c˞M۸2 n{7ȁay09SWmhկ+g' aE[<_X]aiF~`]~ d5 `7I`` 8Y`)a`>4] ai &Z? ca5ͭ|QVGNXw|OƃؙYݒyFIXe Pgk+晟:$ShtY0ĕ)h)h.)ahvCY ia:i&pv`:Z}JYꏢ)?X ʆ*|ނY>*i<2+Y{Rb2x3Pg8iĮY{r܁ xy1pYڏހḏ-'F9h! ($qic!J>/3 7g3PB" 3bGp_Jhr%bރ2y-6 ?GI"m/~w;cy/ٝ 8oMoLɹށS ,O ?o `|;Խ`0 E6qD<̩ #"<<x#P\SL:%NT-2Hd)&;&pYՖշ2Q_'zK!2Ico%eI$P*[n8rSg/ǡ톬aIq, )TU s'BUDx?VG2IBJ`wH15Q* DŽ_Xz1$ץLڣ]*2\JsK:ũ`Cf&'*(x0QPOG ?!xEiJ0*0%6a# $!b0ΆbըI+=(+[O['M^ )s +55G=Q?agCU LOel*elkDXB3kgd<0>&a9؃\P`mA[vPkYJ?; .XdHA/ ҃"ہt(AuLEm'[\9}Y !c"W4uL a4\[ ;QQl [nL)IGLbP(NWI,g\8αol0%dxXl\NLJ!6۬nBʋ1Q`IqOo%O⅂;8i<'OyH|Q pK`+yٻ m,}T|XI9Dznt'hAe|3?&}M ?ާ/$:AYg^/JB˿'c&G})p6~gE5_Lယw|}!wz(!|/ z G~ǂ+ag${ׁyG{ygyw~2{w}烞 `hɇ0H{h.DžI:} h G OzMexG!`lnx}/H!p](8Y('Dt7]{|y@l8}&zy(zgy- ؅,}}VHX}؂ s%" -pg~WH}XWzǘWX ȨȋߗX8w؋3HgƸW`荔(z9tHG~5Appdž'腀U}/zXI ר|~(7 $y}Phih+a- 1{VɕȓE!+sTwzɇ4x: hp5hzw(z. %x)$gf ɘ`~ )2y_ɖ9yZ钎T ~]8ٚa]XViwG=p70hyY)yigɗ`阐]}XYͨ}l؝9)Gx혖9i9Da驐8Ĺal(9!k-|$z9+QzWF|zDi`9{0h3ړע%ɣ>zxۀ١),Dډ'|5:*{ zTڠIi:x(gwz}ޠ1^8`wVh|ٔCX*`W l|Ǜxz:jf2((pJ9vɉ79ڛا+*gק݉H ٪?wy/w@w<:zF'z/ﺮ:Zxzzvvu;u{ t ;.+0[{۱ ";$[&{(*,s[װ2[}A6v:۳o>hB[cAFiQJ۴;˴N? R[CKVGZ۵KK^_b[;Af6j۶GǵnCr+t[n{xzf۷~+^;HW  6! `~5ḅ =AZ1 |;K@   ۺ A z8 RPk64QL+!+=A4Cap69[5! ﻽拾/Qpz1 |˼6,|=3Bk:A9!30 ;%0z ` 6P; l P+{` D\QܾQ8l ,!R4,ʀĔĪh̹;_C |Ţ{Ŀ R]tM++¤  (hNȌóUkK,?Lɝ<a f ɒ,sLL  K@lʔ\/ܾ[=`Ȓ,ĖT+ļɒ P%\W  ݜ P<'܌͒ ήK͹Ǧΐ] Py@,| [ k |Ìܿ+ -'\қ  ϱ,ɋ:`ӝP-J0\3‹L޼+ Bܾxɛב@|֓m:ڲډ}sak_s-_=mNX{ږ Z]-Q ڝ׭]ޔŭ Mbm܌H=ԬmMȵCm== j / }LlݣȠ p Pf}~2++]+j l[ - PBD[} mܛ@i-L d]؍kL@`}禽Ok2nlm ] 蕮Lq=޺ i 9ߋZũ-ŀ,ȳ , ,zv`LQ|qYQʨʾ>.n{ UL.ż;ZL쨞먾~v9R\F>>YN.@, 9^lY3!M1X"I` %?tLQ 0o[R~\F=ON Q[FߴHI=:׋>Q=aIEFq;^o;Da1/A]~<\KCKao?˫8+2R^DO;5qA74@lŔ<-\̨n_ǚ,]< 5@,d,˃\g;qƻ:<_ȇ; Ʃ,nN KoƠ Ž姍ꢜQ K 4IGtpIJ(Z<: \P!GuK ЪARҩB :z`F= $UtDXRHHF4 U!:JziԩW6O! 4S)SC#UIR`ET]pkdU`BJ,/LKsT\(.e5ZE椄+-z4d[u]`UXVcV[έ-"nUtܹ} U{mi]gr АbNzxb7iHW$jt:&fEȿzI|h>;в,@)H'IJhO:ѐ>BQ°J mp K$1 (?ARqƦZ%ď74h#w|0.\NvlJ MNJx#ЬSITH (llSq, Fo+7QLt2> C Qec1HTDs 5P -q,R=2Տ,5MwͲ͌ެEOSf+P 8pMDzo4SUKWSMy ~>ە27XHìy\3U(N.^G|=dY6hFYf?o!u㥪[w5[1PHڨ*X#f虩/L>)jJa~m]nY#" VAGj @ OiGO8Z;FA2]`r ܑ]N˵^t;6Ѝ`u.qdϥ&ntz^2a}|g}}秿~Xz@PD`w?6lY'ARЁ P Av0i`E8BЄ'T QBЅ/@CІ7U8ܰ/[ !Y6M D~()6W)~/#w$'S=1*a^>4!,c ۈ9$7>hR)ui@9Ep>y#AE&p 6N6tIk 61iC"2Q& .@HbI$7j'+RA$.|x$fP q$8Jrɛi5jPpR%ͼ3KBd"2 #FlЛс%CdeJ r-?2t[+鷉&$7YTP}R#/5qbQvE4'5HIбSXk cxȎ/o J"SHjL;s- QE*4ʐM r4MV6Ɠ/1O.erf;F3,&iwӳ4V *"TJDzQ X=!EBYĄ#Id 8YRjgWRbLd2S[(VLQ0[y22z3-lʢ 䕎8eF+k%#j|2-Ϛ,X)>1 Y>$:׵iuZUֿւpUZP,2WZg^Y©wUYg /[J9bEy@ӺTcb\dakz mCPR\K"YYrv#6WkifY٫5RXBڎa(&#WlwΑ90Ov{$yxŘA%|3W` t]{[yۄeq}ފp<|xGzJN{E\[=\8^{hM'!p'wno&S{& ,!•"f9 SkH7Ocf)ny}(JyT#"$.W%C\l?P7T}2^b(͈'G'[[~ %pS$@;clB Q{ >A$ O ڠ*+br*¯r)I 3 !-4¡ @aãh PKk" + 2AH(%)2)0ZChC5t Ž(L@ꌏJDX+B;;+ 0l 1ä-Ú꽲X,- T!ѮɊ?:[09(.>:}1,Z,i `TEۛD+YF䰸NaE2qGZGc1l0Yc-[k¯rЩ) S2G9 J)t1R3ndHӑ:! 7˭3aH{+T!:}qc2I #+k y8b*243:b J(h䯐!Ky4IK-A3,#[2%CsK"IT4|Y0E͠J2S!4C4N >PAL=Q4A2\ON\뼝D(geEjDٹknluqVi%sEmtev=uux=WszUz|S|~uR~׀Q؂]Q5؄%QU؆Pu؈ P؊;،:؎:ؐ!ْ!5ٔm!Uٖ5!iٙٙuٛ] xi7p0#9EZٌٞZ%90ڤYڃhڧZ=Zi0U8YV Ь)a[#B&kkʫZY%` x Rډ+)HC0 G `[x! sы2~B$p_}Ѿ%ܠ\\e]l$Fp wNH" A ^WMU^0b^ IS۬u`ڤ^Y uQE5\t^^K՛N%F8Fѕ-9Pݘ]^\ q~]0ݱQˍH >X ~i95õ =-\}Ԭ^\0 ƒa_؝M& h^p[h:7lb)a97a<& <>~@. ><&B~CF;EvdQGH佥JKdMNPNQ&5STVeVW劕YJ;B[Fa;kR=:fmq >?QbF>z$|ܻ0Zmf!q&E_gգQ oAn6pEgFJPB$mw$%#h%JfS S8?&i߄<?D!S+u<4&jz#  S4A1ch9 >ԫRò(@]+ƒ̐ľ20hSt" 5CXId8ÿ;C 0LZbȚ+2.A)9L Xl-T`B D;UVT^qEV.o$!H`Ea,U..:j-a4bbZ]F5/  $˹VԸ5 Zomx>P=Ҟ+aKcqHIڙS n$.toїO=6M!O/cDݭi] MyOfF:ATԝ/o2ʄ)k=!*JL$oдb0oUY%*yLZJճxL*C;K52s 'aCs|s@)s2Z--:K+ '=JGČk@b$4`ر$MaMf VuܚIa8OTÙ(NT$6랊vyU>#eia^i\iU弤L%epAlQl ~t+bmN{$mލ?DzCyZFɂʺFYwYeI_T0 j/ŢB Gr!}.KMc{/7TD[E0Y2LBB?'}YSgv`vxCaWd;iu?Lu^[\wޏ!VWV/0W׌wt'ok,h „ 2l@@h"ƌ7r#Ȑ"GT8bɔ*Wl%̘1Oʬi&Μ:wޤ'РBu(ҤJ2z)ԨRR*֬Z+ذbAzk,ڴ˪-ܸrҭk.޼z۶3' ٬0È[]|Q㰐#lLZ3k&K3FΠѲi%M$5Q5&Z 0#$J)@ٴ Xvn۸<"1;l ׮<9ίG?Isé=KL9yL]ǹᑇXkR$ҬrmW~8lhۄ(r-]W!s XHwjAr\ jIz7!l8|UB]@J4=8"A>7m7А$Gr?GB@X7f/z#G3  i_~<>Pz8P:e(6b_>gpV'g#x>ڦ(~&jG.ig))6KoHdctFHnբ8rjo&G$pʯ[+cvR['7'=D<${%|9fkmmผzQyӽ`IYR犰 | Fa!.01m(%v;鈂ɤUJrZr234wZi䦕 q+*Q$0}N4&Ծ[ .=)-Y(xM7dY]g2kC fQ}eUtF޸tBdDQ4~TuLքddm 6y݃~HƜ^sةz'Hn$)^A.I*UJRJqJk>䌐_^w5|ǶGqp?Pyz>Hp)R|*6ё' Qo:r鼊XZd$,Hc‘$I '¦k khC)LMw  %2p)R)F"8h^(1d<#I4YF8ʱ_E<걏BYD) w$!GD*d##9H3J6%3Ljb)VB,$RJl9 Q%BX!ɛJ uB aIF3-uN3ҼU9`2;:a 1umg͙qp#>pZ6 7ܖ_>o:S4V㥢B]mk ræl)(]Wv =JHoz#A a[ °z` ,Hȡ ~;&McO}b{{=O3l^W/ӣ6mR]mڱ@Mg >":? %ܾj֑oM9A<rS5:@W)r¼ 2U7ѦDY[x9EqJ+NF>s=Q51Ns2p8a^H1~\wQ;=)\T%E9|@6'8yOr>+<Г~).!JY-lζ!T깣>'A𜄳"W ͬf揩@s{}aMl'a2φ _gϔY?RMՙğ ?O=5^NZULMUY=|3G%qUT=U1(Ue=` 4hI]#82la|2`oS9Tŝ#* U^T\hTLXKF~LZو 3HDPYalaUHl2\ NUR9aWgN XXg \]M ar*J,v->}(V*FuNdfBVj"d-*][ِOBٷ1ؒX $I^#*sqVa+ i+a[Y%[+N$դH1N[k߽z=LM`0AsA&Ii:ҁ݆әgŅ{gyhzρ .i,1ԲǮbDfCv-׆-c8ؖ횐٦m࠭ڶUmGpN---b+."&)6>.䒞N.m\&&\BXn!(B,\!nq!+ĀA(`n'i@n B|AR^ޡ2D֎^(n0C  %Σ"DinĢ.q؎&n C1 C0!`wHĥ^DӡoDmF@,Ю0 @A_|{TZsJ\p=aUa R]R٠.g FvnC0@/;`הxxW$0R-0R-F"+ tֵ0cĀ//@lBrYGN(Xͥe#نqjϞkq;d.@(xooH♅Pf\JK9ק!+E[Y%,%.&d2A(MfmRr\cBJ[$1or~ ۹mh~©"!!lވ h%ݭ:GyJ33uhh).j.zL_F径E_tddtK)GG"4II JKEv't!.B,B M® ޮOtLE+ 51ִnHDmT0O4.+EXSӮ{&1]H|DZou9&Qz/ύ9nDV_ﭟJSujA\IALp Ԭj]k0'DN-."e={}"yM+j]jeqk"$ZW-mp 6WWD !!$; kqɘ [P7+GjƨEO^%asrrGΣвr*Y+7lVeF7_\fYVuuHo&o3BrTZlƒ۷-bM[t^݋3>רYw m]>ZLOTFNKĚuHSy#59y:/:*kG"5:K_ejK-ZU::Ǻ:׺:纮::7ܰg@,;7?{0O;W7{d@+;w[;k;s{7_;g;zg;仾;;;<<#'<7 ̼ AkDg :WB~B{~@+ρ>g?˯' @ { }kh2׿߿&}/>@8珗+s\88?O4# 0fx@< 49G!90т90'(È)Z9hQG&Uz2@SO4* T?LjQ0 (>~l)"t Џ'i43 [rcϠOXd"mirgd\SC5}Fclm۷q 5TOEDrPxF!B` tϣ[}zu8VQbeqN X4d'Ojj_GAN;I\89o)ZC( #2E> ьcN*I$O@ ?Ӑ܀ RHvʷ` `&R++X ,2ȫj%!D#=F(@##CRNKCHO0PQ#4R ,PhP5a E3j S|xE&P 5U\M " 8 ?BO2Ҕ!MV":R#B Z舐rXrE.ER3ᖴR3LӀ,(#Ȃ$ 'B{(7_=v\3 (}_/PVb`HuPIX3n0muPY Db}8ހa("iSocBA8!SÂf iL`mHx]mZ݌c-` !M Bb .:$F~`0h3#TzwX!b VYW \ߗbo#bFەRZ*!y33C2Z;9lM[ BjnITbvmE ] )ȇ[obgXěS*"ʮ68msP :W;܍#ѝor1 K\A@޳&$6W/Qm02H> fA $$ CB¼VEN KR>7 HO_ hNwؑ :Q{t,I<%PAW] fi蝶fvgdhn 4IOɵwAOZ&fbC 9X|iX*(~L2&&_N@{qjg9&hr)c?0_{9 ] )#yzXxߩMʗ#XbɜX#shB"eFwÍqqͷߏMW,(4<$Lw_G"7 .} آ*Pv2,D1(wJq\0|\"I/#Cn| %̀]*yr}v*,GٔOȝcsg] [\9܈a%K}{Q@ !yGrMmtH]gsp87ܨǼ ĝa6q3v~9l& 5(z7Rs:cZ~wGFل#qE-0 b喝_xG>C;llӓ$$@ #!8q޼d :QĖ5=/]ڎd=+EAbG@H "3~wZ3D%ˉ/E:~, ~еs/>`̺Dib$=Y(ыeq4%&y|RTŊeS;I,;jFfut, !+sC@iQ] )YIr_uĄu(WJSEr=鲜uB_yE4R?|30*"PL`AH7Ϡ NyԈuNR@KI*TO{ g~+ O[њS.`BLu#]` Cs&ԑt9ݎ OyU7ALILZzޜŤ K7eN?ET s˩ͬG< LbTO il0Y7d"/s .,6:3oCRc }.oqhB9D#ʝ6!HTj='> /,OgC]_E5Nc~ijR0|ك k/ֵ͛ I5FȆQnq,45f^7GO kXS١rVoyDy.9#t]B.nu{nۛ>8(d_1#p*773^qfEm7ċW%.gNȥ8Ϲwn@z}.k!:җSENԧSX:L{=\hen\;wT}G|+Qz ׀,y}|g77"P0(W{ zh{|}g G "H{;x.ႨP7| J{'z3z6y8y? %7@ւ0 wy'}0 7OW}vh `_{W+|ylh{Ч/+}{ {W}7PXyX ~ȉz+~X5z"@gɗsx:py'/ 8˨~з w ؋x'zWy,x ؉؍(␏GȊ .!GwY؏YqU{灱Hx9"yc(0ɒzp7ؒHg-ѓӨ.a/\80}{CiEOJ r xy yLɅQy+ j $yxNx3Hykix]IGc9eɀoɅZ)Wx^YII?i p}"P|{nhnjr {{Χ YzIُ8(^-q8xwzҗ~؜ŨXI өx,]hȩܙ޹)ɑz|W|=8cHכ0wbʅXyZj㰛@z,.W'|1XXyЃ8):{$8yPj{'"0y6:8z * sH+ jj ;091BJ˴-10K ;; 盾I2X[ +! 0QQ[eěkŶPQ|S K <{> Zh2i,³ 7@ƬZz`[CZ|X,t}qŇCœ]\;+k M  ػɡLʘpȨp|Lj,vwKȗɬs<}\a<|DmK̞%Q۷|J0;);%ͭ Nlfl{ˀ s霴Gņ Q ˘)k·;Ǔ} {,Π +qY KJ̞k-Lv ԜGńP~}Tjҕwk}ȼOMM}-kUm-ѳ^@0Ѷڗ}lF Ѡ,f=Ly] Û֘D@M"ݺqE}SЖ0e}5;z-}8љyQA7mǯ Qmr-w һʤ]Ɩ;@֠_-W=p@yξ)܄;О ŻA9<ۄK֧J dLI]ym,I+<߃9]ħ-¡ .rA !볿K\!|B N ;`;Y$' ۽+1޽D^ >;[' +LX><> > E>;'x9;N 2Z^j\p^- Ek{V@ = XDl7NYIGlAu'>~U騎꠾ڦ>|;AC;ݲN-|5Aoj{}g+W{7[+}Ta9߫›&kA}~=ѫ0%Pɮ,Ƴ@㣽eg1-/>[ K @UB ?)LI5D)C L GJ#~Q`@BE0*!) o"O>?Icƈ$TTU^ŚUV]~vk„b͞EVZmݾW\dśW^}n`… FX?Yd)_ƜYf9ZdIFZ5aϫ]kkٵmvMn޽/\pGq͝?tͥWǞuݽ]ɟG?|zw_^w[l&M l$dO?)[<!0 ˑ\nZf@M 0(*0ԐC$2kZh#jIh&"ꑬv '2: e J"k!2*I~PR("(E44q X::d]"dj|'+s(ԠPzzR,4"Jtю&QM$B 1 Q*'F;zT(L5 P,1DODĮ6%E<ГO6*P0u6UM-"uE@- Uʴ'V~vSrjz] Dh4j˭Jq(D a_ A$`S<3O=fhUZ0h h%]s@2\@1c9I4r!zc57P6hEY1a*]M @}8GTRiu$??&ڣqhEVżYضYʯ5PB􉧤`Ziј֪c툀>lyW8R%~*psU(Airה \_{n)g.9|*H_NU%tnk\J#t=Jwjfm Ay浯^moWW4µړvDƟf޶Z Qi+g(JWH SNkTjHrI7\0~^ 9JRD&rRTT !)f$IZIGe1ތ#@#JD!$ɊkJHff~[<B ș3jGJqQX=1Duc BA=4d"}HE66td$aɪ?d&)Cɩ (F`IR:B&h0鯔,) b"U6 Y-bvm[!0H1XMT9%2y ̍x\Cx ,#,k#iv11=*2\Z()T7{B"U(Qե2%{WPR)nhCX1 -!'7l ?<,cW%|k\K'1.tK!cA"vјY3=~e=g*( gYR}־Eh֋OjS4Tx 0^dje 72ʭ a]?ѽVE׼'| j8 z^ #*ԶݕzFҙt`::$kcSqsQfMq#zw|)E^u}m'[.WU$( JҎ8A=t](c.2yY#PS2$hĞ(8)V,6,bIk`~b5:ƍČtAlF玛bx3ܴqcx94qc!,D6rd%7>Lvrd)W9Tr&oIf1eќc5mv&"E]qа,[d[p3[:uh+yYh+W hMwҁq (UqP)z%K՞9a\{6˭"lZ*<˪}lbBIv }d3Tms;*4˶ -#A]t %^ֲv6,U>ywgRx+00Wa*IS,qy9$e! $p* ȭAU($!RqG"$E2ިWeE<Ws )p GRIx<6<}a3f8FxO";c~ OH\;2F\ Gbz;L̚Q, g!; QzC2Nb& xgB L'~WU5ЗB"4!xNZ<膪FY?am9^( b?)+ L*{ $?q6 +Q@ 4)KH> ,. AܬC!$,C~Y@@y 7} Lo1*"BLDycrMBA( ha0Tr6!c,.L>iJC%@C0 CCI!+y&:D jB#-8"$E!fDD=~9Nĉfp[/YlPaS AqqQV\E{NiCChUcTVFDQܗdÊ7&؁Cjg ^LDFqqff (5 jN!1AGyF g c P+i(8 L"'ȉ;9XCC\$P܈ x"` ɡȑI$ !ɕ8A<URI!ɉ\JI :JpJp'j0#Ih Kc$tʫ6(36S1<3YK9#̅2Ä%4[Hƌ7 sL6ǯLP6^5lu O܊~ @+ͿH7s[EԬ?BZțㄋ[#:û$Τ{N{;<: H:SMG;?̣>C[nsS㼥Kz5<OK'CPP)7qR!={Л"|2@B= $T)5/t:5!2&=Лs.#y9PPLB.D=UQ,V1CQ9CVdQ; QuQo :U@,лEiG"˪\EG}πE5mEo\F4]E+Ak y1"$E2ExS' sʋȏHKDJԚ䈰H; d R |IȪtzԷH^M_Ba b5>BdeerghVjkVmnVpŏq%W0stUCv1vy=z y|}E $~=$P%TZ%iV Zj0im$z3 Xx,prZͨ~{ e -Y0(q x˴ټ&)*ӗRRIK$ Z6(ՑHӉKI;\Z_XR+r+u2)YI%೽\ByዽH5|۵x,Xɢ, ̢Y-}K7z`]"݀qٸ ۺɭ5+%o7ɵ^ L .ם2 Bbė5˧2-j EGxCZ+E^P-%)%!hʏ8J5դȸ U͹\I ];@`.x1XAmP  N |V&f5VieaFM9X&;ᐇ&A[X@"2й .AuE5 8Y>=iYс0Uٱ -*[Jr>KI85ݚ_8^2n;fz{"Qݚ;408K.C z;&{,@ZY4ˈ u\S] F:ٕ [/la&+CJ*޹-%r WxLfA}cxkEn>eDn .A]Rmw>3]k&!FaĸURgaE߀%8 e[ U՘TB8櫈a0`@ڪMb׶i(Ffq꧞ᨖj:&0VkH붖kȐ6&6FVfvdžȖkklրFF&6ml v>^̦mnmlFVߖl1&nV2Vfvf@.nn.̶&l&0 xG.lHfo&N WpFoXրP N_@Ǝp&_n F0 7k :qWl_ qrnr6DP!E@CB րC(K+r) :?¾,g./ 1'2s.rXP9N"8sl? rC(8 6Bs+r81@5rp􎠃Ȋ8IrDt0 GtPgsF(p0us&AO^GBOH胤||gρ(p|?: z?6`X?~7H#x?{"3{]'7n 8lrRl2eZ7o G 06e/[ "TxQ"p$ &Oڙy{ѧO諰V`L:i'! <\%iƀ /  6w!Ę# `haAfѪL-2n3.+ thJN%uT9q·*'755׏i^(cx61ַB,B4)@ 18r3(8;8#H[~9vh} +PBA݁$B$P>*c>4hl׹n|;#<+{t0=[=x/:n!E=o߽| 8P??@ L< @ TR>P >qpkPG&X`kWiIz69O7 kOΠêvTsև/n*phVRsӕfƣw, ۂ-K'*y:Y3勂Wm0{tWJOW΢2ὠY  X)˚W ^ Ɯ90?DQwWd Dk)@*Ёup g>UUi"c5Geio V8^%2A-fx'F}z E,:ҖHtKG4ԥZ[$ QĩPSt'\ZUuZϡHF' l=B YSNu:Id3 b ƒE*ZE7`Jb!teY!Qƚ }RY[d1orLLKS:Mdʗ%IU u2Yn)gAf~e`PB QY0[ܦgte"VF7,) rkꅵQZ彲| d/yK[ :0B LNX̼AotMye"] ۩Gj")(NkWD.&舙ƒ 8αwhq%!ksKd#GNF"d6928TWB,u)_f!2#n~ۙxG,u*ȡ"^ت:o$59ΫA.Ԩ)ީ@_UU[,*Ywd-!7JlEDWVհgcNyRB-Oi 30Hq3J ;1eԇ6?${Mrӝm4Tt^+Kc+Y.,!+(CQPP4Rk{ۊ.HhM/ lqfxW)F_b- 3`ϊނlf%Ew ( 8ě*qFTDOKĩK,!s6ɏ򁬜:doy `==.F ùmF\3OotD(S7J{y;0]ur`~끨^g 1]l^h'ڵv'5u?zAx5GJ'1ͮ| K4QN5Jv =9w1R+"i{Quyj:L8=R.F9ӾT̗2ySW~GH=E!7UYUrFz{!GkqVYb|B~q|aE({ nB1wv}DhywiC cykR'Ԃ;'wt"H|&gevw>WC@7..dSv`RiՃ|7wD)h+v-hwCʶL[i7j" >(z4vdX—H{Cq3^+e[R*8|Ra8XxXqv{< iAd瀠v~XbhnxȨ ֌`<芆vaE҈/`),sxr⋒!&- hX|Y(K$SP*䈟ѭ^Wi"MrqBS1`=!3 ! 8ux,kdw}o'6-Zx+ÙŚɊ[ ׏M +xoJ3rU:<ⱽDQN#p|-rC")̘;C&!# ѳԩv+,B"/|kJ*Io}ТKo ;XG >3,"ҍR02G8g;є)GຩJ=d0TTz|4~˳<Bm*FY`ZȬCTz4S;U W (dw"-:6,t0Qiq6"RP!!P[z} :w 2VvMV'DzO0m* uq҉-r M!\t̛u;Yzs2SH3CA<+CAZs>7AV1PLA@&bBlw3n(qsh7ǰx}j-zâѳ2ϿDm,[&wL$o3B*"0u,[' պ̺aU,o~rpWԻgzwF}m{#Z6Q5:@SS:CtsV)AKa' N; mwCk1==-º2MVmona4x͖@E{sW-] ߂LR7Q8Fֈ}' sy+RlmHH-Gf9sz sqb?C27'y+)hb`]]K.xLxew謼i)j+⢓@ou+#Ps,xSx'γݡ)kQFRAgnWJp=B.`gQn{ 2-aq2Y-b3GR:;XHrǹ1`Y< "]4hY3NQ?)[?;òq;UƋޘPTvb1yʍH& P-};Uގ*6]7B/8J` 틵d=EѥlKݶ-vGzbc,'n \XШ`9'|%9PGʫNԾف}}VkHtCi#v}wip9_JYפ W!dC  /A?'nd? W$)!*4D 5:PM7O/^%Jt眢Is0Ў";a*McJ I@ bT B LO t#HDٗ!K1ʄG,~=J9g3r-KJEcTgϣ/恝~-{:aΟ z "n#6G&, 7* 13(J 9v29*Ƞ9:˾oƆ`q53`lȍ{**? ťPʏ+PAc6ok !򧭟8+(PQWOJ;T'B: ?( D :5%$Ӧ *耐28* AHVj*?* KK:WL4뺪9gNPWE; GNΛ RO<%=eRfn@Q )0#aAf֏sYe]#_ӕ[ Ҹ@t"UqkDLM_YrG9M*[ @@3#x+")ӪJ TAɢU"?V}]}A) ޼E:hϏ:8\BYֻ7s@2(D_w8'BqO8Oc jͻO&aThBN>=! z%>`}_@w(W @U+_!;|z_T9FT;Iݺ7-et8 #@@r\J*R=.` Q[qs $I' &q{]Ĩ' PRmt#Oy ?E8DądVCv:' eמ$C$LqۥD#YL:Ԗ>Es 4KKJ}t+f2sXsQa]F<x~ A^I=X!fEd*o3xmUHW$9G+](dRt* Zy 8P"CI )FZjx/(B3uq•L D>k6E Y ^qkʤE5;۬z9Ϟ$O2 fڨ]'ɠ*F=(ԥ"u+exȮ@(` RpۉIr׬"@ʤVrB@Eki&rR|ɜ*&."ߺ]R'3DKR,qeWtz؂$|c0*jxA [ћJAP6ӰWEh%aЮ֤$,$Yv٩rx"fRa:_|7Y 1@ 1~Rzo9!,K#SO]MIxah$6eD  k|exA ^(2e$}p'ce;F[~v#do^˴r1g;GNy mPZ%t }7DOFWfe4Q ^pdztIlVZ4>C Q3:9:-S 22ceiK2Ӟ4i:Mm 64bFPDYQr|邇0MQZT"REOD{ewAܭ3 S <_bMcoۀ+:"8f>iDdHYϊ4B,qI?^Î'~ >8tR25Un1D=8W}6 ix{꡺Y]/Y6%u %i~B̉<3ǸaBe+@UhZx\ ~3ٯU0R%M9@)Km y.o'3lFz:4x(̋ 0J-3`yHc v9w<4z{rF$Gh>bl-پ<|łȥ@ʼnt˹dSGFP0:V4k|܂! v:!B A^22 J S90:A3b FP P P P P$P}4P[IЗp.kЯ?4 QQQQQQ$H+.#AКIШHROQ'}R(ER*R+E@,R.R6R0 *HN;+!ʴz$ u1%M%&B`;SS?S@ TATAB 1 34;< (.AB:E*TEdQڄP4(DhTTuDqMUԞe0•>* \]!0CHS+ ``X}@D h%G=8Z'fq@y/! u1$UC`ϒPlE(V 0 {W֛V}A^)o$͌8$d5(VGimSUh lXZ! ]z>5B׏`NF5pVٖU%Y=SJJuEA QbvmQnyQ*UN]Z]C jE[4AYUٖp&-1޺ښAUwD(]ΐ[[#|(}UQ5RN6-d7MCMN\[S[(Շ |[2\^XHj[Hص3UΠ eNvkZH\ѵ]]02UNee] FF2$A=ح^30 _E] }  h 8\_$, E5 ^6V}T2W `|4 >a]^HaEeaʣ@ `88HѰa}a\.;˜b*]b-bL-./(]c2b@(\;Qbx`& 'bTO:c;cN45f6~7V(`ˈ]hdG~dHdIdJdKdLdMdNdOdPKր6A AnCV8F(eYeZe[.wLTF .d8[.fc>fdN@R_@^Ve`vU_a>bVflfmf 'S T~ԝfh``u^gvngw~gxgygzg{g|g}g~ggJqfqh.grFj댴BѵжW5p.2M0gj bCG5j < b hhvƲVhVj2C!v5J/֘Si`&䗶ߙV -HS23j&j 'N]辀ꨞv2U@ ^hڐ Ėk -߽>ź]ȵ@i $[݋- ^nl>}lʵaP=6tkl81LNH1Fa.Vmfm-|7˰V2?i^NIAEmf:׎]Y nf~6 6E1Vn.˲>fBW % V jnn8@f5a(FP[P5 xD-]_ RJWqXD([́ _"4 oX#ɀi 0 ?p/@75/88[fCЋis57y󦌵Ȓli `2oqFs=_ԂxmssO/mh-H"JK%Mt\t\stJ9i,'/KLtE%́s6g% [BTis- 0up0u[Z,I mcdW&m8]6WubP8mvoGOOga@t`w 9x_4yWaJNbȁw-xEC sOP_RVSGjxUgFrq( #GόƛO|WNP_2y8t+y6xv??Gn_nx_uۋ7Vx7eu\ {V?x? 9x&0vXxoλb®]| I}wNwyweHsW y]6O+_ȁ}.%za-w}pD,.7ۏϭ}ny}On̿u0` hÄ 'Rh"F$ FT؁% ,$ʔ*Wl<^ҬiB&('РB-jThGY&U)ԨR_67I `̮SU'Ofײm U ΪW庭k(ݻBW(ٿC &VaO -&_ U8GbHsʼQE?.|~Iko2H{5R*cpu$@LTv6'%BY8zsnG*W-|QF=j VoqcDN cudH!Z=qԡ~eevI݂l-z$M_g$tO}N[9$8g16"Os @aJ H v6P"Q\z'z&gw(Ƹ;C0?)H1Y@g zPtv0Nu@?qZ 5PC";PCVРnğHg7Z$x J9<`? ,}lB%>+-+ؠ`ٙ$ (<BgPZYk"9n%iS&E2O2DD_R4iRPfJ(CúQ%D'J^TBS^ҐDYF-iJߘs/O&iKV((./LP3%<0#[,gGQ#=\Wn&Ĥ%=tSeeSQIJR G}O2G*$Wkg-m?KhNW'X€'I $Vdut#U}g?Ţ?uBȡd!Yw p :D፞>e n9͑P!3A3j[` 4Mb1Euno#Xt.qkv%qj\qq\.]\B.8%o[Fzy¨x3Ǜ-ȕCVm_jk`XbǮ#DF+ uM mw.l&\OЮ:@`)j V!:vվĩRe<#.[CL*6ԗ`iiMW"mXM A3ohzrj|9ʻ[V;gn4.ulVxhٖziR΋(<C`i"%(h=:bޕbP.U2NPPͰFU6i)*ufVNf6[di*h4t˵k؀.fB7,7:ѹl|"K6\ֶ+kV=t&_cnMea2m$ȓ HCݚ #um:Ӎ0?`Q+Dv|h2ӪO b!NZΒE R#$p"jJUz5nEˈ+MseDީlra_<pK$dj@PL&8]|Uo}y_>db|d!Li*;L>{E ^u'H!r$rO!9rޤHo:IvA8j0iSFBOIV'ٺZ@*j|,o\?J8$ohfC,FIyTƝN] >MN,XTՎI̋E hIta?aـLҨiO8E`k,۫_jlDHm艇q=έN0NL %\".NjZ1QǕ}zh^ >EԠt")ۨG-..D+\aP !OH`-"ib3>#4FI(PyzT*"zLGcb249:c.0@ 8;#<ƣ<Σ%IR<#MB#NElLDO%<@DZ7ڢ A@?%]֥]%^Υ<AMd%SDHxAE ,&c6<&dFdNf]N&fffcnb">S<@\Z?BX&l& 1ϸ%Ble"O%`@A87b]ldޥ H4f>&c:hEd DDӄrg.n'fpD(fԢDξ+ElZHCD\F. sB@VDFoyLo>]4 % 6yf|EdANmՎm o ,&o??ZȁBTzo~ٮnI@mױ h ך0͗&Wf /h@?`W(b+|$@7A?@0oKḼ?\rF-o$n+ժ?X+qܶn-/"@?p.*dV"r|/Ȃ A??g%%|A7C T)+-*[GdĦ l'^Cs6D(ߪDþ@AD0qu*'lR*tD*7ؖ-me3ۮ2¬7\N+:Aw*k;緪j?$4$5T'$w)JL;( AXD!Xi &3%4\b̥L2P:``6a6`3CDdF KLr3X⦞誛J5ì&ah *%uS;A kk6lvk%@kum¨d᭺+fODds&kʶr/kDjhLN7uh nM/Z+Ppro\ ()dG@XquE:"7u7FB.veNYDstX4GjPzjE'xgҦw\MJܘzr%%Zut7u\^%ÁzL/Ey7E,Z?8zD8N8f/iņ7Th IDK_|8Kxkb/m^rfQ;D0yzPtRwSD>&]J6GEKSxE0TsPDGEd.5^rC @(-(V ͸]D7SĤ.f>gĊrcRb*iEW&E{KzWJ/@ D ;}_ 0l1253V+mM%wsÈӉw9dy;~.&B&%Igdn:%c~zxkp_};CpRB+ԁ$-rK6D`A-5L3Xkxʯr*C2KȟP^o#? DQA.? QB55#sN:3ElHK$MI1Ԏ› .CI^HVZSuq8K5U.T?+V UbZ9 D "i}Q\dk9 )KZV @^~X'Vveؑȍv}P Pbu1{˗Y6xmyak`mnb袍>b} pQ<a S]Y4eyZ1rY1[,N*#֞hqiǚIK-Rԏ$Gʎr  /ըX(ݯq;ψFmUn|mUUPE"ְUBߨa_|)'v9ƯݬkW]:o_}@@*7{;w] . :TZѼ%'(F">x5{ 9 )6˷6Bh@/v" CA,@l#M#!jfAcCB2XDx*  CU aFb ?NWbx"Q?@9t1gF`Xa|5ͅbdD!A p8 )p(IYJSGfg;Kny󝩤*yoL G1'?.TX|F1 4ȃ?~i=G!LL'JiHl+eƺn~:zM)(@+xGNd>Oh4T.2sP^ .&#Ejt'u`>vvtz{gڝyh9ԡ?)A* JOxR8E-k:zyP@yr`/pe”| GZ ] 1I`*`;BSTB)'0` [X ȧEW5u: S;t4Y052:_cƪBW9K+{qL*ɻ:m]Y0/ch,ng'F"~EBb. #!Q5c"\)Wj,=+v[gf]tK FȪ-`| PaFҲєO#$h(D)bm τ-oQ +a AA^AY)TQ! C!-H* AI #H(Z~Y& m=:@M.z1BQG r@EQ` 2 C:"+"1 `+В:".2)Z+2,R,(&g&[$b;ps"~''d/uQ|'. |jjF4"8s+,r3!ѲB @|"+,.7a=G>&.8!׾6(E(+D(_(iN+rDz!aQJ"3y0N2#1#=,yxLr+%WQOR/4D7*QtiLGLLc@IK2E^c=#C-K?9lBPɀB#qET_YYq:H1%.S,Hb9j)nq:puSu#1#Ӯ&XS'vgqu0aGZZf  1Ak:":aa :FGCAjF:af?xv9ݝ= Ӳa[@N`HvN 5,F&`X0Bq-4j]7oޛ"G>~}6Z0'7?!{ #0^C'X'  +:,b6G7ǰd+8XB00J;bZ<`n#y (]y"} }2"=X  1"~6+7D9k,$UJ-O`y= Nz6|\av>#ڃj'`}ӝXoq##toG#4(^2%3 !):l]+lLx% 0G!~'V`!b#:Y0… :|O!1ƍ;zq?$K<2ʎظ| 3̙402'H %/!Wѕ+@@uh;zA?A ;Gő A[pPt mNKmC㬽m-7]FgŝZR?Tip^]p`J n4ra#.3*.X|^qo,I!|rA4tEQgz%D葏)!($,+lWyq8^-jU`FZBi 24?zNuU240W\LMpJ[uμ1m'<!jaL`=̎Aph|M6 E4x&`!7Kms!`L.Nc^thxuwm{ߛ= *60Gu1cIT-ݧZsT>Ջ2BA./::C;nB* ^|j 9Upx4n ЂTFUcZY:Z/Ud֤H C84!qUv /D0;݅XkkM„P8˹ƂiAl??>Z}9d((`)dE !qj!8cw   o&v,?2YDi!ce0VtvP&Sd򦷌an{ۢ.#ˬS9vP"x| B(-lSd KH!>%t >OWj4fsIqSՂ=7&K>B\& ^ XoG& яd&1iHC)@"ŵ=[&?uZ;Rzx+k YoL#IHzpl?rmh;Pp<"J? l5||BM/{#˝4NЋJx_ ЈCơ Nt@  @WhNph0?:CNj#@`,2fђN\0r9 y6ǂP<9[ t 7|-!'3[D HCsazP__=#a8p/eb-x FnX0y1RtQrA80 180<P}0އ eׂHc)p2v5sS7I8'Pa//6KvppwbQW/|ׅ:CB!qpUWHPSr8 8}8  , 8 %l(4 hv4@6hOBP_3A`vp'2 2(+qHxɨ،hnf }8}а%H% }&'X#0"萏CR:0iQe >`Pˇ6&i ( a)eȆs a/`H^7 ӈ 8},Px% ؘ ☓^𓉩^{`+|A `/ bs xq`ȅ|0HWǁ !86Btq8P0}Q}&8i饘>yZBy׉٩ɝV@hsT9,^QçGxi(seG}Xg}Y'vx9,+P > PXBvW@!*#J%j#:"Rx*J|_xs",@X#Ô]}6ybVyff"7Wp~S ,0 Q iY-UB14˹onG̒js%"ΘNb 4WcO- }GnJ}aP:X-!Bvd*~Иi:kڦ,p{]R~/sq`iL nQwY[wQ~a=uq(&sgrlJp"-~\0Z4·s WIjKz~@\0NQ\u*C#qi 30}pЭhН˱IrYyY|)AڨHr^0 =2 -s k+g;O@ ?X D{ BŠqEnڟŊyS1@ ? 209;2гqœ&7\nL^ T+\6!iMаQ%P' ' ƶZ}>u}u$s /  \@?- ~9ҕ^V 0 k 8&& 0{6;  Q%Q0x;}F:1bpr};:[p`  G`lc+K  -c?).GV ;滹Q$Ys+{s2xI,sPE37WteWyW{WXGXXXl+ U, lǽ@`Q$$lƒp" jv PZ`7|9l;l[Pr$C"Z*][ 2 e8ԀĤ\vqPY`!P F$PY)d͌mЋ}*XYXȬ] klȌ0<ȃl  @5_*= @"` <Ϙ8σa$9Qp VT'''%|ėq$?9A^,KIX(-*],͌.-5[~=-ˢӈg F ӬMQ]~  8v p pa=|fmh=]$(r P|ϝ1=}r!mCTiDcay i_ؖoLJ^mӅ!\Ԉ{LK=N Յp۹۽ٰp&ǝ ]֙ݜ֕ 5 b Mg->@G=JQBZN!Zr\@^<('y۶K)!!p__چL(n۸.N=8n;>~@Tn<Rrrvm:>m屾#KE)Iɹ[u.IZ]h 'Ƌ=a9; ڄ^*-0.n㔞N^ޭ'$k+RY?1$(1p =MO$n@9k;}!nĚD)`V>ld`*F+^2~~㕮NݛAC_3 ϵjTQqIC?=3·~ Ў2ʣt~#Ԇ% QTK0pO Dل@{/}X#V !"tm@COB UEQD+gQF=~oοKLFDiѢAYf-$H%dPSN=u@(G&5j@)$2$'UV0 XeV4ډ7~l׊b?,  rv8QHE90ӉFv'ΩKQP n)8L f聋ݾm[dʕ-_ƜYōGܸ?N=tiӧQV'G$0Phxͦ5c̄W޾PW|,(+ 3 $ki"`p!FZ6$PR%`SE+!2 r *:>(x02I%CoIx=)IȬh9(@$~A-2!C?z`@)$Zf6Rb`;X $Q(=4Rh!&rK@);Ϫ&⪃vD k2gFsռfdư!I`6@))p 'I \ @2O]K6q .a\m.X?Ω?WG xH&:ߊ[Vy  8u?or!AkX93Ԁ{CmG8 C%kA!8$nvK@*BD9Pbeb*{.O t 72kq6H&g L!X^SD D#ܕSCrq'ǀsn?'63$ Nnw .Ϩm7[u÷B)Bh= dpP'[;cLH|]\F?=@>xg/&ΙA?m$@vc!L/T7PzŬ@S2Wjm5p ") !~B2D^}R"y/z~ T`3@=/XBZ1%]V ⣈s;5 K5)Ӿ  {2  Q3[B Po~!҈. ;Ń "#4$?[B'? 37)l+DBuɀȇW+~hA% c;L>;9;:<q @ ďHd&B?J.h ?qDDAŪJ?X'D$hNstP44k!q!/h/85{C_,:lX/Hd>L(Fۈl m3#ɒ4ɓ,i pGJ0GtQG(bgH/xEèŎYA LʦDJ2 B`J= Dʾx%{88LEA5xfxkS6o\Ѐ47LI J=4Gϐ,4 1Ja(!ˏ8qaLT1rǴ0 oÁ="0{\˜|܈JH&4"2T"F̐Kܱ~`B8/PM|MT?|MIMߤONQ @-1}̌ ,ef*&dBPb}&JH( дHO1"t= \ †ѳC}/1䌋dŬ B5&&-UCFڱ NQ\e;Q=%TQ l!8!ךsp L둋 ,qP`.j.RbBS.=`P€$0Et1-ыp CQ4DU]UNaS,9UQ<&|9S- HS8841HT) ?@ӌHIMM4y0O$2KBJL?XY݄[u9)BH42xPָbCLi]Vl((tHlM b,DQ,U ;UsMSP$uFwYO@(k:`-}=bc%H惸,XȢLpN9X}ˊLq#F؎ͦ37 8٬5@@YSpͼ7)"\lPY^\l>`I%E`X;N~7@"QXMLsEWtSW `ZxW% ٷSۂDAL <(@о%nXƝˠȕ܋E3yR?-[\7[ Xqغ+ ȵ`B`L&/\X]Z5rF3?B:tmg[\0^͊@Pbz\״صuۉ[`B l TlR?a߸"^]6nsa N]( 0 ߑ$E[]`m[}[QXxE_qG(፼][aٜMpGa0=a 9~5V"^VVFbVb a+ oFuO2v3 ^핣ʥdʃ+9ʬJX'E>ۥ9íI]D@Fn5VHd@ PTب:؉UVvquZ$JUteeXLШȄ(NT^?N`esereYf Єq3N xg$gT`~ a@ 0 :!leL9Xnr~AV\t5h0vEPh9a h舀LDeyX'LJ-eӠ v x66@P`PXhB,Q  xe'Y̪|8j9?Ehb`'v=ͦˠamƇ׆ؖvvx6;k>nv6lkƖ"l^}l9jϻl" &ul pm=F܃!Q>oN'A IhhIx6  Hln Lh– ǁꡞnn%n.DHXP/},O83 f !r#/ 6 7`N-p.kNPp蘮X~*e0R0 WO 3{x}B(?NF`EM@l؀ P8MD8O{0&ɢ#rt*k .YZoN0教9-qmD}7hAQ tCGtEgtGtIt;tLtNOuQwtJ_HuMVɝ ȄB^un羆L`v5MO@pb_R_=Η*4@E8mB?D_FHJLNP/Q'xAypHx*qyfx2cHHvsAcMqxlmyo7yqOr_yt7`0 xyw蟟)gkhXIwpqvklyn'ow'wsgLy@MP/td@{i_&c| 8sG<Gxmn/yp?qWsoy88 xBɧ|7˟揚uc@P)ێ:680y/0Pj}ȏt w|?ou\)cg "LpB(q"Ŋ/R"Ǝ(r$ɒhXK}DPUN0bH&t8d۰a (8p,lڄ(P OH 0E#Άldr,ٲfϢM֡k߾̋o2̫w^~ xIkϪ ^`N> %jԃqv&X+#kÎ-{vڶKƝ[H~.|8Ə<7` <31eڣ!%g+NÏ/sӵ?f"4 (` ဃ> 4|"p'&IbXWbnu/ :;H##lрjȡh"J؟LD2_&#YS&$9ć|#odU)A( /(!"HD饘2ڨթ 3ǘ~ tjD/Q(`@!b 3T|qGc1F B s$B(?n,*pY~..Hsr"_)!t)uA? DA n|r?P ZH"<P?!J@"*<ܮBH,yF ېbA{F h ,U@H/O 8A]:A!E0Cƹr ?1$O1tϸSKyPnS?O0;ݸl?R`PPH/MK{h ?À>bH|]?ˆc;>ڸkխw+܆:57^=}ǖ?8c $cӡ> 1W X#.Kjc3CZ9mpsA3t4` FA7TQe} ?TZ : ewj`D 8pDw.t hŎ`p0sDa{ L@}x,ef= :pT`M6+FRޫnU0 x*+V$n?W3*"2#9\xSH@6G/ {8G/@XK";B+B7$BnsbHDRF2Dv 9 u5jsW:WFgDbp,p?ωl@B 4 3s.49KNb41ZN Ќ0e$K&62VZԧS&KHtC RČHjD CJքr*")KV* x[TJAoNTs.:,1xJ f0ؐ(Wvŕ !WgQ*$X `Rꕯ~N(Vq- p22"ZᚨSllʆoݪxucr`,<} P܍0T?@67Buh^4}<_zpUoWImB1`⾪0X7gO*fkAĊdx򵸯BKc8'9a /-Wor3 ޷Iǭ2g?:Ј3)fWٶt^4kDCMn.Ƀ:x4;o#Y?mS"0ǠLVCͼ,g̊5vH1Y[LX:׼ q$ 8J\66i e+#?FG&ӷli!&؁Imlm`jZ$=5ۛ _x[ssw*kwE)JOޯxg۫n"x{$I{-2c%V`z<:gd`w3]m`}MwKMoE Y=&e2ԻՍn IO@;PKCϲPK"+AOEBPS/img_text/search_album.htm Description of the illustration search_album.gif

This is a text description of search_album.gif.

This is a screen capture of the Oracle interMedia PL/SQL Web Toolkit Photo Album Demo application Search album Web page. This Web page includes navigation links to the View album, Search metadata, and Upload photo Web pages, which are also included in the Oracle interMedia PL/SQL Web Toolkit Photo Album Demo application. This Web page also includes an entry field labeled Full text search: where you can enter keywords or phrases to initiate full text searches through all image metadata, and a button labeled Search, which you can click to start the search operation. Below the Full text search: field, there is a horizontal line. Below that line, the following message is displayed: "Select the thumb-nail to view the full size image. Select the description link to view image metadata." Below that message, the results of the search are displayed as a set of thumbnail images. Below each thumbnail image, there is a description link that you can use to display the metadata for that image.

PKPK"+AOEBPS/img_text/cw12.html Description of the illustration cw12.gif

This is a text description of cw12.gif.

This screen capture shows the Oracle Multimedia Code Wizard: Template Upload Form window.

The upload form contains two fields with values:

  • ID: 1

  • PHOTO: C:\temp\Winter.jpg; a file Browse button lets you browse for the file to upload.

  • DESCRIPTION: Frosty trees

Click the Upload media button to upload this image file.

PKA$SPK"+AOEBPS/img_text/cw1.htm_ Description of the illustration cw1.gif

This is a text description of cw1.gif.

This screen capture shows the Main menu page of the Oracle Multimedia Code Wizard for the PL/SQL Gateway. It shows the name of the current DAD ORDCWADMIN and the name of the current schema CWADMIN. The following options can be selected:

  • Create media retrieval procedure

  • Create media upload procedure

  • DAD authorization

  • Logout

The DAD authorization button is selected.

The following actions can be selected:

  • Next - advances to the next Code Wizard page.

PKƙ5d_PK"+AOEBPS/img_text/imurg002.htm  Description of the illustration imurg002.eps

This is a text description of imurg002.gif.

The description for this illustration is included in the text preceding the illustration.

PK\{% PK"+A!OEBPS/img_text/write_metadata.htm\ Description of the illustration write_metadata.gif

This is a text description of write_metadata.gif.

This is a screen capture of the Oracle interMedia PL/SQL Web Toolkit Photo Album Demo application Write XMP metadata Web page. This Web page includes navigation links to the View entry, View metadata, View album, Search metadata, and Upload photo Web pages, which are also included in the Oracle interMedia PL/SQL Web Toolkit Photo Album Demo application. Below the navigation links, there is a horizontal line. Below that line, the thumbnail image for the image you selected is displayed. To the right of the thumbnail image, the following message is displayed: "Complete the form to add metadata to your photo. Then click the 'Write it!' button." This Web page also includes the following list of entry fields, starting with the topmost field and descending to the bottommost field:

  • Title:

  • Creator: This field is indicated as indicated as (Optional).

  • Date: This field is indicated as indicated as (Optional).

  • Description: This field is indicated as indicated as (Optional).

  • Copyright: This field is indicated as indicated as (Optional).

You can use these fields to enter new XMP metadata for the image you selected. Below these fields, there is a button labeled Write it!, which you can use to write the new XMP metadata for that image file.

PKa \ PK"+AOEBPS/img_text/cw6.htm Description of the illustration cw6.gif

This is a text description of cw6.gif.

This screen capture shows the Step1: Select database table and procedure type page. It shows a list of available tables in the SCOTT schema that were found to contain one or more media columns.

Select a table. The PHOTOS table button is selected.

Choose either to create a standalone PL/SQL procedure or to generate the source of a PL/SQL procedure for inclusion into a PL/SQL package. The Standalone procedure button is selected.

The following actions can be selected:

  • Cancel - cancels the current operation and returns to the Main menu page.

  • Step 1 of 5 Next - advances to the next Code Wizard page.

PKrֺPK"+AOEBPS/img_text/cw11.htm Description of the illustration cw11.gif

This is a text description of cw11.gif.

This screen capture shows the Compile procedure and review generated source page.

Procedure created successfully: UPLOAD_PHOTOS_PHOTO

Click the View button to display the compiled PL/SQL source code in another window. To save the source in a file for editing, select Save As... from your browser's File menu.

Click to display the generated source: View button

Enter a DAD name, or accept the default provided, then click the Test button to display an HTML form in a pop-up window to upload media to the database to test the generated PL/SQL procedure. To save the source in a file for editing, select Save As... from your browser's File menu.

DAD: scottcw Test button

Click the Test button to upload the image.

The following actions can be selected:

  • Done - commits the operation and returns to the Main menu page.

  • Back - goes back to the previous page, Step 5: Review selected options.

PKwlPK"+AOEBPS/img_text/cw15.htmn Description of the illustration cw15.gif

This is a text description of cw15.gif.

This screen capture shows the Step 2: Select media column and key column page.

Select the column from which to retrieve the media data from the following list of media columns found in the PHOTOS table.

The PHOTO (ORDIMAGE) column button is selected.

Select the column to be used to locate the media data from the following list of columns found in the PHOTOS table.

The ID (Primary key) column button is selected.

The following actions can be selected:

  • Cancel - cancels the current operation and returns to the Main menu page.

  • Back - goes back to the previous page, Step 1: Select database table and procedure type.

  • Step 2 of 4 Next - advances to the next Code Wizard page.

PKe?PK"+AOEBPS/img_text/cw3.htm! Description of the illustration cw3.gif

This is a text description of cw3.gif.

This screen capture shows the List of authorized DADs updated page. It shows that the DAD SCOTTCW and the user SCOTT are added to the list of authorized DADs and users authorized to use the Oracle Multimedia Code Wizard.

The following actions can be selected:

  • Done - commits the operation and returns to the Main menu page.

  • Back - goes back to the previous page, the DAD authorization page.

PKz 7PK"+AOEBPS/img_text/cw10.htm" Description of the illustration cw10.gif

This is a text description of cw10.gif.

This screen capture shows the Step 5: Review selected options page.

Click the Finish button if the following options are correct:

  • Procedure type: Standalone

  • Table name: PHOTOS

  • Media column(s): PHOTO (ORDIMAGE)

  • Key column: ID

  • Additional column(s): DESCRIPTION

  • Table access mode: Conditional update or insert

  • Procedure name: UPLOAD_PHOTOS_PHOTO

  • Function: Create procedure in the database

The following actions can be selected:

  • Cancel - cancels the current operation and returns to the Main menu page.

  • Back - goes back to the previous page, Step 4: Select additional columns and procedure name.

  • Step 5 of 5 Finish - advances to the next Code Wizard page.

PK PK"+AOEBPS/img_text/view_album.htm  Description of the illustration view_album.gif

This is a text description of view_album.gif.

This is a screen capture of the Oracle interMedia PL/SQL Web Toolkit Photo Album Demo application View album Web page. This Web page includes navigation links to the Search metadata and Upload photo Web pages, which are also included in the Oracle interMedia PL/SQL Web Toolkit Photo Album Demo application. This Web page also includes an entry field labeled Full text search: where you can enter text for a full text search as well as a button labeled Search, which you can click to start the search operation. Below the Full text search: field, there is a horizontal line. Below that line, the following message is displayed: "Select the thumb-nail to view the full size image. Select the description link to view image metadata." Below that message, the contents of the photo album are displayed as thumbnail images in four-column format. You can select a thumbnail image to display the full-sized version. Below each thumbnail image, there is a description link that you can use to display the metadata for that image.

PKq5 PK"+A OEBPS/img_text/view_metadata.htm Description of the illustration view_metadata.gif

This is a text description of view_metadata.gif.

This is a screen capture of the Oracle interMedia PL/SQL Web Toolkit Photo Album Demo application View metadata Web page. This Web page includes navigation links to the View entry, Write metadata, View album, Search metadata, and Upload photo Web pages, which are also included in the Oracle interMedia PL/SQL Web Toolkit Photo Album Demo application. Below the navigation links, there is a horizontal line. Below that line, the thumbnail image for the image you selected is displayed. To the right of the thumbnail image, the following message is displayed: "The following metadata is available:", followed by a list of metadata documents for the image. Below that message, the full contents of the metadata documents are displayed.

PK[ͽPK"+AOEBPS/img_text/imurg001.htmx Description of the illustration imurg001.eps

This is a text description of imurg001.gif.

The main components of the PL/SQL development environment consist of Oracle HTTP Server powered by Apache, Oracle Database, and a Web browser.

Oracle HTTP Server contains the PL/SQL Gateway or mod_plsql module, the database access description (DAD) that contains the database connection information, and the file system where static HTML files and images are stored for use by Web applications.

Oracle Database contains the PL/SQL stored procedures of the Web application and the PL/SQL Web Toolkit. The PL/SQL Web Toolkit contains a set of packages called htp, htf, and owa packages. These packages are used in the stored procedures to get information about the Web application request, construct HTML tags, and return header information back to the client Web browser as the response returned to PL/SQL Gateway. From the PL/SQL Gateway, the response is returned to the HTTP server for hosting as a formatted Web page for the client Web browser.

PK័̌PK"+AOEBPS/img_text/cw9.htmb Description of the illustration cw9.gif

This is a text description of cw9.gif.

This screen capture shows the Step 4: Select additional columns and procedure name page.

Optionally select any additional columns to be stored in the table along with the media data. The primary key and any columns with a unique or non-null constraint are selected automatically. If updating an existing row, clear any columns you do not wish to be stored. Note that the key column selected in the previous step is always included. The DESCRIPTION column is listed and the column box is selected.

Choose a name for the media upload procedure. You can accept the default provided or supply a different name. The default procedure name, UPLOAD_PHOTOS_PHOTO is shown.

Choose either to create the procedure in the database or to generate the procedure source code only. In either case, you will subsequently have the opportunity to view the generated source code. The Create procedure in the database button is selected.

The following actions can be selected:

  • Cancel - cancels the current operation and returns to the Main menu page.

  • Back - goes back to the previous page, Step 3: Select data access and media column(s).

  • Step 4 of 5 Next - advances to the next Code Wizard page.

PK6 Description of the illustration cw5.gif

This is a text description of cw5.gif.

This screen capture shows the functions that can be selected from the Main menu page of the Oracle Multimedia Code Wizard for the PL/SQL Gateway:

  • Create media retrievel procedure

  • Create media upload procedure (This option is selected.)

The following action can also be selected on the Main menu page:

  • Next - advances to the next Code Wizard page.

PKTPK"+AOEBPS/img_text/cw7.htm= Description of the illustration cw7.gif

This is a text description of cw7.gif.

This screen capture shows the Step 2: Select PL/SQL Gateway document upload table page.

Select either an existing document table or create a new document table. The Use existing document table button is selected. The button for the existing document table named WPG_DOCUMENT is also shown as selected.

If you were to select the Create new document table button, then you would enter a unique table name in the Table Name field.

The following actions can be selected:

  • Cancel - cancels the current operation and returns to the Main menu page.

  • Back - goes back to the previous page, Step 1: Select database table and procedure type.

  • Step 2 of 5 Next - advances to the next Code Wizard page.

PK1 jCPK"+AOEBPS/img_text/cw18.htm0 Description of the illustration cw18.gif

This is a text description of cw18.gif.

This screen capture shows the Compile procedure and review generated source page.

Procedure created successfully: GET_PHOTOS_PHOTO

Click the View button to display the compiled PL/SQL source code in another window. To save the source in a file for editing, select Save As... from your browser's File menu.

Click to display the generated source: View button

Use the following URL format to retrieve media data from the database using the GET_PHOTOS_PHOTO procedure.

http://host:port/DAD-name/get_photos_photo?media_id=key-value

Enter a key value, then click the Test button to test the generated PL/SQL procedure. The media or media player will be displayed in another window.

Key parameter (MEDIA_ID): 1 Test button

Click the Test button to retrieve the image.

The following actions can be selected:

  • Done - commits the operation and returns to the Main menu page.

  • Back - goes back to the previous page, Step 4: Review selected options.

PKK:50PK"+AOEBPS/img_text/cw13.htmJ Description of the illustration cw13.gif

This is a text description of cw13.gif.

This screen capture shows the functions that can be selected from the Main menu page of the Oracle Multimedia Code Wizard for the PL/SQL Gateway:

  • Create media retrieval procedure (This option is selected.)

  • Create media upload procedure

The following action can also be selected on the Main menu page:

  • Next - advances to the next Code Wizard page.

PK.d/PK"+AOEBPS/img_text/cw17.htmv Description of the illustration cw17.gif

This is a text description of cw17.gif.

This screen capture shows the Step 4: Review selected options page.

Click the Finish button if the following options are correct:

  • Procedure type: Standalone

  • Table name: PHOTOS

  • Media column: PHOTO (ORDIMAGE)

  • Key column: ID

  • Procedure name: GET_PHOTOS_PHOTO

  • Parameter name: MEDIA_ID

  • Function: Create procedure in the database

The following actions can be selected:

  • Cancel - cancels the current operation and returns to the Main menu page.

  • Back - goes back to the previous page, Step 3: Select procedure name and parameter name.

  • Step 4 of 4 Finish - advances to the next Code Wizard page.

PKwdUMPK"+AOEBPS/img_text/cw2.htmn Description of the illustration cw2.gif

This is a text description of cw2.gif.

This screen capture shows the DAD authorization page.

This page lists the DADs and users that are authorized to use the Oracle Multimedia Code Wizard. Only the DAD ORDCWADMIN and the user CWADMIN are listed on this page.

Enter the name of the DAD and the user name to be authorized. The DAD SCOTTCW and the user SCOTT are entered.

The following actions can be selected:

  • Cancel - cancels the DAD authorization operation and returns you to the Main menu.

  • Apply - authorizes the DAD and user name you entered and shows you an updated list of authorized DADs.

PKrIPK"+A"OEBPS/img_text/search_metadata.htmB Description of the illustration search_metadata.gif

This is a text description of search_metadata.gif.

This is a screen capture of the Oracle interMedia PL/SQL Web Toolkit Photo Album Demo application Search metadata Web page. This Web page includes text links to the View album and Upload photo Web pages, which are also included in the Oracle interMedia PL/SQL Web Toolkit Photo Album Demo application. Below the text links, there is a horizontal line. Below that line, the following message is displayed: "Select the metadata type, the tag and the search method. Enter a word or phrase to search for. Then click the 'Search' button." This Web page also includes the following entry fields: Search in metadata:, Search in tag:, Search method:, and Search string:. You can use these fields to specify details about the type of metadata to be searched. The Search in metadata: field includes a pull-down menu, from which you can select IPTC, EXIF, or XMP metadata. The Search in tag: field also includes a pull-down menu, which displays the default tag, RDF/Description. The Search method: field provides two options, labeled Contains and Equals, from which to select a search method. The Search string: field is a text entry field, which you can use to enter words or phrases to search for. Below the Search string: field, there is a button labeled Search, which you can click to start the search operation. Below the Search button, there is another horizontal line. Below that line, the following message is displayed: "Select the thumb-nail to view the full size image. Select the description link to view image metadata." Below that message, the results of the search are displayed as a set of thumbnail images. Below each thumbnail image, there is a description link that you can use to display the metadata for that image.

PKR/sG B PK"+AOEBPS/img_text/upload_photo.htmf Description of the illustration upload_photo.gif

This is a text description of upload_photo.gif.

This is a screen capture of the Oracle interMedia PL/SQL Web Toolkit Photo Album Demo application Upload photo Web page. This Web page includes navigation links to the View album and Search metadata Web pages, which are also included in the Oracle interMedia PL/SQL Web Toolkit Photo Album Demo application. Below the navigation links, there is a horizontal line. Below that line, the following message is displayed: "Enter a description and file location for your photo. Then click the 'Upload photo' button." This Web page also includes an entry field labeled Description: , indicated as (Optional), followed by a sample entry of (e.g., My vacation). You can use this field to enter an optional text description for an image. Under the Description: field, there is a field labeled File name: , followed by a text entry box, a Browse... button, and a sample entry of (e.g., island.jpg). You can enter the directory path to the location of the image on the local computer in the Description: field. Or, you can use the Browse... button to find the image on the local computer. Below the Description: field, there is a button labeled Upload photo, which you can use to upload the image file to the database.

PK 5՞PK"+AOEBPS/img_text/view_entry.htm] Description of the illustration view_entry.gif

This is a text description of view_entry.gif.

This is a screen capture of the Oracle interMedia PL/SQL Web Toolkit Photo Album Demo application View entry Web page. This Web page includes navigation links to the View metadata, Write metadata, View album, Search metadata, and Upload photo Web pages, which are also included in the Oracle interMedia PL/SQL Web Toolkit Photo Album Demo application. Below the navigation links, there is a horizontal line. Below that line, there is a field labeled Description:, which displays the description text for the image. Below the description, there is a field labeled Photo:, which displays the full-sized image.

PKjPK"+AOEBPS/img_text/cw16.htmI Description of the illustration cw16.gif

This is a text description of cw16.gif.

This screen capture shows the Step 3: Select procedure name and parameter name page.

Choose a name for the media retrieval procedure. You can accept the default provided or supply a different name.

The Procedure name field contains the default name: GET_PHOTOS_PHOTO

Choose a name for the parameter used to supply the key value. You can accept the default provided or supply a different name. The parameter name is used in a media retrieval URL as follows: http://host/DAD/proc-name?param-name=key-value

The Parameter name field contains the name: MEDIA_ID

Choose either to create the procedure in the database or to generate the procedure source code only. In either case you will subsequently have the opportunity to view the generated source code.

The Create procedure in the database button is selected.

The following actions can be selected:

  • Cancel - cancels the current operation and returns to the Main menu page.

  • Back - goes back to the previous page, Step 2: Select media column and key column.

  • Step 3 of 4 Next - advances to the next Code Wizard page.

PK NIPK"+AOEBPS/img_text/cw4.htmq Description of the illustration cw4.gif

This is a text description of cw4.gif.

This screen capture shows the Main menu page of the Oracle Multimedia Code Wizard for the PL/SQL Gateway. It shows the current DAD SCOTTDCW and the current schema SCOTT. The following options can be selected:

  • Create media retrieval procedure (This option is selected.)

  • Create media upload procedure

  • Change DAD, with these options:

    • Change to ORDCWADMIN (This option is selected.)

    • Change to SCOTTCW

  • Logout

The following action can be selected:

  • Next - advances to the next Code Wizard page.

PKA NPK"+AOEBPS/img_text/cw14.htm" Description of the illustration cw14.gif

This is a text description of cw14.gif.

This screen capture shows the Step 1: Select database table and procedure type page.

Select a table from the following list of tables found to contain one or more media columns.

The PHOTOS button is selected.

Choose either to create a standalone PL/SQL procedure or to generate the source of a PL/SQL procedure for inclusion into a PL/SQL package.

The Standalone procedure button is selected.

The following actions can be selected:

  • Cancel - cancels the current operation and returns to the Main menu page.

  • Step 1 of 4 Next - advances to the next Code Wizard page.

PK3PK"+AOEBPS/img_text/cw8.htm Description of the illustration cw8.gif

This is a text description of cw8.gif.

This screen capture shows the Step 3: Select data access and media column(s) page.

Select the column or columns to which media data is to be uploaded from the following list of media columns found in the PHOTOS table. If the table contains multiple media columns, you may select multiple columns to allow more than one media item to be uploaded from a single HTML form. Two columns are listed: THUMBNAIL (ORDIMAGE) and PHOTO (ORDIMAGE). The PHOTO (ORDIMAGE) column box is selected.

Select the column to be used to locate the media data from the following list of columns found in the PHOTOS table. Two columns are listed: ID (Primary key) and DESCRIPTION. The ID (Primary key) column button is selected.

Choose how the generated procedure will access the table to store uploaded media data. You may choose to insert a new row into the table, to update an existing row in the table, or to conditionally insert a new row if an existing row does not exist. The Conditional insert or update row button is selected.

The following actions can be selected:

  • Cancel - cancels the current operation and returns to the Main menu page.

  • Back - goes back to the previous page, Step 2: Select PL/SQL Gateway document upload table.

  • Step 3 of 5 Next - advances to the next Code Wizard page.

PKPK"+AOEBPS/ch_dba.htm~v Oracle Multimedia Tuning Tips for DBAs

8 Oracle Multimedia Tuning Tips for DBAs

This chapter provides information and advice for Oracle DBAs who want to achieve more efficient storage and management of multimedia data in the database when using Oracle Multimedia.

The goals of your Oracle Multimedia application determine the resource requirements and how to allocate those resources. Because application development and design decisions have the greatest effect on performance, standard tuning methods must be applied to the system planning, design, and development phases of the project to achieve optimal results for your Oracle Multimedia application in a production environment.

Multimedia data consists of a variety of media types including images, audio clips, video clips, line drawings, and so on. All these media types are typically stored in LOBs. LOBs can be either internal BLOBs (stored in an internal database tablespace) or BFILEs (external LOBs in operating system files outside of the database tablespaces). This chapter discusses the management of audio, image, and video data stored in BLOBs only.

This chapter includes these sections:


See Also:

Oracle Database SecureFiles and Large Objects Developer's Guide for more information about using LOBs in Oracle Database


8.1 Understanding the Performance Profile of Oracle Multimedia Operations

Multimedia data, and the operations that can be performed on that data, differs significantly from traditional types of data commonly stored in relational databases. A basic understanding of the performance profile of Oracle Multimedia operations can help you make better decisions when tuning your database for media performance.

The following tables summarize the general performance profiles for a set of commonly performed operations. There are two primary components to each profile. The I/O pattern is a general characterization of the primary type of I/O access and of how much of the media data the operation reads or writes. Because some operations involve two media objects, the I/O pattern is described for both the source and destination media objects. The second component is a general characterization of the level of CPU usage for the operation.


Note:

The information in these tables describes general characterizations and I/O patterns, thus CPU usage may vary considerably for some media formats.

Table 8-1 shows the profile for loading and retrieving data, which applies to all Oracle Multimedia media types.

Table 8-1 Performance Profile For All Multimedia Types

OperationI/O Pattern (Source)I/O Pattern (Destination)I/O Pattern (Amount)CPU Usage

Load new media data into a database

N/A

Sequential write

All

Low

Retrieve media from a database

Sequential read

N/A

All

Low


Table 8-2 shows the profile for commonly used methods of the ORDImage type.

Table 8-2 Performance Profile For ORDImage Methods

Object MethodI/O Pattern (Source)I/O Pattern (Destination)I/O Pattern (Amount)CPU Usage

setProperties( )

Sequential read

N/A

Media header

Low to medium

getMetadata( )

Sequential read

N/A

Media header

Low to medium

putMetadata( )

Sequential read

Sequential write

All

Low to medium

process( )

Sequential read

Sequential write

All

High

processCopy( )

Sequential read

Sequential write

All

High


Table 8-3 shows the profile for commonly used methods of the ORDDicom type.

Table 8-3 Performance Profile For ORDDicom Methods

Object MethodI/O Pattern (Source)I/O Pattern (Destination)I/O Pattern (Amount)CPU Usage

setProperties( )

Sequential read

N/A

Media header

Low to medium

extractMetadata( )

Sequential read

N/A

Media header

Low to medium

writeMetadata( )

Sequential read

Sequential write

All

Low to medium

makeAnonymous( )

Sequential read

Sequential write

All

Low to medium

process( )

Sequential read

Sequential write

All

High

processCopy( )

Sequential read

Sequential write

All

High


Table 8-4 shows the profile for commonly used methods of the ORDAudio and ORDVideo types.

Table 8-4 Performance Profile For ORDAudio and ORDVideo Methods

Object MethodI/O Pattern (Source)I/O Pattern (Destination)I/O Pattern (Amount)CPU Usage

setProperties( )

Sequential read

N/A

Media header

Low

getProperties( )

Sequential read

N/A

Media header

Low


8.2 Choosing LOB Storage Parameters for Oracle Multimedia Objects

The choices you make for specifying LOB storage attributes during table creation can significantly affect the performance of media load, retrieval, and processing operations. This section describes the most important options to consider and shows how the performance profile of Oracle Multimedia operations can affect the choice of LOB storage parameters.

The following subsections describe the LOB storage parameters and include examples of how to use them:


See Also:

Oracle Database SecureFiles and Large Objects Developer's Guide for detailed information about LOBs


8.2.1 SecureFile LOBs and BasicFile LOBs

SecureFile LOBs (SecureFiles) were introduced in Oracle Database 11g Release 1 (11.1) to supplement the original BasicFile LOBs implementation that is identified by the SQL parameter BASICFILE. The performance of SecureFile LOBs is significantly better than that of BasicFile LOBs, especially for large media data. Oracle recommends using SecureFile LOBs for storing media data whenever possible. SecureFile LOBs are identified by specifying the SQL parameter SECUREFILE.

8.2.2 TABLESPACE

You can achieve the best performance for LOBs by specifying storage for LOBs in a different tablespace than the one used for the table that contains the LOB. If many different LOBs are to be accessed frequently, you can also specify a separate tablespace for each LOB column or attribute to reduce device contention.

8.2.3 CACHE, NOCACHE, and CACHE READS

The cache option is a part of the STORE AS clause, and determines whether LOB pages are stored in the buffer cache.

  • When the option has the value CACHE, Oracle places LOB pages in the buffer cache where they can be shared among multiple users. Over time and if the LOB pages are no longer accessed, the pages are eventually removed from the buffer cache.

  • For the value NOCACHE, LOB pages are not placed in the buffer cache.

  • For the value CACHE READS, LOB pages are placed in the cache for read operations only.

If your application performs multiple read operations on a media object (for example: invoking the setProperties( ) method and then generating a thumbnail image), enable read caching for the source media object.

8.2.4 LOGGING and NOLOGGING

The logging option is a part of the STORE AS clause and determines if REDO data is logged when a LOB is updated. If the [NO]LOGGING clause is omitted, neither NOLOGGING nor LOGGING is specified and the logging attribute of the table or table partition defaults to the logging attribute of the tablespace in which it resides.

There is another alternative depending on how the cache option is specified.

  • If CACHE is specified and [NO]LOGGING is omitted, LOGGING is automatically implemented (because you cannot have CACHE NOLOGGING).

  • If CACHE is not specified and [NO]LOGGING is omitted, the [NO]LOGGING value is obtained from the tablespace in which the LOB segment resides.

Specify NOLOGGING only when you do not care about media recovery. However, if the disk, tape, or storage media fails, you will not be able to recover your changes from the log because those changes were not logged.

NOLOGGING can be useful for bulk loading of media data. For instance, when loading data into the LOB, if you do not care about the redo operation and you can start the load over if it fails, set the LOB data segment storage characteristics to NOCACHE NOLOGGING. This option provides good performance for the initial loading of data.

After you finish loading data, if necessary, you can use the ALTER TABLE statement to modify the LOB storage characteristics for the LOB data segment for normal LOB operations (for example: to CACHE or NOCACHE LOGGING).


Note:

Oracle Data Guard Redo Apply technology uses logging to populate the standby database. Thus, do not specify NOLOGGING with this Data Guard technology.

8.2.5 CHUNK

The CHUNK option applies only to BasicFile LOBs. It is part of the STORE AS clause, and indicates the size of the minimum unit of storage for the LOB data. CHUNK must be an integer multiple of the block size, and it must have a maximum value of 32K bytes.

Accessing LOBs in bigger chunks is more efficient. For the most efficient storage of media objects, which are almost always much larger than 32K, choose the maximum value of 32K.

8.2.6 Example of Setting LOB Storage Options

This section describes a simple example that shows how to use the performance profiles of Oracle Multimedia operations (see Table 8-1 through Table 8-4) to guide your usage of LOB storage options.

In this example, Company X wants to build an archive for digital images. The archive stores a full resolution copy of the original image, and two Web-ready, JPEG format versions of the original at reduced scales, one at 50% of the original size and another at 25% of the original size. The database team plans to use the SQL*Loader utility to bulk load all the initial images. Then, they can use a PL/SQL program to initialize the image data. Initialization consists of setting the properties for the original image and generating the scaled images. After initialization, the table is prepared for the primary application, which retrieves images for Web-based users.

The following example shows a table definition for storing the images. The table stores the binary image data using SecureFiles in tablespace tbs2. All the other table data is stored in tablespace tbs1.

create table images(id        integer primary key,
                    original  ordsys.ordimage,
                    scale50   ordsys.ordimage,
                    scale25   ordsys.ordimage)
tablespace tbs1
lob(original.source.localdata)store as secureFile (tablespace tbs2)
lob(scale50.source.localdata)store as secureFile (tablespace tbs2)
lob(scale25.source.localdata)store as secureFile (tablespace tbs2);

After the table is created, the image data can be loaded. Loading image data generates a sequential write pattern to the LOB. Because no applications are reading the data during the load operation, caching it is not required. You can also improve load performance by disabling logging for the column that is loaded. The following command dynamically alters the table to prepare the original image column LOB for loading.

alter table images modify lob(original.source.localdata) (nocache nologging);

After loading, the next step is to set the image properties for the original column and generate the scaled versions to be stored in the scale50 and scale25 columns. In this step, the source image are fully read twice to generate the scaled versions. The scaled images that are generated are written but not read. The following command dynamically alters the table to enable read caching for the source image, and disables caching and logging for the destination images.

alter table images modify lob(original.source.localdata) (cache reads);
alter table images modify lob(scale50.source.localdata) (nocache nologging);
alter table images modify lob(scale25.source.localdata) (nocache nologging);

After running the program to set the properties of the original image and generate the scaled versions, the LOB storage attributes can be optimized for the main application that retrieves images for users to view in a Web browser. Because the archive contains millions of images, users are not expected to view the same image simultaneously. Thus, there is little benefit to caching the image data. The following command reenables logging for the LOBs and disables caching.

alter table images modify lob(original.source.localdata) (nocache logging);
alter table images modify lob(scale50.source.localdata) (nocache logging);
alter table images modify lob(scale25.source.localdata) (nocache logging);

8.3 Setting Database Initialization Parameters

Section 8.2 points out that you can disable logging of LOB data at the column level to reduce the amount of I/O to the redo log. However, if logging cannot be disabled, additional database tuning may be required. Specifically, you may have to increase the size of the redo log buffer to prevent load processes from waiting.

The initialization parameter LOG_BUFFER specifies the amount of memory (in bytes) that Oracle uses when buffering redo entries to a redo log file. Redo log entries contain a record of the changes that have been made to the database block buffers. The LGWR process writes redo log entries from the log buffer to a redo log file.

If the LGWR process writes the redo log data to the redo log buffer faster than it can write the data to disk, the buffer becomes full and user sessions are forced to wait until space is available. The wait event "log buffer space" indicates the number of times a session had to wait for space in the redo log buffer. You can monitor this event in the V$SYSTEM_EVENT dynamic view to learn how many times a session had to wait for log buffer space. If sessions are forced to wait often for log buffer space, consider increasing the value of the LOG_BUFFER initialization parameter.


See Also:

Oracle Database Performance Tuning Guide and Oracle Database Reference for comprehensive information on setting database initialization parameters


PKwv~vPK"+A OEBPS/toc.ncx Oracle® Multimedia User's Guide, 11g Release 2 (11.2) Cover Table of Contents List of Examples List of Figures List of Tables Oracle Multimedia User's Guide, 11g Release 2 (11.2) Preface What's New in Oracle Multimedia? Introduction to Oracle Multimedia Oracle Multimedia Application Development Oracle Multimedia Photo Album Sample Applications Oracle Multimedia Code Wizard Sample Application for the PL/SQL Gateway Oracle Multimedia Java API Sample Application Working with Metadata in Oracle Multimedia Images Extending Oracle Multimedia Oracle Multimedia Tuning Tips for DBAs Oracle Multimedia Examples Oracle Multimedia Sample Applications Managing Oracle Multimedia Installations Glossary Index Copyright PK}!PK"+AOEBPS/ch_examples.htm Oracle Multimedia Examples

9 Oracle Multimedia Examples

This chapter provides examples that show common operations with Oracle Multimedia.

These scripts, and other examples, can be found on the Oracle Multimedia Sample Code section of the Oracle Technology Network (OTN) Web site at

http://www.oracle.com/technology/products/multimedia/

Select Sample Code under Oracle Multimedia Resources to go to the Oracle Multimedia Sample Code Web page. On that page, select Use Multimedia and PL/SQL to manage rich media content under Multimedia Code Samples.


Note:

To run these examples on your system, use the files on the Oracle Multimedia Sample Code Web page. Do not attempt to compile and run the code in this chapter.

This chapter includes these sections:

9.1 Audio Data Examples

Audio data examples using Oracle Multimedia include common operations on audio data, such as using audio types with object views and using a set of scripts for populating an ORDAudio object with BLOB data stored in the database. The following subsections describe these operations:


See Also:

Oracle Multimedia Reference for reference information about the methods used in these examples


9.1.1 Using Audio Types with Object Views

This section describes how to use audio types with object views. Just as a view is a virtual table, an object view is a virtual object table.

Oracle provides object views as an extension of the basic relational view mechanism. By using object views, you can create virtual object tables -- of either built-in or user-defined types -- from data stored in the columns of relational or object tables in the database.

Object views can offer specialized or restricted access to the data and objects in a database. For example, you might use an object view to provide a version of an employee object table that does not have attributes containing sensitive data or a deletion method. Object views also let you try object-oriented programming without permanently converting your tables. Using object views, you can convert data gradually and transparently from relational tables to object-relational tables.

In Example 9-1, consider the following relational table (containing no ORDAudio objects).

Example 9-1 Define a Relational Table Containing No ORDAudio Object

create table flat (
   id                NUMBER,
   description       VARCHAR2(4000),
   localData         BLOB,
   srcType           VARCHAR2(4000),
   srcLocation       VARCHAR2(4000),
   srcName           VARCHAR2(4000),
   upDateTime        DATE,
   local             NUMBER,
   format            VARCHAR2(31),
   mimeType          VARCHAR2(4000),
   comments          CLOB,
   encoding          VARCHAR2(256),
   numberOfChannels  NUMBER,
   samplingRate      NUMBER,
   sampleSize        NUMBER,
   compressionType   VARCHAR2(4000),
   audioDuration     NUMBER,
)
--
-- Store audio data as SecureFile LOBs.
--
LOB(localData) STORE AS SECUREFILE;

You can create an object view on the relational table shown in Example 9-1, as shown in Example 9-2.

Example 9-2 Define an Object View Containing an ORDAudio Object and Relational Columns

create or replace view object_audio_v as 
  select
      id,
      ORDSYS.ORDAudio(T.description,
      ORDSYS.ORDSource(
         T.localData, T.srctype, T.srcLocation, T.srcName, T.updateTime,
         T.local),
         T.format,
         T.mimeType,
         T.comments, 
         T.encoding, 
         T.numberOfChannels, 
         T.samplingRate, 
         T.sampleSize, 
         T.compressionType, 
         T.audioDuration)
   from flat T;

Object views provide the flexibility of looking at the same relational or object data in more than one way. Therefore, you can use different in-memory object representations for different applications without changing the way you store the data in the database.


See Also:

See Oracle Database Concepts for more information about defining, using, and updating object views.


9.1.2 Scripts for Populating an ORDAudio Object with BLOB Data

The scripts presented in this section demonstrate how to populate an Oracle Multimedia ORDAudio object from an existing BLOB stored in the database.

Table 9-1 lists each script by name, along with a brief description of the operations it performs. Each script is included and described in further detail in the following sections.

Table 9-1 Audio Scripts

Script NameOperations Performed

create_mediadir.sql

(See Example 9-3)

Creates an audio data load directory.

(See Section 9.1.2.1)

create_soundtable.sql

(See Example 9-4)

Creates and populates the soundtable table.

(See Section 9.1.2.2)

create_audtable.sql

(See Example 9-5)

Creates the audio_table table.

(See Section 9.1.2.3)

import_aud.sql

(See Example 9-6)

Loads the audio data. This script imports the audio data from an audio file into the audio_table table using the ORDAudio import( ) method.

(See Section 9.1.2.4)

copy_audblob.sql

(See Example 9-7)

Copies the BLOB data from the soundtable table to the audio_table table.

(See Section 9.1.2.5)

showprop_aud.sql

(See Example 9-8)

Displays the properties of the loaded audio data stored in the audio_table table.

(See Section 9.1.2.6)

setup_audsample.sql

(See Example 9-9)

Automates the process by running the previous audio scripts in the required order.

(See Section 9.1.2.7)

cleanup_audsample.sql

(See Example 9-10)

Cleans up by removing the sample tables, directories, and procedures from your database.

(See Section 9.1.2.8)


9.1.2.1 Create an Audio Data Load Directory

The create_mediadir.sql script creates the audio data load directory. This script is shown in Example 9-3. (See Section 9.2.1.1 and Section 9.3.1.1, respectively, for information about how to use this script to create the load directories for media data and image data.)

To load the audio data successfully, you must create a database directory object that points to a file directory on your system. Example 9-3 uses the media_dir directory, which points to the file directory C:\media_dir. You can edit the create_mediadir.sql script to replace the directory path in the CREATE OR REPLACE DIRECTORY statement with your directory specification.

This directory specified in the create_mediadir.sql script must contain your sample audio files. The audio examples use the sample file aud1.wav, which is installed in the <ORACLE_HOME>/ord/aud/demo directory. You can copy any supported audio files to the C:\media_dir directory to run the scripts in these examples.

Before running the create_mediadir.sql script, ensure that you have these privileges:

  • CREATE ANY DIRECTORY (to specify the directory specification for your audio files)

  • DROP ANY DIRECTORY (to delete previous instances of the audio data load directory)


Note:

If you run the create_mediadir.sql script as a different user than the user who ran the other audio scripts, you must perform these steps:
  1. Uncomment the GRANT READ ON DIRECTORY statement.

  2. Replace the string <USER> in this statement with the new user (for example: SCOTT).


Example 9-3 create_mediadir.sql Script

-- create_mediadir.sql
--
SET SERVEROUTPUT ON;
SET ECHO ON;
 
-- To delete the directory, uncomment the next statement; 
-- otherwise, leave it commented out.
-- DROP DIRECTORY media_dir;
 
-- To specify a different directory path, replace the default directory 
-- path with the new path in the next statement.
CREATE OR REPLACE DIRECTORY media_dir AS 'C:\media_dir';

-- To change the user, uncomment the next statement and replace the 
-- string "<USER>" with the new user. Otherwise, leave the statement 
-- commented out.
-- GRANT READ ON DIRECTORY media_dir TO <USER>;

9.1.2.2 Create and Populate the soundtable Table

The create_soundtable.sql script creates and populates the soundtable table. This table contains a BLOB column; it is created to demonstrate how to populate a table with an Oracle Multimedia ORDAudio column from a table with a BLOB column. This script is shown in Example 9-4.

This script creates the soundtable table, inserts a row with an empty BLOB, loads the BLOB with audio data, and then checks the length of the BLOB data. You can replace the name of the data file in the create_soundtable.sql script with the name of the data file you plan to use.

Before running this script, ensure that you have the CREATE TABLE privilege.

Example 9-4 create_soundtable.sql Script

-- create_soundtable.sql
--
-- Create the soundtable table. This table is used ONLY to show
-- how to copy data from a BLOB column to an ORDAudio column.
--
-- Insert a row into the table with an empty BLOB.
-- Load the row with BLOB data by pointing to the audio file to 
-- be loaded from the directory specified using the BFILE data 
-- type.
-- Close the files and commit the transaction.
-- Check the length of the BLOB loaded. Is the length
-- what you are expecting?
--
SET SERVEROUTPUT ON;
 
CREATE TABLE soundtable ( id number,
                         sound BLOB default EMPTY_BLOB() )
--
-- Store audio data as SecureFile LOBs.
--
LOB(sound) STORE AS SECUREFILE;
 
-- 
INSERT INTO soundtable(id, sound) VALUES (1, EMPTY_BLOB());
COMMIT;

DECLARE
   f_lob BFILE := BFILENAME('MEDIA_DIR','aud1.wav');
   b_lob BLOB;
   length INTEGER;
BEGIN
 
  SELECT sound INTO b_lob FROM soundtable WHERE id=1 FOR UPDATE;
 
  -- Open the LOBs.
  dbms_lob.open(f_lob, dbms_lob.file_readonly);
  dbms_lob.open(b_lob, dbms_lob.lob_readwrite);
 
  -- Populate the BLOB from the 'aud1.wav' file in the BFILE.
  dbms_lob.loadfromfile (b_lob, f_lob, dbms_lob.getlength(f_lob));
 
  -- Close the LOBs.
  dbms_lob.close(b_lob);
  dbms_lob.close(f_lob);
  COMMIT;
 
  -- Check the length of the LOB.
  SELECT dbms_lob.getlength(t.sound) INTO length FROM soundtable t WHERE id = 1;
  DBMS_OUTPUT.PUT_LINE('The length is '|| length);
END;
/

9.1.2.3 Create the audio_table Table

The create_audtable.sql script creates the audio_table table with the two columns id and audio. The audio column is defined as type ORDAudio. This script is shown in Example 9-5.

Before running this script, ensure that you have the CREATE TABLE privilege.

Example 9-5 create_audtable.sql Script

-- create_audtable.sql
--
CREATE TABLE audio_table ( id NUMBER,
                       audio ORDAudio )
LOB(audio.source.localData) STORE AS SECUREFILE;

9.1.2.4 Load the Audio Data

The import_aud.sql script inserts a row into the audio_table table, and imports audio data from an audio file into the audio column in the audio_table table using the ORDAudio import( ) method. This script is shown in Example 9-6.

To run this script successfully, you must copy one audio clip to your media_dir directory using the name specified in this script, or modify this script to match the file names of your audio clips.

This script loads the same audio clip that was loaded by the create_soundtable.sql script. It is used later in the showprop_aud.sql script to show that data loaded with the import( ) method matches the data copied from the BLOB column of the soundtable table.


Note:

Run this script as the user who ran the previous audio scripts.

Example 9-6 import_aud.sql Script

--import_aud.sql
--
DECLARE
  obj ORDAUDIO;
  ctx RAW(64) := NULL;
 
BEGIN
 
  -- Insert a row with an ORDAudio object.
  INSERT INTO audio_table VALUES 
    (1, ORDAudio('FILE', 'MEDIA_DIR', 'aud1.wav'))
    returning audio into obj;
 
  --Import the audio clip aud1.wav from media_dir.
  obj.import(ctx);
 
  --Set the properties.
  obj.setProperties(ctx);
 
  --Update the table with the audio object. 
  UPDATE audio_table SET audio = obj WHERE id = 1;
 
  COMMIT;
 
END;
/

9.1.2.5 Copy the BLOB Data to the ORDAudio Object

The copy_audblob.sql script inserts a row with id=2 into the audio_table table and copies the audio data in the sound column of the soundtable table into the audio column of the audio_table table for a row with id=2. The script uses the ORDAudio constructor that takes a BLOB as the input parameter. It also sets the properties of the audio data after inserting it. This script is shown in Example 9-7.


Note:

Run this script as the user who ran the previous audio scripts.

Example 9-7 copy_audblob.sql Script

--copy_audblob.sql
-- 
-- Use the ORDAudio constructor that takes a BLOB as the input parameter
-- in the SQL INSERT statement.
-- 
-- In this case, the BLOB (an audio clip), which was stored in
-- a row with ID = 1 in the soundtable table, is copied to a row 
-- with ID = 2 in the audio_table table containing an audio column 
-- defined as an ORDAudio object type.
-- 
INSERT INTO audio_table
  (select 2, ORDAudio(S.sound) FROM soundtable S WHERE S.id = 1);
 
DECLARE
 obj ORDSYS.ORDAudio;
 ctx RAW(40) := NULL;
BEGIN
SELECT audio INTO obj FROM audio_table WHERE id = 2 for update;
obj.setProperties(ctx);
UPDATE audio_table SET audio = obj WHERE ID = 2;
END;
/
 
COMMIT; 

9.1.2.6 Show the Properties of the Loaded Audio Data

The showprop_aud.sql script displays the properties of the audio data clips stored in the audio_table table. They should be identical. Different load methods were used to load the same audio clip into two rows in the audio_table table. This script verifies that the audio data that was loaded using the ORDAudio import( ) method matches the audio data that was copied from a BLOB column of the soundtable table. This script is shown in Example 9-8.


Note:

Run this script as the user who ran the previous audio scripts.

Example 9-8 showprop_aud.sql Script

-- showprop_aud.sql
--
SET SERVEROUTPUT ON;
 
--
--Query audio_table for ORDAudio content in PL/SQL.
--
 
BEGIN
  -- Check the properties of the audio data clip imported into the
  -- ORDAudio object type. Properties for ID=1 should be identical
  -- with ID=2.
 
  dbms_output.put_line(' Properties of these audio clips are identical:');
 
  FOR rec in (SELECT id, audio FROM audio_table ORDER BY id) LOOP 
    dbms_output.put_line('Properties for id: ' || rec.id);
 
    dbms_output.put_line('audio encoding: ' || rec.audio.getEncoding);
    dbms_output.put_line('audio number of channels: '|| 
                        rec.audio.getNumberOfChannels);
    dbms_output.put_line('audio MIME type: ' || rec.audio.getMimeType);
    dbms_output.put_line('audio file format: ' || rec.audio.getFormat);
    dbms_output.put_line
        ('----------------------------------------------');
  END LOOP;
END;
/
--
-- Query audio_table for ORDAudio and list the properties using SQL.
--
clear columns
column id       format 99;
column encoding format a15;
column mimetype   format a20;
column fileformat   format a15;
column channels     format 99;
SELECT t.id, 
       t.audio.getEncoding() encoding, 
       t.audio.getNumberOfChannels() channels, 
       t.audio.getMimetype() mimetype, 
       t.audio.getFormat() fileformat 
from audio_table t ORDER BY t.id;

The results from running the script showprop_aud.sql show that the properties are identical for each stored audio clip.

Properties of these audio clips are identical:
Properties for id: 1
audio encoding: MS_PCM
audio number of channels: 1
audio MIME type: audio/x-wav
audio file format: WAVE
----------------------------------------------
Properties for id: 2
audio encoding: MS_PCM
audio number of channels: 1
audio MIME type: audio/x-wav
audio file format: WAVE
----------------------------------------------
 
PL/SQL procedure successfully completed.
 
 
ID ENCODING        CHANNELS MIMETYPE             FILEFORMAT     
--- --------------- -------- -------------------- ---------------
  1 MS_PCM                 1 audio/x-wav          WAVE
  2 MS_PCM                 1 audio/x-wav          WAVE

9.1.2.7 Automate the ORDAudio Examples

The setup_audsample.sql script runs each of the previous audio scripts in the correct order to automate this process. This script is shown in Example 9-9.

Before running this script, ensure that you have these privileges:

  • CREATE ANY DIRECTORY

  • CREATE TABLE

Example 9-9 setup_audsample.sql Script

-- setup_audsample.sql
--
 
-- Create the media_dir load directory:
@create_mediadir.sql
 
-- Create the soundtable table and populate it with
-- an audio clip:
@create_soundtable.sql
 
-- Create the audio_table table:
@create_audtable.sql
 
--Import an audio clip:
@import_aud.sql
 
-- Copy a BLOB into an ORDAudio object, set the properties,
-- and update the time:
@copy_audblob.sql
 
-- Check the properties of the audio clips. The properties
-- should be identical:
@showprop_aud.sql
 
--exit;

9.1.2.8 Clean Up the ORDAudio Examples

The cleanup_audsample.sql script removes the sample tables, directories, and procedures created by the previous audio scripts from your database. This script is shown in Example 9-10.

Before running this script, ensure that you have the DROP ANY DIRECTORY privilege.


Note:

Run this script as the user who ran the previous audio scripts.

Example 9-10 cleanup_audsample.sql Script

-- cleanup_audsample.sql
--
-- Drop the audio load directory.
-- DROP DIRECTORY media_dir;
 
-- Drop the tables created by the demo.
DROP TABLE soundtable PURGE;
DROP TABLE audio_table PURGE;

exit;

9.2 Media Data Examples

Media data examples using Oracle Multimedia include common operations on heterogeneous data, such as using a set of scripts for populating an ORDDoc object from a file data source. The following subsection describes this operation:


See Also:

Oracle Multimedia Reference for reference information about the methods used in these examples


9.2.1 Scripts for Populating an ORDDoc Object from a File Data Source

The scripts presented in this section demonstrate how to populate an ORDDoc object from an existing file.

Table 9-2 lists each script by name, along with a brief description of the operations it performs. Each script is included and described in further detail in the following sections.

Table 9-2 Media Scripts

Script NameOperations Performed

create_mediadir.sql

(See Example 9-3)

Creates a media data load directory.

(See Section 9.2.1.1)

create_doctable.sql

(See Example 9-11)

Creates the doc_table table.

(See Section 9.2.1.2)

import_doc.sql

(See Example 9-12)

Loads the media data. This script imports the media data from a file into the doc_table table using the ORDDoc import( ) method.

(See Section 9.2.1.3)

read_doc.sql

(See Example 9-13)

Reads the media data from a BLOB using a stored procedure.

(See Section 9.2.1.4)

showprop_doc.sql

(See Example 9-14)

Displays the properties of the loaded media data stored in the doc_table table.

(See Section 9.2.1.5)

setup_docsample.sql

(See Example 9-15)

Automates the process by running the previous media scripts in the required order.

(See Section 9.2.1.6)

cleanup_docsample.sql

(See Example 9-16)

Cleans up by removing the sample tables, directories, and procedures from your database.

(See Section 9.2.1.7)


9.2.1.1 Create a Media Data Load Directory

The create_mediadir.sql script creates the media data load directory. This script is shown in Example 9-3.

To load the media data successfully, you must create a database directory object that points to a file directory on your system. Example 9-3 uses the media_dir directory, which points to the file directory C:\media_dir. You can edit the create_mediadir.sql script to replace the directory path in the CREATE OR REPLACE DIRECTORY statement with your directory specification.

This directory specified in the create_mediadir.sql script must contain your sample media files. The media examples use the sample files aud1.wav and aud2.mp3, which are installed in the <ORACLE_HOME>/ord/aud/demo directory. You can copy any supported media files to the C:\media_dir directory to run the scripts in these examples.

Before running the create_mediadir.sql script, ensure that you have these privileges:

  • CREATE ANY DIRECTORY (to specify the directory specification for your media files)

  • DROP ANY DIRECTORY (to delete previous instances of the media data load directory)


Note:

If you run the create_mediadir.sql script as a different user than the user who ran the other media scripts, you must perform these steps:
  1. Uncomment the GRANT READ ON DIRECTORY statement.

  2. Replace the string <USER> in this statement with the new user (for example: SCOTT).


9.2.1.2 Create the doc_table Table

The create_doctable.sql script creates the doc_table table with the two columns id and document. The document column is defined as type ORDDoc. This script is shown in Example 9-11.

Before running this script, ensure that you have the CREATE TABLE privilege.

Example 9-11 create_doctable.sql Script

-- create_doctable.sql
--
CREATE TABLE doc_table ( id NUMBER,
                         document ORDDoc )
LOB(document.source.localData) STORE AS SECUREFILE;

9.2.1.3 Load the Media Data

The import_doc.sql script inserts two rows into the doc_table table, and imports media data from a media file into the document column in the doc_table table using the ORDDoc import( ) method. This script is shown in Example 9-12.

To run this script successfully, you must copy two media files to your media_dir directory using the names specified in this script, or modify this script to match the file names of your media files.


Note:

Run this script as the user who ran the previous media scripts.

Example 9-12 import_doc.sql Script

-- import_doc.sql
--
CREATE OR REPLACE PROCEDURE load_document (in_id INTEGER, 
                                           in_dir VARCHAR2, 
                                           in_fname VARCHAR2)
AS
  obj ORDDOC;
  ctx RAW(64) := NULL;
BEGIN
  INSERT INTO doc_table VALUES 
    (in_id, ORDDoc('FILE', in_dir, in_fname))
    RETURNING document INTO obj;
  obj.import(ctx,TRUE);
  UPDATE doc_table SET document = obj WHERE id = in_id;
  COMMIT;
END;
/
show errors;
 
-- Import the audio files aud1.wav and aud2.mp3 from the MEDIA_DIR directory
-- on a local file system. 
EXECUTE load_document(1, 'MEDIA_DIR', 'aud1.wav');
EXECUTE load_document(2, 'MEDIA_DIR', 'aud2.mp3');

9.2.1.4 Read the Media Data from the BLOB

The read_doc.sql script reads media data from a BLOB by creating the stored procedure read_document. This procedure reads a specified amount of media data from the BLOB attribute, beginning at a particular offset, until all the media data is read. This script is shown in Example 9-13.


Note:

Run this script as the user who ran the previous media scripts.

Example 9-13 read_doc.sql Script

--read_doc.sql
--
SET SERVEROUTPUT ON
 
create or replace procedure read_document( in_id integer) as
obj ORDDoc;
buffer RAW (32767);
numBytes integer;
bytesRead integer := 0;
startpos integer := 1;
ctx RAW(64) := NULL;
BEGIN
  select document into obj from doc_table where id = in_id;
  DBMS_OUTPUT.PUT_LINE('Content length is: ' || obj.getContentLength());
 
  LOOP
    numBytes := 32767;
    startpos := startpos + bytesRead;
    obj.readFromSource(ctx,startPos,numBytes,buffer);
    bytesRead := numBytes;
 
    DBMS_OUTPUT.PUT_LINE('start position: '|| startPos);
    DBMS_OUTPUT.PUT_LINE('read ' || bytesRead || ' bytes.');
 
   -- Note: Add your own code here to process the media data being read.
   -- This routine reads the data into the buffer 32767 bytes at a time,
   -- then reads the next chunk, overwriting the first buffer full of data.
 END LOOP;
 EXCEPTION
     WHEN NO_DATA_FOUND THEN
       DBMS_OUTPUT.PUT_LINE('End of data ');
     WHEN ORDSYS.ORDSourceExceptions.METHOD_NOT_SUPPORTED THEN
       DBMS_OUTPUT.PUT_LINE('ORDSourceExceptions.METHOD_NOT_SUPPORTED caught');
     WHEN OTHERS THEN
       DBMS_OUTPUT.PUT_LINE('EXCEPTION caught:' || SQLERRM);
END;
/
show errors
 

To execute the stored procedure, enter the following SQL statements:

SQL> set serveroutput on; 
SQL> execute read_document(1); 

Content length is: 93594
start position: 1
read 32767 bytes.
start position: 32768
read 32767 bytes.
start position: 65535
read 28060 bytes.
End of data

PL/SQL procedure successfully completed.

9.2.1.5 Show the Properties of the Loaded Media Data

The showprop_doc.sql script displays the properties of the media data loaded into the doc_table table. This script is shown in Example 9-14.


Note:

Run this script as the user who ran the previous media scripts.

Example 9-14 showprop_doc.sql Script

-- showprop_doc.sql
--
SET SERVEROUTPUT ON;
 
--
-- Query doc_table for ORDDoc and print the properties using PL/SQL.
--
 
BEGIN
  FOR rec in (SELECT id, document FROM doc_table ORDER BY id) LOOP 
    dbms_output.put_line('document id: '|| rec.id);
    dbms_output.put_line('document MIME type: '|| rec.document.getMimeType());
    dbms_output.put_line('document file format: '|| rec.document.getFormat());
    dbms_output.put_line('BLOB Length: '|| rec.document.getContentLength());
    dbms_output.put_line('----------------------------------------------');
  END loop;
END;
/
 
--
-- Query doc_table for ORDDoc and list the properties using SQL.
--
clear columns
column id    format 99;
column mimetype format a20;
column format   format a10;
column length   format 99999999;
SELECT t.id, 
       t.document.getMimeType() mimetype, 
       t.document.getFormat() format, 
       t.document.getContentLength() length
from doc_table t ORDER BY t.id;

The results from running the script showprop_doc.sql are the following:

SQL> @showprop_doc.sql 

document id: 1
document MIME type: audio/x-wav
document file format: WAVE
BLOB Length: 93594
----------------------------------------------
document id: 2
document MIME type: audio/mpeg
document file format: MPGA
BLOB Length: 51537
----------------------------------------------
 
PL/SQL procedure successfully completed.
 
 
 ID MIMETYPE             FORMAT        LENGTH
--- -------------------- ---------- ---------
  1 audio/x-wav          WAVE           93594
  2 audio/mpeg           MPGA           51537

9.2.1.6 Automate the ORDDoc Examples

The setup_docsample.sql script runs each of the previous media scripts in the correct order to automate this process. This script is shown in Example 9-15.

Before running this script, ensure that you have these privileges:

  • CREATE ANY DIRECTORY

  • CREATE TABLE

Example 9-15 setup_docsample.sql Script

-- setup_docsample.sql
--
 
-- Create the media_dir load directory:
@create_mediadir.sql
 
-- Create the doc_table table:
@create_doctable.sql
 
--Import 2 media clips and set the properties:
@import_doc.sql
 
--Display the properties of the media clips:
@showprop_doc.sql
 
--Create a stored procedure to read from ordDoc:
@read_doc.sql
 
--Execute the stored procedure:
execute read_document(1);
 
--exit;

9.2.1.7 Clean Up the ORDDoc Examples

The cleanup_docsample.sql script removes the sample tables, directories, and procedures created by the previous media scripts from your database. This script is shown in Example 9-16.

Before running this script, ensure that you have the DROP ANY DIRECTORY privilege.


Note:

Run this script as the user who ran the previous media scripts.

Example 9-16 cleanup_docsample.sql Script

-- cleanup_docsample.sql
--
-- Drop the doc load directory.
-- DROP DIRECTORY media_dir;
 
-- Drop the table and procedures created by the demo.
DROP TABLE doc_table PURGE;
DROP PROCEDURE read_document;
DROP PROCEDURE load_document;

exit;

9.3 Image Data Examples

Image data examples using Oracle Multimedia include common operations on image data, such as using a set of scripts for populating an ORDImage object from a file data source, using a set of scripts for loading an image table from an HTTP data source, and addressing issues related to globalization support. The following subsections describe these operations:


See Also:

Oracle Multimedia Reference for reference information about the methods used in these examples


9.3.1 Scripts for Populating an ORDImage Object from a File Data Source

The scripts presented in this section demonstrate how to populate an Oracle Multimedia ORDImage object from an existing file.

Table 9-3 lists each script by name, along with a brief description of the operations it performs. Each script is included and described in further detail in the following sections.

Table 9-3 Image Scripts

Script NameOperations Performed

create_mediadir.sql

(See Example 9-3)

Creates an image data load directory.

(See Section 9.3.1.1)

create_imgtable.sql

(See Example 9-17)

Creates the image_table table.

(See Section 9.3.1.2)

import_img.sql

(See Example 9-18)

Loads the image data. This script imports the image data from a file into the image_table table using the ORDImage import( ) method.

(See Section 9.3.1.3)

read_image.sql

(See Example 9-19)

Reads the image data from a BLOB using a stored procedure.

(See Section 9.3.1.4)

showprop_img.sql

(See Example 9-20)

Displays the properties of the loaded image data stored in the image_table table.

(See Section 9.3.1.5)

setup_imgsample.sql

(See Example 9-21)

Automates the process by running the previous image scripts in the required order.

(See Section 9.3.1.6)

cleanup_imgsample.sql

(See Example 9-22)

Cleans up by removing the sample tables, directories, and procedures from your database.

(See Section 9.3.1.7)


9.3.1.1 Create an Image Data Load Directory

The create_mediadir.sql script creates the image data load directory. This script is shown in Example 9-3.

To load the image data successfully, you must create a database directory object that points to a file directory on your system. Example 9-3 uses the media_dir directory, which points to the file directory C:\media_dir. You can edit the create_mediadir.sql script to replace the directory path in the CREATE OR REPLACE DIRECTORY statement with your directory specification.

This directory specified in the create_mediadir.sql script must contain your sample image files. The image examples use the sample files img71.gif and img50.gif, which are installed in the <ORACLE_HOME>/ord/img/demo directory. You can copy any supported image files to the C:\media_dir directory to run the scripts in these examples.

Before running the create_mediadir.sql script, ensure that you have these privileges:

  • CREATE ANY DIRECTORY (to specify the directory specification for your image files)

  • DROP ANY DIRECTORY (to delete previous instances of the image data load directory)


Note:

If you run the create_mediadir.sql script as a different user than the user who ran the other image scripts, you must perform these steps:
  1. Uncomment the GRANT READ ON DIRECTORY statement.

  2. Replace the string <USER> in this statement with the new user (for example: SCOTT).


9.3.1.2 Create the image_table Table

The create_imgtable.sql script creates the image_table table with the two columns id and image. The image column is defined as type ORDImage. This script is shown in Example 9-17.

Before running this script, ensure that you have the CREATE TABLE privilege.

Example 9-17 create_imgtable.sql Script

-- create_imgtable.sql
--
CREATE TABLE image_table ( id NUMBER,
                           image ORDImage )
LOB(image.source.localData) STORE AS SECUREFILE;

9.3.1.3 Load the Image Data

The import_img.sql script inserts two rows into the image_table table, and imports image data from an image file into the image column in the image_table table using the ORDImage import( ) method. This script is shown in Example 9-18.

To run this script successfully , you must copy two image files to your media_dir directory using the file names specified in this script, or modify this script to match the file names of your image files.


Note:

Run this script as the user who ran the previous image scripts.

Example 9-18 import_img.sql Script

-- import_img.sql
--
CREATE OR REPLACE PROCEDURE load_image(in_id INTEGER,
                                       in_dir VARCHAR2,
                                       in_fname VARCHAR2)
AS
  obj ORDIMAGE;
  ctx RAW(64) := NULL;
BEGIN
  INSERT INTO image_table VALUES
      (in_id, ORDImage('FILE', in_dir, in_fname))
      RETURNING image INTO obj;
  obj.import(ctx);
  UPDATE image_table SET image = obj WHERE id = in_id;
  COMMIT;
END;
/
show errors
 
-- Import the two files into the database.
EXECUTE load_image(1, 'MEDIA_DIR', 'img71.gif');
EXECUTE load_image(2, 'MEDIA_DIR', 'img50.gif');

9.3.1.4 Read the Image Data from the BLOB

The read_image.sql script reads image data from a BLOB by creating the stored procedure read_image. This procedure reads a specified amount of image data from the BLOB attribute, beginning at a particular offset, until all the image data is read. This script is shown in Example 9-19.


Note:

Run this script as the user who ran the previous image scripts.

Example 9-19 read_image.sql Script

-- read_image.sql
--
set serveroutput on
create or replace procedure read_image (in_id integer) as
-- Note: ORDImage has no readFromSource method like ORDAudio
-- and ORDVideo; therefore, you must use the DBMS_LOB package to
-- read image data from a BLOB.
buffer RAW (32767);
src BLOB;
amt integer; 
pos integer := 1;
bytesRead integer := 0;
length integer;
BEGIN
  Select t.image.getcontent(), t.image.getContentLength()
    into src, length from image_table t where t.id = in_id;
  DBMS_OUTPUT.PUT_LINE('Content length is: '|| length);
 
  LOOP
    amt := 32767;
    pos := pos + bytesRead;
    DBMS_LOB.READ(src,amt,pos,buffer);
    bytesRead := amt;
 
    DBMS_OUTPUT.PUT_LINE('start position: '|| pos);
    DBMS_OUTPUT.PUT_LINE('bytes read '|| bytesRead);
-- Note: Add your own code here to process the image data being read.
-- This routine reads data into the buffer 32767 bytes at a time, 
-- then reads the next chunk, overwriting the first buffer full of data.
  END LOOP;
  EXCEPTION
  WHEN NO_DATA_FOUND THEN
    DBMS_OUTPUT.PUT_LINE('----------------');
    DBMS_OUTPUT.PUT_LINE('End of data ');
END;
/
show errors
 

To execute the stored procedure, enter the following SQL statements:

SQL> set serveroutput on;
SQL> execute read_image(1);
Content length is: 1124
start position: 1
bytes read 1124
----------------
End of data

PL/SQL procedure successfully completed.

9.3.1.5 Show the Properties of the Loaded Image Data

The showprop_img.sql script displays the properties of the image data loaded into the image_table table. This script is shown in Example 9-20.


Note:

Run this script as the user who ran the previous image scripts.

Example 9-20 showprop_img.sql Script

-- showprop_img.sql
--
SET SERVEROUTPUT ON;
 
--
-- Display the properties of the images stored in image_table using PL/SQL.
--
 
BEGIN
 
  FOR rec in (SELECT id, image from image_table ORDER BY id) LOOP
    dbms_output.put_line('Image properties:');
    dbms_output.put_line('image id: '|| rec.id);
    dbms_output.put_line('image height: '|| rec.image.getHeight());
    dbms_output.put_line('image width: '|| rec.image.getWidth());
    dbms_output.put_line('image MIME type: '|| rec.image.getMimeType());
    dbms_output.put_line('image file format: '|| rec.image.getFileFormat());
    dbms_output.put_line('BLOB Length: '|| rec.image.getContentLength());
    dbms_output.put_line('-------------------------------------------');
  END loop;
END;
/

--
-- Display the properties of the images stored in image_table using SQL.
--
clear columns
column id        format 99;
column height    format 999999;
column width     format 999999;
column mimetype  format a15;
column fileformat format a10;
column length     format 999999999;
select t.id, 
       t.image.getHeight() height,
       t.image.getWidth() width,
       t.image.getMimetype() mimetype,
       t.image.getFileFormat() fileformat,
       t.image.getContentLength() length
from image_table t ORDER BY t.id;

The results from running the script showprop_img.sql are the following:

SQL> @showprop_img.sql
Image properties:
image id: 1
image height: 15
image width: 43
image MIME type: image/gif
image file format: GIFF
BLOB Length: 1124
-------------------------------------------
Image properties:
image id: 2
image height: 32
image width: 110
image MIME type: image/gif
image file format: GIFF
BLOB Length: 686
-------------------------------------------
 
PL/SQL procedure successfully completed.
 
 
 ID  HEIGHT   WIDTH MIMETYPE        FILEFORMAT     LENGTH
--- ------- ------- --------------- ---------- ----------
  1      15      43 image/gif       GIFF             1124
  2      32     110 image/gif       GIFF              686
 

9.3.1.6 Automate the ORDImage Examples

The setup_imgsample.sql script runs each of the previous image scripts in the correct order to automate this process. This script is shown in Example 9-21.

Before running this script, ensure that you have these privileges:

  • CREATE ANY DIRECTORY

  • CREATE TABLE

Example 9-21 setup_imgsample.sql Script

-- setup_imgsample.sql
--
 
--Create the media_dir load directory:
@create_mediadir.sql
 
--Create the image_table table:
@create_imgtable.sql
 
--Import images into the image_table table:
@import_img.sql
 
--Show the properties of the images:
@showprop_img.sql
 
--Create a stored procedure to read from ordImage:
@read_image.sql
 
--Execute the stored procedure:
execute read_image(1);
 
--exit;

9.3.1.7 Clean Up the ORDImage Examples

The cleanup_imgsample.sql script removes the sample tables, directories, and procedu~res created by the previous image scripts from your database. This script is shown in Example 9-22.

Before running this script, ensure that you have the DROP ANY DIRECTORY privilege.


Note:

Run this script as the user who ran the previous image scripts.

Example 9-22 cleanup_imgsample.sql Script

-- cleanup_imgsample.sql
--
-- Drop the image load directory.
DROP DIRECTORY media_dir;
 
-- Drop the tables created by the demo.
DROP TABLE image_table PURGE;
 
-- Drop the procedures.
DROP PROCEDURE read_image;
DROP PROCEDURE load_image;
 
exit;

9.3.2 Loading an Image Table from an HTTP Data Source

The import_imghttp.sql script imports the image data from an HTTP data source. This script inserts two rows into the image_table table and loads the image data from the specified HTTP data source (source type HTTP, URL location, and HTTP object name). This script is shown in Example 9-23.

To run this script successfully, you must modify it to point to two images located on your Web site, as described in Example 9-23.

Example 9-23 Import Image Data from an HTTP Data Source

-- import_imghttp.sql
--
-- Import the two HTTP images from a Web site into the database.
-- Prerequisites
--    Follow these steps before running this script:
--        1. Run create_imgdir.sql.
--        2. Run create_imgtable.sql.
--        3. Modify the HTTP URL and object name to point to two images on 
--           your Web site.

-- Insert two rows with an empty BLOB.
 
insert into image_table values (7,ORDImage(
'http','http://your_website/images','image1.jpg'));
 
insert into image_table values (8,ORDImage(
'http','http://your_website/images','image2.gif'));
 
commit;
 
DECLARE 
  obj ORDSYS.ORDIMAGE;
  ctx RAW(64) := NULL;
BEGIN
-- This imports the image file image1.gif from the HTTP source URL 
-- (srcType=HTTP), and automatically sets the properties.
 
  select Image into obj from image_table where id = 7 for update;
    obj.import(ctx);
 
  update image_table set image = obj where id = 7;
  commit;
 
-- This imports the image file image2.gif from the HTTP source URL
-- (srcType=HTTP), and automatically sets the properties.
 
  select Image into obj from image_table where id = 8 for update;
    obj.import(ctx);
 
  update image_table set image = obj where id = 8;
  commit;
END;
/

9.3.3 Addressing Globalization Support Issues

The globalization.sql script demonstrates how to address issues related to globalization support. It shows how to use the process( ) method with language settings that use the comma as the decimal point. For example, when the territory is FRANCE, the decimal point is expected to be a comma. Thus,",75" is specified as the scale factor. This script is shown in Example 9-24.

Example 9-24 Address a Globalization Support Issue

-- globalization.sql
--
ALTER SESSION SET NLS_LANGUAGE = FRENCH;
ALTER SESSION SET NLS_TERRITORY = FRANCE;
DECLARE
myimage ORDImage;
BEGIN
 
SELECT image into myimage from image_table where id=1 for update;
myimage.process('scale=",75"');
UPDATE image_table SET image = myimage where id=1;
COMMIT;
END;
/

Run the showprop_img.sql script (Example 9-20) to see the properties of the scaled image.

See Oracle Multimedia Reference for more information about ensuring the correct globalization support interpretation when using the process( ) method.

9.4 Video Data Examples

Video data examples using Oracle Multimedia are not available in this chapter.


See Also:

Oracle Multimedia Reference for reference information and video data examples


PK՝ ~PK"+AOEBPS/ch_extend.htm Extending Oracle Multimedia

7 Extending Oracle Multimedia

Oracle Multimedia can be extended to support:

  • Other external sources of media data not currently supported

  • Other media data formats not currently supported

  • A new object type

  • Media (audio and video) data processing

For each unique external media data source or each unique ORDAudio, ORDDoc, or ORDVideo data format you want to support, you must:

  1. Design your new data source or new ORDAudio, ORDDoc, or ORDVideo data format.

  2. Implement your new data source or new ORDAudio, ORDDoc, or ORDVideo data format.

  3. Install your new plug-in into the ORDPLUGINS schema.

  4. Grant EXECUTE privileges on your new plug-in to PUBLIC.

This chapter includes these sections:

7.1 Supporting Other External Sources

To implement your new data source, you must implement the required interfaces in the ORDX_<srcType>_SOURCE package in the ORDPLUGINS schema (where <srcType> represents the name of the new external source type). Use the package body example in Section 7.1.1.3 as a template to create the package body. Then, set the source type parameter in the setSourceInformation( ) call to the appropriate source value to indicate to the ORDAudio, ORDImage, ORDDoc, or ORDVideo object that package ORDPLUGINS.ORDX_<srcType>_SOURCE is available as a plug-in. Use the ORDPLUGINS.ORDX_FILE_SOURCE and ORDPLUGINS.ORDX_HTTP_SOURCE packages as guides when you extend support to other external audio, image, video, or other heterogeneous media data sources.

The following subsection presents reference information on the packages or PL/SQL plug-ins provided:

7.1.1 Packages or PL/SQL Plug-ins

Plug-ins must be named as ORDX_<name>_<module_name> where the <module_name> is SOURCE for ORDSource. For example, the FILE plug-in described in Section 7.1.1.1 is named ORDX_FILE_SOURCE and the HTTP plug-in described in Section 7.1.1.2 is named ORDX_HTTP_SOURCE and <name> is the source type. Both source type names, FILE and HTTP, are reserved to Oracle.

Use the ORDPLUGINS.ORDX_FILE_SOURCE and ORDPLUGINS.ORDX_HTTP_SOURCE packages as a guide in developing your new source type package.

The following subsections provide examples and more information about extending the supported external sources of audio, image, video, or other heterogeneous media data:

7.1.1.1 ORDPLUGINS.ORDX_FILE_SOURCE Package

The ORDPLUGINS.ORDX_FILE_SOURCE package or PL/SQL plug-in provides support for multimedia stored in the local file system external to the database.

CREATE OR REPLACE PACKAGE ORDX_FILE_SOURCE AS
  -- functions/procedures
  FUNCTION processCommand(obj     IN OUT NOCOPY ORDSYS.ORDSource,
                          ctx     IN OUT RAW,
                          cmd     IN VARCHAR2,
                          arglist IN VARCHAR2,
                          result  OUT RAW)
           RETURN RAW;
  PROCEDURE import(obj      IN OUT NOCOPY ORDSYS.ORDSource,
                   ctx      IN OUT RAW,
                   mimetype OUT VARCHAR2,
                   format   OUT VARCHAR2);
  PROCEDURE import(obj      IN OUT NOCOPY ORDSYS.ORDSource,
                   ctx      IN OUT RAW,
                   dlob     IN OUT NOCOPY BLOB,
                   mimetype OUT VARCHAR2,
                   format   OUT VARCHAR2);
  PROCEDURE importFrom(obj      IN OUT NOCOPY ORDSYS.ORDSource,
                       ctx      IN OUT RAW,
                       mimetype OUT VARCHAR2,
                       format   OUT VARCHAR2,
                       loc      IN VARCHAR2,
                       name     IN VARCHAR2);
  PROCEDURE importFrom(obj      IN OUT NOCOPY ORDSYS.ORDSource,
                       ctx      IN OUT RAW,
                       dlob     IN OUT NOCOPY BLOB,
                       mimetype OUT VARCHAR2,
                       format   OUT VARCHAR2,
                       loc      IN VARCHAR2,
                       name     IN VARCHAR2);
  PROCEDURE export(obj  IN OUT NOCOPY ORDSYS.ORDSource,
                   ctx  IN OUT RAW,
                   slob IN OUT NOCOPY BLOB,
                   loc  IN VARCHAR2,
                   name IN VARCHAR2);
  FUNCTION  getContentLength(obj  IN ORDSYS.ORDSource,
                             ctx  IN OUT RAW),
            RETURN INTEGER;
  PRAGMA RESTRICT_REFERENCES(getContentLength, WNDS, WNPS, RNDS, RNPS);
  FUNCTION  getSourceAddress(obj  IN ORDSYS.ORDSource,
                             ctx  IN OUT RAW,
                             userData IN VARCHAR2)
            RETURN VARCHAR2;
  PRAGMA RESTRICT_REFERENCES(getSourceAddress, WNDS, WNPS, RNDS, RNPS);
  
  FUNCTION open(obj IN OUT NOCOPY ORDSYS.ORDSource, 
           userArg IN RAW, 
           ctx OUT RAW) RETURN INTEGER;
  FUNCTION close(obj IN OUT NOCOPY ORDSYS.ORDSource, ctx IN OUT RAW) 
         RETURN INTEGER;
  FUNCTION trim(obj IN OUT NOCOPY ORDSYS.ORDSource, 
                ctx IN OUT RAW,
                newlen IN INTEGER) RETURN INTEGER;
PROCEDURE read(obj     IN OUT NOCOPY ORDSYS.ORDSource,
               ctx      IN OUT RAW,
               startPos IN INTEGER,
               numBytes IN OUT INTEGER,
               buffer   OUT RAW);
PROCEDURE write(obj      IN OUT NOCOPY ORDSYS.ORDSource,
                ctx      IN OUT RAW,
                startPos IN INTEGER,
                numBytes IN OUT INTEGER,
                buffer   OUT RAW);
END ORDX_FILE_SOURCE;
/

Table 7-1 shows the methods supported in the ORDX_FILE_SOURCE package and the exceptions raised if you call a method that is not supported.

Table 7-1 Methods Supported in the ORDPLUGINS.ORDX_FILE_SOURCE Package

Name of MethodLevel of Support

processCommand

Not supported - raises exception: METHOD_NOT_SUPPORTED

import

Supported

import

Supported

importFrom

Supported

importFrom

Supported

export

Supported

getContentLength

Supported

getSourceAddress

Supported

open

Supported

close

Supported

trim

Not supported - raises exception: METHOD_NOT_SUPPORTED

read

Supported

write

Not supported - raises exception: METHOD_NOT_SUPPORTED


7.1.1.2 ORDPLUGINS.ORDX_HTTP_SOURCE Package

The ORDPLUGINS.ORDX_HTTP_SOURCE package or PL/SQL plug-in provides support for multimedia stored in any HTTP server and accessed through a URL.

CREATE OR REPLACE PACKAGE ORDX_HTTP_SOURCE AS
  -- functions/procedures
  FUNCTION processCommand(obj     IN OUT NOCOPY ORDSYS.ORDSource,
                          ctx     IN OUT RAW,
                          cmd     IN VARCHAR2,
                          arglist IN VARCHAR2,
                          result  OUT RAW)
           RETURN RAW;
  PROCEDURE import(obj      IN OUT NOCOPY ORDSYS.ORDSource,
                   ctx      IN OUT RAW,
                   mimetype OUT VARCHAR2,
                   format   OUT VARCHAR2);
  PROCEDURE import(obj      IN OUT NOCOPY ORDSYS.ORDSource,
                   ctx      IN OUT RAW,
                   dlob     IN OUT NOCOPY BLOB,
                   mimetype OUT VARCHAR2,
                   format   OUT VARCHAR2);
  PROCEDURE importFrom(obj      IN OUT NOCOPY ORDSYS.ORDSource,
                       ctx      IN OUT RAW,
                       mimetype OUT VARCHAR2,
                       format   OUT VARCHAR2,
                       loc      IN VARCHAR2,
                       name     IN VARCHAR2);
  PROCEDURE importFrom(obj      IN OUT NOCOPY ORDSYS.ORDSource,
                       ctx      IN OUT RAW,
                       dlob     IN OUT NOCOPY BLOB,
                       mimetype OUT VARCHAR2,
                       format   OUT VARCHAR2,
                       loc      IN VARCHAR2,
                       name     IN VARCHAR2);
  PROCEDURE export(obj  IN OUT NOCOPY ORDSYS.ORDSource,
                   ctx  IN OUT RAW,
                   dlob IN OUT NOCOPY BLOB,
                   loc  IN VARCHAR2,
                   name IN VARCHAR2);
  FUNCTION  getContentLength(obj  IN ORDSYS.ORDSource,
                             ctx  IN OUT RAW)
            RETURN INTEGER;
  PRAGMA RESTRICT_REFERENCES(getContentLength, WNDS, WNPS, RNDS, RNPS, TRUST);
  FUNCTION  getSourceAddress(obj  IN ORDSYS.ORDSource,
                             ctx  IN OUT RAW,
                             userData IN VARCHAR2) 
            RETURN VARCHAR2;
  PRAGMA RESTRICT_REFERENCES(getSourceAddress, WNDS, WNPS, RNDS, RNPS);
  FUNCTION open(obj IN OUT NOCOPY ORDSYS.ORDSource, userArg IN RAW,
           ctx OUT RAW) RETURN INTEGER;
  FUNCTION close(obj IN OUT NOCOPY ORDSYS.ORDSource, ctx IN OUT RAW) 
           RETURN INTEGER;
  FUNCTION trim(obj IN OUT NOCOPY ORDSYS.ORDSource, 
           ctx IN OUT RAW,
           newlen IN INTEGER) RETURN INTEGER;
  PROCEDURE read(obj      IN OUT NOCOPY ORDSYS.ORDSource,
                 ctx      IN OUT RAW,
                 startPos IN INTEGER,
                 numBytes IN OUT INTEGER,
                 buffer   OUT RAW);
  PROCEDURE write(obj      IN OUT NOCOPY ORDSYS.ORDSource,
                  ctx      IN OUT RAW,
                  startPos IN INTEGER,
                  numBytes IN OUT INTEGER,
                  buffer   OUT RAW);
END ORDX_HTTP_SOURCE;
/

Table 7-2 shows the methods supported in the ORDX_HTTP_SOURCE package and the exceptions raised if you call a method that is not supported.

Table 7-2 Methods Supported in the ORDPLUGINS.ORDX_HTTP_SOURCE Package

Name of MethodLevel of Support

processCommand

Not supported - raises exception: METHOD_NOT_SUPPORTED

import

Supported

import

Supported

importFrom

Supported

importFrom

Supported

export

Not supported - raises exception: METHOD_NOT_SUPPORTED

getContentLength

Supported

getSourceAddress

Supported

open

Supported

close

Supported

trim

Not supported - raises exception: METHOD_NOT_SUPPORTED

read

Not supported - raises exception: METHOD_NOT_SUPPORTED

write

Not supported - raises exception: METHOD_NOT_SUPPORTED


7.1.1.3 Extending Oracle Multimedia to Support a New Data Source

Extending Oracle Multimedia to support a new data source consists of these steps:

  1. Design your new data source.

  2. Implement your new data source and name it, for example, ORDX_MY_SOURCE.SQL.

  3. Install your new ORDX_MY_SOURCE.SQL plug-in into the ORDPLUGINS schema.

  4. Grant EXECUTE privileges on your new plug-in, for example, ORDX_MY_SOURCE.SQL plug-in to PUBLIC.

  5. Set the srctype to my to cause your plug-in to be invoked.

A package body listing is provided in Example 7-1 to assist you in this operation. Add your variables to the places that say "--Your variables go here" and add your code to the places that say "--Your code goes here".

Example 7-1 Package Body for Extending Support to a New Data Source

CREATE OR REPLACE PACKAGE BODY ORDX_MY_SOURCE
AS
  -- functions/procedures
  FUNCTION processCommand(
                    obj  IN OUT NOCOPY ORDSYS.ORDSource,
                    ctx  IN OUT RAW,
                    cmd  IN VARCHAR2,
                    arglist IN VARCHAR2,
                    result OUT RAW)
  RETURN RAW
  IS
   --Your variables go here.
  BEGIN
  --Your code goes here.
  END processCommand;
  PROCEDURE import( obj  IN OUT NOCOPY ORDSYS.ORDSource,
                    ctx  IN OUT RAW,
                    mimetype OUT VARCHAR2,
                    format   OUT VARCHAR2)
  IS
  --Your variables go here.
  BEGIN
  --Your code goes here.
  END import;
  PROCEDURE import( obj  IN OUT NOCOPY ORDSYS.ORDSource,
                    ctx  IN OUT RAW,
                    dlob IN OUT NOCOPY BLOB,
                    mimetype OUT VARCHAR2,
                    format   OUT VARCHAR2)
  IS
  --Your variables go here.
  BEGIN
  --Your code goes here.
  END import;
  PROCEDURE importFrom( obj      IN OUT NOCOPY ORDSYS.ORDSource,
                        ctx      IN OUT RAW,
                        mimetype OUT VARCHAR2,
                        format   OUT VARCHAR2,
                        loc      IN VARCHAR2,
                        name     IN VARCHAR2)
  IS
  --Your variables go here.
  BEGIN
  --Your code goes here.
  END importFrom;
  PROCEDURE importFrom( obj      IN OUT NOCOPY ORDSYS.ORDSource,
                        ctx      IN OUT RAW,
                        dlob     IN OUT NOCOPY BLOB,
                        mimetype OUT VARCHAR2,
                        format   OUT VARCHAR2,
                        loc      IN VARCHAR2,
                        name     IN VARCHAR2)
  IS
  --Your variables go here.
  BEGIN
  --Your code goes here.
  END importFrom;
  PROCEDURE export( obj  IN OUT NOCOPY ORDSYS.ORDSource,
                    ctx  IN OUT RAW,
                    slob IN OUT NOCOPY BLOB,
                    loc  IN VARCHAR2,
                    name IN VARCHAR2)
  IS
  --Your variables go here.
  BEGIN
  --Your code goes here.
  END export;
  
  FUNCTION  getContentLength( obj  IN ORDSYS.ORDSource,
                              ctx  IN OUT RAW)
  RETURN INTEGER
  IS
  --Your variables go here.
  BEGIN
  --Your code goes here.
  END getContentLength;
  FUNCTION  getSourceAddress(obj  IN ORDSYS.ORDSource,
                             ctx  IN OUT RAW,
                             userData IN VARCHAR2)
  RETURN VARCHAR2
  IS
  --Your variables go here.
  BEGIN
  --Your code goes here.
  END getSourceAddress;
  FUNCTION open(obj IN OUT NOCOPY ORDSYS.ORDSource, userArg IN RAW, ctx OUT RAW)
  RETURN INTEGER
  IS
  --Your variables go here.
  BEGIN
  --Your code goes here.
  END open;
  FUNCTION close(obj IN OUT NOCOPY ORDSYS.ORDSource, ctx IN OUT RAW)
  RETURN INTEGER
  IS
  --Your variables go here.
  BEGIN
  --Your code goes here.
  END close;
  FUNCTION trim(obj    IN OUT NOCOPY ORDSYS.ORDSource,
                       ctx    IN OUT RAW,
                       newlen IN INTEGER)
  RETURN INTEGER
  IS
  --Your variables go here.
  BEGIN
  --Your code goes here.
  END trim;
  PROCEDURE read(obj      IN OUT NOCOPY ORDSYS.ORDSource,
                 ctx      IN OUT RAW,
                 startPos IN INTEGER,
                 numBytes IN OUT INTEGER,
                 buffer   OUT RAW)
  IS
  --Your variables go here.
  BEGIN
  --Your code goes here.
  END read;
  PROCEDURE write(obj      IN OUT NOCOPY ORDSYS.ORDSource,
                  ctx      IN OUT RAW,
                  startPos IN INTEGER,
                  numBytes IN OUT INTEGER,
                  buffer   OUT RAW)
  IS
  --Your variables go here.
  BEGIN
  --Your code goes here.
  END write;
END ORDX_MY_SOURCE;
/
show errors;

7.2 Supporting Other Media Data Formats

To implement your new ORDAudio, ORDDoc, or ORDVideo data format, you must implement the required interfaces in the ORDPLUGINS.ORDX_<format>_<media> package in the ORDPLUGINS schema (where <format> represents the name of the new audio or video, or other heterogeneous media data format and <media> represents the type of media ("AUDIO" or "VIDEO", or "DOC"). Use the ORDPLUGINS.ORDX_DEFAULT_<media> package as a guide when you extend support to other audio or video data formats or other heterogeneous media data formats. Use the package body examples in Section 7.2.1.2, Section 7.2.2.2, and Section 7.2.3.2 as templates to create the audio or video, or other heterogeneous media data package body, respectively. Then, set the new format parameter in the setFormat( ) call to the appropriate format value to indicate to the ORDAudio, ORDDoc, or ORDVideo object that package ORDPLUGINS.ORDX_<format>_<media> is available as a plug-in, and that it must be used for method invocation.

The following subsections describe how to extend Oracle Multimedia to support other data formats:

7.2.1 Supporting Other ORDAudio Data Formats

The following subsections describe how to extend ORDAudio to support other data formats:

7.2.1.1 ORDPLUGINS.ORDX_DEFAULT_AUDIO Package

Use the following ORDPLUGINS.ORDX_DEFAULT_AUDIO package provided as a guide in developing your own ORDPLUGINS.ORDX_<format>_AUDIO audio format package. This package sets the mimeType field in the setProperties( ) method with a MIME type value that is dependent on the file format.

CREATE OR REPLACE PACKAGE ORDX_DEFAULT_AUDIO
authid current_user
AS 
--AUDIO ATTRIBUTES ACCESSORS

PROCEDURE setProperties(ctx IN OUT RAW, 
                        obj IN OUT NOCOPY ORDSYS.ORDAudio,
                        setComments IN NUMBER := 0);
FUNCTION checkProperties(ctx IN OUT RAW, obj IN OUT ORDSYS.ORDAudio)
                RETURN NUMBER;
FUNCTION getAttribute(ctx IN OUT RAW,
                      obj IN ORDSYS.ORDAudio,
                      name IN VARCHAR2) RETURN VARCHAR2;
PROCEDURE getAllAttributes(ctx IN OUT RAW, 
                           obj IN ORDSYS.ORDAudio, 
                           attributes IN OUT NOCOPY CLOB);
--AUDIO PROCESSING METHODS
FUNCTION processCommand(ctx       IN OUT RAW,
                        obj       IN OUT NOCOPY ORDSYS.ORDAudio,
                        cmd       IN VARCHAR2,
                        arguments IN VARHAR2,
                        result    OUT RAW)
         RETURN RAW;

END;
/

Table 7-3 shows the methods supported in the ORDPLUGINS.ORDX_DEFAULT_AUDIO package and the exceptions raised if you call a method that is not supported.

Table 7-3 Methods Supported in the ORDPLUGINS.ORDX_DEFAULT_AUDIO Package

Name of MethodLevel of Support

setProperties

Supported; if the source is local, extract attributes from the local data and set the properties, but if the source is NULL, raise an ORDSYS.ORDSourceExceptions.EMPTY_SOURCE exception; if the source is a BFILE, then extract attributes from the BFILE and set the properties; if the source is neither local nor a BFILE, get the media content into a temporary LOB, extract attributes from the data, and set the properties.

checkProperties

Supported; if the source is local, extract the attributes from the local data and compare them with the attribute values of the object, but if the source is NULL, raise an ORDSYS.ORDSourceExceptions.EMPTY_SOURCE exception; if the source is a BFILE, extract the attributes from the BFILE and compare them with the attribute values of the object; if the source is neither local nor a BFILE, get the media content into a temporary LOB, extract the attributes from the media content and compare them with the attribute values of the object.

getAttribute

Not supported - raises exceptions: METHOD_NOT_SUPPORTED and AUDIO_PLUGIN_EXCEPTION.

getAllAttributes

Supported; if the source is local, get the attributes and return them, but if the source is NULL, raise an ORDSYS.ORDSourceExceptions.EMPTY_SOURCE exception; otherwise, if the source is external, raise an ORDSYS.ORDAudioExceptions.LOCAL_DATA_SOURCE_REQUIRED exception.

processCommand

Not supported - raises exceptions: METHOD_NOT_SUPPORTED and AUDIO_PLUGIN_EXCEPTION.


7.2.1.2 Extending Oracle Multimedia to Support a New Audio Data Format

Extending Oracle Multimedia to support a new audio data format consists of the following steps:

  1. Design your new audio data format.

    1. To support a new audio data format, implement the required interfaces in the ORDX_<format>_AUDIO package in the ORDPLUGINS schema (where <format> represents the name of the new audio data format). See Section 7.2.1.1 for a complete description of the interfaces for the ORDX_DEFAULT_AUDIO package. Use the package W]body example in Example 7-2 as a template to create the audio package body.

    2. Then, set the new format parameter in the setFormat( ) call to the appropriate format value to indicate to the audio object that package ORDPLUGINS.ORDX_<format>_AUDIO is available as a plug-in.

  2. Implement your new audio data format and name it, for example, ORDX_MY_AUDIO.SQL.

  3. Install your new ORDX_MY_AUDIO.SQL plug-in into the ORDPLUGINS schema.

  4. Grant EXECUTE privileges on your new plug-in, for example, ORDX_MY_AUDIO plug-in, to PUBLIC.

  5. In an application, set the format attribute to my to cause your plug-in to be invoked.

A package body listing is provided in Example 7-2 to assist you in this operation. Add your variables to the places that say "--Your variables go here" and add your code to the places that say "--Your code goes here".

Example 7-2 Package Body for Extending Support to a New Audio Data Format

CREATE OR REPLACE PACKAGE BODY ORDX_MY_AUDIO
AS
  --AUDIO ATTRIBUTES ACCESSORS
  PROCEDURE setProperties(ctx IN OUT RAW,
                          obj IN OUT NOCOPY ORDSYS.ORDAudio,
                          setComments IN NUMBER :=0)
  IS
--Your variables go here.
  BEGIN
--Your code goes here.
  END;
  FUNCTION checkProperties(ctx IN OUT RAW, obj IN OUT ORDSYS.ORDAudio)
  RETURN NUMBER
  IS
--Your variables go here.
  BEGIN
--Your code goes here.
  END;
  FUNCTION  getAttribute(ctx IN OUT RAW,
                         obj IN ORDSYS.ORDAudio,
                         name IN VARCHAR2)
  RETURN VARCHAR2
  IS
--Your variables go here.
  BEGIN
--Your code goes here.
  END;
  PROCEDURE getAllAttributes(ctx IN OUT RAW,
                             obj IN ORDSYS.ORDAudio,
                             attributes IN OUT NOCOPY CLOB)
  IS
--Your variables go here.
  BEGIN
--Your code goes here.
  END;
  -- AUDIO PROCESSING METHODS
  FUNCTION  processCommand(
                                 ctx       IN OUT RAW,
                                 obj       IN OUT NOCOPY ORDSYS.ORDAudio,
                                 cmd       IN VARCHAR2,
                                 arguments IN VARCHAR2,
                                 result    OUT RAW)
  RETURN RAW
  IS
--Your variables go here.
  BEGIN
--Your code goes here.
  END;
END;
/
show errors;

7.2.2 Supporting Other ORDDoc Data Formats

The following subsections describe how to extend ORDDoc to support other data formats:

7.2.2.1 ORDPLUGINS.ORDX_DEFAULT_DOC Package

Use the following ORDPLUGINS.ORDX_DEFAULT_DOC package provided as a guide in developing your own ORDPLUGINS.ORDX_<format>_DOC media format package.

CREATE OR REPLACE PACKAGE ORDX_DEFAULT_DOC
authid current_user
AS 

PROCEDURE setProperties(ctx IN OUT RAW, 
                        obj IN OUT NOCOPY ORDSYS.ORDDoc,
                        setComments IN NUMBER := 0);

END;
/

Table 7-4 shows the method supported in the ORDPLUGINS.ORDX_DEFAULT_DOC package and the exception raised if the source is NULL.

Table 7-4 Method Supported in the ORDPLUGINS.ORDX_DEFAULT_DOC Package

Name of MethodLevel of Support

setProperties

Supported; if the source is local, extract attributes from the local data and set the properties, but if the source is NULL, raise an ORDSYS.ORDSourceExceptions.EMPTY_SOURCE exception; if the source is a BFILE, then extract attributes from the BFILE and set the properties; if the source is neither local nor a BFILE, get the media content into a temporary LOB, extract attributes from the data, and set the properties.


7.2.2.2 Extending Oracle Multimedia to Support a New ORDDoc Data Format

Extending Oracle Multimedia to support a new ORDDoc data format consists of the following steps:

  1. Design your new media data format.

    1. To support a new media data format, implement the required interfaces in the ORDX_<format>_DOC package in the ORDPLUGINS schema (where <format> represents the name of the new media data format). See Section 7.2.2.1 for a complete description of the interfaces for the ORDX_DEFAULT_DOC package. Use the package body example in Example 7-3 as a template to create the package body.

    2. Then, set the new format parameter in the setFormat( ) call to the appropriate format value to indicate to the media object that package ORDPLUGINS.ORDX_<format>_DOC is available as a plug-in.

  2. Implement your new media data format and name it, for example, ORDX_MY_DOC.SQL.

  3. Install your new ORDX_MY_DOC.SQL plug-in into the ORDPLUGINS schema.

  4. Grant EXECUTE privileges on your new plug-in, for example, ORDX_MY_DOC plug-in, to PUBLIC.

  5. In an application, set the format to my to cause your plug-in to be invoked.

A package body listing is provided in Example 7-3 to assist you in this operation. Add your variables to the places that say "--Your variables go here" and add your code to the places that say "--Your code goes here".

Example 7-3 Package Body for Extending Support to a New ORDDoc Data Format

CREATE OR REPLACE PACKAGE BODY ORDX_MY_DOC
AS
  --DOCUMENT ATTRIBUTES ACCESSORS
  PROCEDURE setProperties(ctx IN OUT RAW,
                          obj IN OUT NOCOPY ORDSYS.ORDDoc,
                          setComments IN NUMBER :=0)
  IS
--Your variables go here.
  BEGIN
--Your code goes here.
  END;
END;
/
show errors;

7.2.3 Supporting Other Video Data Formats

The following subsections describe how to extend ORDVideo to support other data formats:

7.2.3.1 ORDPLUGINS.ORDX_DEFAULT_VIDEO Package

Use the following ORDPLUGINS.ORDX_DEFAULT_VIDEO package provided as a guide in developing your own ORDPLUGINS.ORDX_<format>_VIDEO video format package. This package sets the mimeType field in the setProperties( ) method with a MIME type value that is dependent on the file format.

CREATE OR REPLACE PACKAGE ORDX_DEFAULT_VIDEO
authid current_user
AS
--VIDEO ATTRIBUTES ACCESSORS
FUNCTION  getAttribute(ctx IN OUT RAW,
                       obj IN ORDSYS.ORDVideo,
                       name IN VARCHAR2) 
          RETURN VARCHAR2;
PROCEDURE setProperties(ctx IN OUT RAW, 
                        obj IN OUT NOCOPY ORDSYS.ORDVideo,
                        setComments IN NUMBER := 0);
FUNCTION checkProperties(ctx IN OUT RAW,obj IN ORDSYS.ORDVideo) RETURN NUMBER;

-- must return name=value; name=value; ...  pairs
PROCEDURE getAllAttributes(ctx IN OUT RAW,
                           obj IN ORDSYS.ORDVideo,
                           attributes IN OUT NOCOPY CLOB);
-- VIDEO PROCESSING METHODS
FUNCTION  processCommand(
                         ctx       IN OUT RAW,
                         obj       IN OUT NOCOPY ORDSYS.ORDVideo,
                         cmd       IN VARCHAR2,
                         arguments IN VARCHAR2,
                         result    OUT RAW)
         RETURN RAW;

END;
/

Table 7-5 shows the methods supported in the ORDPLUGINS.ORDX_DEFAULT_VIDEO package and the exceptions raised if you call a method that is not supported.

Table 7-5 Methods Supported in the ORDPLUGINS.ORDX_DEFAULT_VIDEO Package

Name of MethodLevel of Support

getAttribute

Not supported - raises exceptions: METHOD_NOT_SUPPORTED and VIDEO_PLUGIN_EXCEPTION

setProperties

Supported; if the source is local, extract attributes from the local data and set the properties, but if the source is NULL, raise an ORDSYS.ORDSourceExceptions.EMPTY_SOURCE exception; if the source is a BFILE, then extract attributes from the BFILE and set the properties; if the source is neither local nor a BFILE, get the media content into a temporary LOB, extract attributes from the data, and set the properties.

checkProperties

Supported; if the source is local, extract attributes from the local data and compare them with the attribute values of the object, but if the source is NULL, raise an ORDSYS.ORDSourceExceptions.EMPTY_SOURCE exception; if the source is a BFILE, then extract attributes from the BFILE data and compare them with the attribute values of the object; if the source is neither local nor a BFILE, get the media content into a temporary LOB, extract attributes from the media content and compare them with the attribute values of the object.

getAllAttributes

Supported; if the source is local, get the attributes and return them, but if the source is NULL, raise an ORDSYS.ORDSourceExceptions.EMPTY_SOURCE exception; otherwise, if the source is external, raise an ORDSYS.ORDVideoExceptions.LOCAL_DATA_SOURCE_REQUIRED exception.

processCommand

Not supported - raises exceptions: METHOD_NOT_SUPPORTED and VIDEO_PLUGIN_EXCEPTION


7.2.3.2 Extending Oracle Multimedia to Support a New Video Data Format

Extending Oracle Multimedia to support a new video data format consists of the following steps:

  1. Design your new video data format.

    1. To support a new video data format, implement the required interfaces in the ORDX_<format>_VIDEO package in the ORDPLUGINS schema (where <format> represents the name of the new video data format). See Section 7.2.3.1 for a complete description of the interfaces for the ORDX_DEFAULT_VIDEO package. Use the package body example in Example 7-4 as a template to create the video package body.

    2. Then, set the new format parameter in the setFormat( ) call to the appropriate format value to indicate to the video object that package ORDPLUGINS.ORDX_<format>_VIDEO is available as a plug-in.

  2. Implement your new video data format and name it, for example, ORDX_MY_VIDEO.SQL.

  3. Install your new ORDX_MY_VIDEO.SQL plug-in into the ORDPLUGINS schema.

  4. Grant EXECUTE privileges on your new plug-in, for example, ORDX_MY_VIDEO plug-in, to PUBLIC.

  5. In an application, set the video format to my to cause your plug-in to be invoked.

A package body listing is provided in Example 7-4 to assist you in this operation. Add your variables to the places that say "--Your variables go here" and add your code to the places that say "--Your code goes here".

Example 7-4 Package Body for Extending Support to a New Video Data Format

CREATE OR REPLACE PACKAGE BODY ORDX_MY_VIDEO
AS
  --VIDEO ATTRIBUTES ACCESSORS
  FUNCTION  getAttribute(ctx IN OUT RAW,
                         obj IN ORDSYS.ORDVideo,
                         name IN VARCHAR2)
  RETURN VARCHAR2
  IS
--Your variables go here.
  BEGIN
--Your code goes here.
  END;
  PROCEDURE setProperties(ctx IN OUT RAW, 
          obj IN OUT NOCOPY ORDSYS.ORDVideo,
          setComments IN NUMBER :=0)
  IS
--Your variables go here.
  BEGIN
--Your code goes here.
  END;
  FUNCTION checkProperties(ctx IN OUT RAW, obj IN ORDSYS.ORDVideo) RETURN NUMBER
  IS
--Your variables go here.
  BEGIN
--Your code goes here.
  END;
  PROCEDURE getAllAttributes(ctx IN OUT RAW,
                             obj IN ORDSYS.ORDVideo,
                             attributes IN OUT NOCOPY CLOB)
  IS
--Your variables go here.
  BEGIN
--Your code goes here.
  END;
  -- VIDEO PROCESSING METHODS
  FUNCTION  processCommand(
                                 ctx       IN OUT RAW,
                                 obj       IN OUT NOCOPY ORDSYS.ORDVideo,
                                 cmd       IN VARCHAR2,
                                 arguments IN VARCHAR2,
                                 result OUT RAW)
  RETURN RAW
  IS
--Your variables go here.
  BEGIN
--Your code goes here.
  END;
END;
/
show errors;

7.2.4 Supporting Other Image Data Formats

Oracle Multimedia supports certain other image formats through the setProperties( ) method for foreign images. This method enables other image formats to be recognized by writing the values supplied to the setProperties( ) method for foreign images to the existing ORDImage data attributes.


See Also:

The setProperties( ) for foreign images method inOracle Multimedia Reference for more information, and to determine the type of images that are supported this way


7.3 Extending Oracle Multimedia with a New Type

You can use any of the Oracle Multimedia objects types as the basis for a new type of your own creation as shown in Example 7-5 for the ORDImage object type.


Note:

When a type is altered, any dependent type definitions are invalidated. You will encounter this problem if you define a new type that includes an Oracle Multimedia object type attribute and the Oracle Multimedia object type is altered, which always occurs during an Oracle Multimedia installation upgrade.

A workaround to this problem is to revalidate all invalid type definitions with the following SQL statement:

SQL> ALTER TYPE <type-name> COMPILE;

Example 7-5 Extend Oracle Multimedia ORDImage with a New Object Type

CREATE TYPE AnnotatedImage AS OBJECT
    ( image ORDSYS.ORDImage,
      description VARCHAR2(2000),
      MEMBER PROCEDURE SetProperties(SELF IN OUT AnnotatedImage),
      MEMBER PROCEDURE Copy(dest IN OUT AnnotatedImage),
      MEMBER PROCEDURE ProcessCopy(command IN VARCHAR2,
                                   dest IN OUT AnnotatedImage)
    );
/

CREATE TYPE BODY AnnotatedImage AS
  MEMBER PROCEDURE SetProperties(SELF IN OUT AnnotatedImage) IS
  BEGIN
    SELF.image.setProperties();
    SELF.description :=
        'This is an example of using Image object as a subtype';
  END SetProperties;
  MEMBER PROCEDURE Copy(dest IN OUT AnnotatedImage) IS
  BEGIN
    SELF.image.copy(dest.image);
    dest.description := SELF.description;
  END Copy;
  MEMBER PROCEDURE ProcessCopy(command IN VARCHAR2,
                               dest IN OUT AnnotatedImage) IS
  BEGIN
    SELF.Image.processCopy(command,dest.image);
    dest.description := SELF.description;
  END ProcessCopy;
END;
/

After creating the new type, you can use it as you would any other type. For example:

CREATE OR REPLACE DIRECTORY ORDIMGDIR AS 'C:\TESTS';

CREATE TABLE my_example(id NUMBER, an_image AnnotatedImage);
INSERT INTO my_example VALUES (1,
    AnnotatedImage(
        ORDSYS.ORDImage.init('file','ORDIMGDIR','plaid.gif'));
COMMIT;
DECLARE
    myimage AnnotatedImage;
BEGIN
    SELECT an_image INTO myimage FROM my_example;
    myimage.SetProperties;
    DBMS_OUTPUT.PUT_LINE('This image has a description of ');
    DBMS_OUTPUT.PUT_LINE(myimage.description);
    UPDATE my_example SET an_image = myimage;
END;
/

7.4 Supporting Media Data Processing

Oracle Multimedia also supports the processing of audio and video data, as described in the following subsections:

7.4.1 Supporting Audio Data Processing

To support audio data processing, that is, the passing of an audio processing command and set of arguments to a format plug-in for processing, use the processAudioCommand( ) method. This method is available only for user-defined formats.


See Also:

The processAudioCommand( ) method in Oracle Multimedia Reference for a description


7.4.2 Supporting Video Data Processing

To support video data processing, that is, the passing of a command and set of arguments to a format plug-in for processing, use the processVideoCommand( ) method. This method is only available for user-defined formats.


See Also:

The processVideoCommand( ) method in Oracle Multimedia Reference for a description


PKpoaWPK"+AOEBPS/content.opf6 Oracle® Multimedia User's Guide, 11g Release 2 (11.2) en-US E10777-03 Oracle Corporation Oracle Corporation Oracle® Multimedia User's Guide, 11g Release 2 (11.2) 2010-07-30T10:35:11Z Presents information about using Oracle Database to store, manage, and retrieve images, audio, video, DICOM format medical images and other objects, or other heterogeneous media data in an integrated fashion with other enterprise information. (Oracle Multimedia was formerly known as Oracle interMedia.) PKd76PK"+A OEBPS/lof.htm\ List of Figures PK@a\PK"+AOEBPS/dcommon/prodbig.gif GIF87a!!!)))111BBBZZZsss{{ZRRcZZ!!1!91)JB9B9)kkcJJB991ssc絽Zcc!!{祽BZc!9B!c{!)c{9{Z{{cZB1)sJk{{Z{kBsZJ91)Z{!{BcsRsBc{9ZZk甽kBkR!BZ9c)JJc{!))BZks{BcR{JsBk9k)Zck!!BZ1k!ZcRBZcZJkBk1Z9c!R!c9kZRZRBZ9{99!R1{99R{1!1)c1J)1B!BJRkk{ƽ絵ތkk絵RRs{{{{JJsssBBkkk!!9ss{{ZZssccJJZZRRccRRZZ))cBBJJ99JJ!!c11991199Z11!c!!))Z!!!1BRck{)!cJBkZRZ,HP)XRÇEZ֬4jJ0 @ "8pYҴESY3CƊ@*U:lY0_0#  5tX1E: C_xޘeKTV%ȣOΏ9??:a"\fSrğjAsKJ:nOzO=}E1-I)3(QEQEQEQEQEQEQE֝Hza<["2"pO#f8M[RL(,?g93QSZ uy"lx4h`O!LŏʨXZvq& c՚]+: ǵ@+J]tQ]~[[eϸ (]6A&>ܫ~+כzmZ^(<57KsHf妬Ϧmnẁ&F!:-`b\/(tF*Bֳ ~V{WxxfCnMvF=;5_,6%S>}cQQjsOO5=)Ot [W9 /{^tyNg#ЄGsֿ1-4ooTZ?K Gc+oyڙoNuh^iSo5{\ܹ3Yos}$.nQ-~n,-zr~-|K4R"8a{]^;I<ȤL5"EԤP7_j>OoK;*U.at*K[fym3ii^#wcC'IIkIp$󿉵|CtĈpW¹l{9>⪦׺*ͯj.LfGߍԁw] |WW18>w.ӯ! VӃ :#1~ +މ=;5c__b@W@ +^]ևՃ7 n&g2I8Lw7uҭ$"&"b eZ":8)D'%{}5{; w]iu;_dLʳ4R-,2H6>½HLKܹR ~foZKZ࿷1[oZ7׫Z7R¢?«'y?A}C_iG5s_~^ J5?œ tp]X/c'r%eܺA|4ծ-Ե+ْe1M38Ǯ `|Kյ OVڅu;"d56, X5kYR<̭CiطXԮ];Oy)OcWj֩}=܅s۸QZ*<~%뺃ȶp f~Bðzb\ݳzW*y{=[ C/Ak oXCkt_s}{'y?AmCjޓ{ WRV7r. g~Q"7&͹+c<=,dJ1V߁=T)TR՜*N4 ^Bڥ%B+=@fE5ka}ędܤFH^i1k\Sgdk> ֤aOM\_\T)8靠㡮3ģR: jj,pk/K!t,=ϯZ6(((((((49 xn_kLk&f9sK`zx{{y8H 8b4>ÇНE|7v(z/]k7IxM}8!ycZRQ pKVr(RPEr?^}'ðh{x+ՀLW154cK@Ng C)rr9+c:׹b Жf*s^ fKS7^} *{zq_@8# pF~ [VPe(nw0MW=3#kȵz晨cy PpG#W:%drMh]3HH<\]ԁ|_W HHҡb}P>k {ZErxMX@8C&qskLۙOnO^sCk7ql2XCw5VG.S~H8=(s1~cV5z %v|U2QF=NoW]ո?<`~׮}=ӬfԵ,=;"~Iy7K#g{ñJ?5$y` zz@-~m7mG宝Gٱ>G&K#]؃y1$$t>wqjstX.b̐{Wej)Dxfc:8)=$y|L`xV8ߙ~E)HkwW$J0uʟk>6Sgp~;4֌W+חc"=|ř9bc5> *rg {~cj1rnI#G|8v4wĿhFb><^ pJLm[Dl1;Vx5IZ:1*p)إ1ZbAK(1ׅ|S&5{^ KG^5r>;X׻K^? s fk^8O/"J)3K]N)iL?5!ƾq:G_=X- i,vi2N3 |03Qas ! 7}kZU781M,->e;@Qz T(GK(ah(((((((Y[×j2F}o־oYYq $+]%$ v^rϭ`nax,ZEuWSܽ,g%~"MrsrY~Ҿ"Fت;8{ѰxYEfP^;WPwqbB:c?zp<7;SBfZ)dϛ; 7s^>}⍱x?Bix^#hf,*P9S{w[]GF?1Z_nG~]kk)9Sc5Ո<<6J-ϛ}xUi>ux#ţc'{ᛲq?Oo?x&mѱ'#^t)ϲbb0 F«kIVmVsv@}kҡ!ˍUTtxO̧]ORb|2yԵk܊{sPIc_?ħ:Ig)=Z~' "\M2VSSMyLsl⺿U~"C7\hz_ Rs$~? TAi<lO*>U}+'f>7_K N s8g1^CeКÿE ;{+Y\ O5|Y{/o+ LVcO;7Zx-Ek&dpzbӱ+TaB0gNy׭ 3^c T\$⫫?F33?t._Q~Nln:U/Ceb1-im WʸQM+VpafR3d׫é|Aү-q*I P7:y&]hX^Fbtpܩ?|Wu󭏤ʫxJ3ߴm"(uqA}j.+?S wV ~ [B&<^U?rϜ_OH\'.;|.%pw/ZZG'1j(#0UT` Wzw}>_*9m>󑓀F?EL3"zpubzΕ$+0܉&3zڶ+jyr1QE ( ( ( ( ( ( ( (UIdC0EZm+]Y6^![ ԯsmܶ捆?+me+ZE29)B[;я*wGxsK7;5w)}gH~.Ɣx?X\ߚ}A@tQ(:ͧ|Iq(CT?v[sKG+*רqҍck <#Ljα5݈`8cXP6T5i.K!xX*p&ќZǓϘ7 *oƽ:wlຈ:Q5yIEA/2*2jAҐe}k%K$N9R2?7ýKMV!{W9\PA+c4w` Wx=Ze\X{}yXI Ү!aOÎ{]Qx)#D@9E:*NJ}b|Z>_k7:d$z >&Vv󃏽WlR:RqJfGإd9Tm(ҝEtO}1O[xxEYt8,3v bFF )ǙrPNE8=O#V*Cc𹾾&l&cmCh<.P{ʦ&ۣY+Gxs~k5$> ӥPquŽўZt~Tl>Q.g> %k#ú:Kn'&{[yWQGqF}AЅ׮/}<;VYZa$wQg!$;_ $NKS}“_{MY|w7G!"\JtRy+贾d|o/;5jz_6fHwk<ѰJ#]kAȎ J =YNu%dxRwwbEQEQEQEQEQEQEQEQEQE'fLQZ(1F)hQ@X1KEQE-Q@ 1KE3h=iPb(((1GjZ(-ʹRPbR@ 1KE7`bڒyS0(-&)P+ ڎԴP11F)h&:LRmQ@Q@Š(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((,RmuM. I-nBvskO֑CcmtbJ 6zIl@=((/7-K^1Ѽ?ohrR d0aڀ=Ҋuސ)60 'PEPEy_[RѼ cqv344LWʔ { <<^IJMQEQEQEQEQEQ^]/:No,`gm5üqE]N cΙW¶x>KCkv-.FgҀ;+/P[xWHT2B;(R&2;Ԡ((GK7>L˝c]ıs9P,RmuM. I-nBvsk֥6]#TX{(n$X 1$dԢ((((> Xf]Ƿv߽רPEPEPEPEPEPEPEPEPEPEPEPEPEPO4 8 \xZ,fj ab8A!UeA,xGiEKV\#^_7y½ow:%H_G]ԢP..Ϙ6*LJpW!d^|@3Y]xreivV/cc  ?Jh'cR`YfԴ;Q+a^[[+|)ayoxOĺK܍VpV@72ޭ{?xkV)kihO<6\K0DF dOkOߌ A(Gfq892 mBr >35MyHHY*"RA"ᾥCNEx[š5Η#s+*3o!I Gm9|Ex}r8[]D JUwpx IBN+>|u}]+v(mIWGB[dk _H_|E?j?ݷg)Ge?dy{xK,y*7 |sb_|g&7`ɦD&X(i-vٻ3QVu>ne;̬1*3Ҿ>jOۭ.n|۶o83^:τ|g}MA!gLBFG\'H! {x#5 WGG<+=#wt;<˫>ihROJ}C_|Kk˿ϣile b#(ž>ށO'UZy2ƙ+ }跖ɵY~AJ1 h~@|Ii)6-ncwlp0cvaX?q^ k[nhQGQNt'.o jѠe9TDPa\kSqyVO{Q@?,ZW8_}@?G<+KO:N= iّ  $h'' zW7G<+KO C:N=Ėwف2J2nܣ#:cDFM{kgdpV@G\PXs>{M޵fn#K{`|"o$gRv$X8#E'!I5=7 7( 9S[8FN{yмMŦ63W!xo/5Mc7bY pΣ^a}oryQ$о7#T2^]wңٽฌ8GU>蚏>i:No{<2-wL9RA*@.c6KxlR|!S9A‚+5^>]R,wwM*) 1 P ~B%h3["HTnUc)`P U$w=+:-c_*3~Oym׊>0DmORg6ro`cM~xCNno pw!'0sǮ~@Ԭվ%j{HGHY;AYUxPtx>7n-Ix~Kwx'Xݿ,<̼pH<qxnY!y$3aO[2ݸO ▅YqyȲF̮>V];EwQEQEQEQEQEQEQEQEQEQEQEQEx$O*Z<RՏx[FvgX*yz1BLӭ,mbHaME(րם'skC[4:,gEv 9R? ?Jh'cRרh& 'I=ŏ,I|B|%0K ú6i/@`0ݏjqC)#|Or#rt9Һ =NK;H.dgHʞ.n%;yfE(ڀ< 3> I.lMs"r3 _I o-#KH4= eO'$.A=Nx64O 4m. "9 Q\Xzw]ɍ<@jqC)#|Or#rt9Ҽ3$/|yx:-jT1OfC$1%T6o |>war#s«j4xsȫVRۈi.8z 6&o9ny'42`K`Hd +t$5ScsB Yg q+u(uTY x#Y 0~O@&p'I;={:!($ qUE81@2nZ [֎YzzQ@Q@Q@U{=2K--cFI W a}Rߝd+ϚS{g8qoYÖskubN8 :@Q\_~+/W^1y 1kkTip$l%F|b1p9ҊgA6jP\3]FC*mv9ˎ޵PEPEPEƺohuMR mmQYf1=(; ??vO |_n7cU@A*I-px4QEQEQ\ş^𭮩i4ޥ-3(RYNruԦ|+j {e ċ!C: dS@QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEx_Yzwy$7;w̭ #lH͌gc/ ]| C͸ uv뇸q(rI>OON_o_@PXvlU'죵%vB,\9}9u_:1x?nui%+ w6TfThSӹӓRot*FXbpF^~_^6?!ϲ|ۤT8G|O ,u^g<3n>s=;?InQ_PAo l/7ݺEOnNx'B_~6푓`g;sӽsKIoQ% 7=oŸfҾӿXSc<[7Y uE-d@q#= ?|koV|n?^䱓̑q'ߓqRs~#|TejfRu.X6pݞB^ys9Mn⽱$I/@v AROpA VG  HB(qѬ5W6]_,Wmc|ITq>]5& MwRG$n2i&XrQA]g=f@g6,KH Y' _~Ҵ+p5+J9?xMG{{;Gmmg` 8889+8OˢID$s&GGd+C~F"4TUTdY5x݇ccHSxawmey6!N@Jg~ў< +ɐHg]rK3_G^?G<+yV?-z?xkV)kh iqi6^'+S-&tL7 `q')NeoY˶eT8$`S\ڶ-ui4=6dt`2 ppۀ>֥6]#TX{(n$X 1$d}3Ekx$'Fh,#q3y=p; +{x$qơU 8|y]6֫x 4젵E#D\db;o6sjv8gV Uٰ; Euckۭ*M:K֬ўq(Wp eR `g7 ;^ys]7?; wfn.-.rO?;IaXTyZ襯?iEK]fM|-6ÑFT[Q@~2osZ\C Z8+ܳP {|ZCRe#gNK N$c%ddW?ڭ/sG'ng$Pvq^ ;@~8=aYZ#6n0ppH<< r>Nj4h>ԑE<.$qD v3 yR%IY-[y.!ʩ2$Yu995~,mY(I$ .Oy/`:ςӧ\RW6 qC֗ _*<-գ^c  pn~!|ԡo~$VK}KmL I$VFNsp zO_8Sa)fڼ89<⏎6N тHH3ʵ*}wVDݍs 3T|0v1`2^ \'6.MJ|0ĀGV :sAu=7Ne 8vE9G7$4_[ƷKBtf79?q g㬱㼰L $0? ƺmǭW^\wpiw[Aj FY#0wgl< c$pέ)<2`vA<B׷ZTuޗY=ŜpPA+ʤ o; ??vƺo~=xw>\[[]37 1^1О4Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@7ך^9f1* 78y_i~<#Z;e>pp؂Q^Wzږuwjđ5rݼ'O`.z|7yºS^$ƣC\七͌˓3FG zx;?y']HVf,n56,I1G"HEV>}owM 7i,6̍ ]ODn巸9 I]H#Wluo)KAIPG:/''ǽfOgsLZo#'c. e_Ht/x҉+O7Z&w#FcLA[B\0 Sx'xB@g>~n׵x8_I xOk0[h*Pd'~3[__lVOqg9 oDӼGϤhoMX0H#$ҵ[sK˘l|RFr<8"pQcOdcT|+}1O,AS]u-)ß+Ow-1;K'v09hֿgKӬt}JM<ڼ5ynK II _\xٶ.<#teST.I9\u Liw !пJ$^5;9,'jvc|3$ QcGĚevv[KX!4\NOIh(zMvceqw%%̙3*\䓒FzMp~)qM{wz=WIf("*bUOAր8p5+J>cϨDws n;s r@'=Mz|xS-k?:c:| Di~)>z!bY|?0>[qo,sA*H2AG9KHtf$?G!FM8$<G5 ԭ|BbK9(0ɑ&̐NNIڀ8?'dkK++4,g8nrd5 iz_sn) ód`aWhZg''inv2qg5bSӮl/#-nxfMnF0dҀ0|g e bwMQ?w2$ KcEͨۻڻ"po *%X^ϷA 8ܧayg/gZyV$`a d *9'%4ydJv[ v״6?ĽfOGc+', df<%~/j#Եj'b˅VS ]Nc@2h'cRai'~ݻo s>#y7ksnpqt3IEmۿb݌gMxumSZ&%\S ,y݆ "p{p~9Mm<[+˻R!rm YrT[>sKmy>Ŵg\Y@`G$(u[K;|E̒p@&|md?nnپ6ۜ 8vl~-񮹯*KǑ NATyS oQ2Gc`W\C J<-p,ftEw0ܪą$u`}Ҹo?5*oZr d,>ɀ`0«?kQfkq[O GB۾cc۞׉.?qP.d. c<2Ñ#r~$Э/CF2r3U>no?]ڋ}+7P[U9 6]-tx&W54q8'$^5ӖZ| I 0*89R@8TrO / K,h>ȕV8='imtz͆ dW5,N>YT$(lxK><^&ercԐq*j(Ě/T@!3FewT'}+R ( +G}¾!t kOQhؙgeQ:q€ *i5j K%-p 3N=n6q+i-fYT6*H8r(DZg; xAxmn4dǽ7Ua~5z 6Y?la۫/(V/˒<`*9[cHU I9I\_ŭJm+_. X[WXG;\(Aw/x&a͵2؅X`MF瞹ZmGF{y"<H0A'=GN6 »;B\Jbljy$P_|9xW^o5-[TL n@P;8fazIaY?TU;y_]覯?jEE@^o⟄~4ާkڶϱ@RU|o 5P&xsImc.-wY<$I  (<S?{ŞḰmƊ8ƈC q23[<Yk7aӱJ+'#ͫV𪼼z"p"I<_|?ߨx {"%RH_傍wpH@<[oqsA*92<G> h> _C_qK(Btid|'ohC\{|O?ij6<ڗټ囕_0m1Fs{q_@PEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPs  !y$($s~3־0WO;wuHft<[G-˹pK>DujVyW+ .1*Ò1J>k4_﫧WDAݎI GϚn?~1mKRi,|;d1§ʏ# + r8v>.x SO[!\ *_t  Exr%*_}!#U #4 & ֩3|b]L ]t b+Da&R_2lEٱZ`aC)/яmvUkS r(-iPE Vv_{z GLt\2s!F A#葡JY r|AA,hB}q|B`du }00(䡆<pb,G+oB C0p/x$…– ]7 @2HFc ) @AD \0 LHG',(A` `@SC)_" PH`}Y+_|1.K8pAKMA @?3҄$[JPA)+NH I ,@8G0/@R T,`pF8Ѓ)$^$ DDTDlA@ s;PKPK"+AOEBPS/dcommon/darbbook.cssPKPK"+A!OEBPS/dcommon/O_signature_clr.JPG"(JFIF``C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (?O '~MQ$Vz;OlJi8L%\]UFjޙ%ԯS;rA]5ފ<׈]j7Ouyq$z'TQuw7Ŀ KX߁M2=S'TQt?.5w'97;~pq=" ~k?`'9q6 E|yayM^Om'fkC&<5x' ?A?Zx'jß={=SßM gVC.5+Hd֪xc^)Җufz{Cީ|D Vkznq|+Xa+{50rx{|OG.OϞ~f/ xxX[2H )c+#jpUOZYX\=SG ߨC|K@;_߆'e?LT?]:?>w ڔ`D^So~xo[Ӡ3i7B:Q8 Vc-ďoi:FM292~y_*_闱YN\Fr=xZ3鳎OwW_QEzW~c]REeaSM}}Hӏ4&.E]u=gMѠ+mF`rNn$w9gMa꺢nTuhf2Xv>އ a(Û6߭?<=>z'TQuw7Ŀ KX߁M2=S'TQt?.5Kko\.8S$TOX߀Gw?Zx汴X)C7~.i6(Щ=+4{mGӭ¸-]&'t_kV*I<1)4thtIsqpQJ+> \m^[aJ5)ny:4o&QEnyAEPEEss 72,PDۢ׃K W{Wjr+wگ iM/;pd?~&?@;7E4gv8 $l'z'TQuw7Ŀ Gֱ=ɿ&G?. iR(5W*$|?w᫼gkmIbHe/_t>tg%y.l}N5[]+Mk0ĠeHdPrsst'UiC,y8`V%9ZIia|ܪvi מYG,o}+kk{YbyIeb*sAtի82zWoEK5z*o-eo;n(P u-I)4Š(HQEQEQEQEhz(X/Đ?}Bk˩ ݏrk0]4>8XzV? }6$}d^F>nU K ?Bտk_9׾x~w'ߞ  uDŽtL ؈5c-E/"|_Oo.IH쐍=i*Iw5(ںw?t5s.)+tQ2dUt5Vĺ.jZ"@IRrZƅY4ߡ_;}ų(KyQf1Aǵt?sZg+?F5_oQR&Dg߿]6FuRD u>ڿxl7?IT8'shj^=.=J1rj1Wl$얲cPx;E,p$֟ˏkw qg"45(ǛkV/=+ũ)bYl~K#˝J_כ5&\F'I#8/|wʾ_Xj Q:os^T1.M_|TO.;?_  jF?g N 8nA2F%i =qW,G=5OU u8]Rq?wr'˻S+۾.ܼ 87Q^elo/T*?L|ۚ<%<,/v_OKs B5f/29n0=zqQq(ª=VX@*J(э(f5qJN_EVǞQEOuoѕOuoa5}gO?:߂8Wא|cڽ~]N&O( (<]>͠@VQ=^~U ̴m&\խ5i:}|}r~9՝f}_>'vVֲ$~^f30^in{\_.O F8to}?${φ|#x^#^n~w=~k~?'KRtO.㌡h![3Zu*ٷճ(ԟ]z_/W1(ԟ]v~g|Yq<ז0 ; b8֮s,w9\?uEyStKaª@\,)) (!EPEPEPEPEPzѧts{v>C/"N6`d*J2gGӧWqBq_1ZuΓ\X]r?=Ey88Mp&pKtO-"wR2 K^-Z< \c>V0^@O7x2WFjs<׻kZ(<Т(OFw/6$1[:ޯԯ#q~4|,LVPem=@=YLUxӃV}AUbcUB.Ds5*kٸAeG>PJxt͝ b88?*$~@ׯD VkraiJs}Q.20x&mXξ,Z]“A-J#`+-E/"<]\a'tZGy.(|lދ~gMK OZdxDŽU9T6ϯ^<Ϡt5CZ]].t۫S=s`ڳ%8iVK:nqe+#<.T6U>zWoy3^I {F?J~=G}k)K$$;$de8*G Uӟ4Ocºw}|]4=ݣ\x$ʠms?q^ipw\"ȿPs^Z Q_0GڼU.t}ROM[G#]8wٞ ӫ87}Cgw vHȩBM55vof =A_٭`Ygx[6 P,5}>蚊(0(+?>+?> k|TuXq6_ +szk :u_ Z߶Ak_U}Jc2u/1[_»ݸG41-bሬ۴}}Eȹפ_c?5gi @cL\L<68hF_Ih>X4K7UТ sMj =J7CKo>Օ5s:߀t ~ηaٿ?|gdL8+gG%o?x`دOqȱwc¨&TW_V_aI=dpG!wu۞սZ1yL50$(l3(:~'ַo A}a3N*[0ǭ HKQV}G@֜$ 9of$ArNqUOgË05#m?D)^_h//5_/<?4}Jį+GkpG4"$ r| >S4Ђ"S 1%R:ȝ 8;PKPz PK"+AOEBPS/dcommon/feedback.gif7GIF89a'%(hp|fdx?AN5:dfeDGHɾTdQc`g*6DC\?ؘ||{;=E6JUՄfeA= >@,4`H.|`a (Q 9:&[|ځ,4p Y&BDb,!2@, $wPA'ܠǃ@CO~/d.`I @8ArHx9H75j L 3B/` P#qD*s 3A:3,H70P,R@ p!(F oԥ D;"0 ,6QBRɄHhI@@VDLCk8@NBBL2&pClA?DAk%$`I2 #Q+l7 "=&dL&PRSLIP)PɼirqМ'N8[_}w;PK-PK"+AOEBPS/dcommon/booklist.gifGIF89a1޵֥΄kZ{Jk1Rs!BZ)B),@I9Z͓Ca % Dz8Ȁ0FZЌ0P !x8!eL8aWȠFD(~@p+rMS|ӛR$ v "Z:]ZJJEc{*=AP  BiA ']j4$*   & 9q sMiO?jQ = , YFg4.778c&$c%9;PKː5PK"+AOEBPS/dcommon/cpyr.htm1 Oracle Legal Notices

Oracle Legal Notices

Copyright Notice

Copyright © 1994-2012, Oracle and/or its affiliates. All rights reserved.

Trademark Notice

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered trademark of The Open Group.

License Restrictions Warranty/Consequential Damages Disclaimer

This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.

Warranty Disclaimer

The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.

Restricted Rights Notice

If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, the following notice is applicable:

U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are "commercial computer software" or "commercial technical data" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, the use, duplication, disclosure, modification, and adaptation shall be subject to the restrictions and license terms set forth in the applicable Government contract, and, to the extent applicable by the terms of the Government contract, the additional rights set forth in FAR 52.227-19, Commercial Computer Software License (December 2007). Oracle America, Inc., 500 Oracle Parkway, Redwood City, CA 94065.

Hazardous Applications Notice

This software or hardware is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications that may create a risk of personal injury. If you use this software or hardware in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software or hardware in dangerous applications.

Third-Party Content, Products, and Services Disclaimer

This software or hardware and documentation may provide access to or information on content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services.

Alpha and Beta Draft Documentation Notice

If this document is in prerelease status:

This documentation is in prerelease status and is intended for demonstration and preliminary use only. It may not be specific to the hardware on which you are using the software. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to this documentation and will not be responsible for any loss, costs, or damages incurred due to the use of this documentation.

Oracle Logo

PKN61PK"+AOEBPS/dcommon/masterix.gif.GIF89a1ޜΌscJk1Rs!Bc1J),@IS@0"1 Ѿb$b08PbL,acr B@(fDn Jx11+\%1 p { display: none; } /* Class Selectors */ .ProductTitle { font-family: sans-serif; } .BookTitle { font-family: sans-serif; } .VersionNumber { font-family: sans-serif; } .PrintDate { font-family: sans-serif; font-size: small; } .PartNumber { font-family: sans-serif; font-size: small; } PKeӺ1,PK"+AOEBPS/dcommon/larrow.gif#GIF87a絵ƌֵƽ{{ss֜ƔZZ{{{{ZZssZZccJJJJRRBBJJJJ991111))!!{,@pH,Ȥrl:ШtpHc`  өb[.64ꑈ53=Z]'yuLG*)g^!8C?-6(29K"Ĩ0Яl;U+K9^u2,@@ (\Ȱ Ë $P`lj 8x I$4H *(@͉0dа8tA  DсSP v"TUH PhP"Y1bxDǕ̧_=$I /& .)+ 60D)bB~=0#'& *D+l1MG CL1&+D`.1qVG ( "D2QL,p.;u. |r$p+5qBNl<TzB"\9e0u )@D,¹ 2@C~KU 'L6a9 /;<`P!D#Tal6XTYhn[p]݅ 7}B a&AƮe{EɲƮiEp#G}D#xTIzGFǂEc^q}) Y# (tۮNeGL*@/%UB:&k0{ &SdDnBQ^("@q #` @1B4i@ aNȅ@[\B >e007V[N(vpyFe Gb/&|aHZj@""~ӎ)t ? $ EQ.սJ$C,l]A `8A o B C?8cyA @Nz|`:`~7-G|yQ AqA6OzPbZ`>~#8=./edGA2nrBYR@ W h'j4p'!k 00 MT RNF6̙ m` (7%ꑀ;PKl-OJPK"+AOEBPS/dcommon/index.gifGIF89a1޵ΥΥ{sc{BZs,@IM" AD B0 3.R~[D"0, ]ШpRNC  /& H&[%7TM/`vS+-+ q D go@" 4o'Uxcxcc&k/ qp zUm(UHDDJBGMԃ;PK(PK"+AOEBPS/dcommon/bookbig.gif +GIF89a$!!!)))111999BBBJJJRRRZZZccckkksss{{{skkB991)))!!B11))1!JB9B9!!cZ9ƭƽssk{ZZRccZRRJJJBBB9c!!ν)1)k{s絽ƌkssֽZccJRRBJJ{9BB)11)99!!))11!!k!JZ!)RcJccBcs)1c)JZ!BR!)BZ)99J!Rk9!c11B)Z{)9Bkc1kB9BZ!Z{9Rs)Jkksk9kB1s1Jk9Rƥc{k9s)Z{1k91)s1Rk)Jc1J!))BZ!1k{csc{)19B!)Bcsc{ksc{kZs!RkJkJkքc{9Zks{ck9R)Bks9R9R1J!)Z1B!)c)9)99BR19kksBBJcc{ccBBZ))9kk!!199c11ZBB{9!!R!!Z!!c))!!kR!!s!!BcksRZ1c9B)R91c1)Z!R9B9k1)RcZ{)!1B9JB9B)!)J9B!& Imported from GIF image: bookbig.gif,$!!!)))111999BBBJJJRRRZZZccckkksss{{{skkB991)))!!B11))1!JB9B9!!cZ9ƭƽssk{ZZRccZRRJJJBBB9c!!ν)1)k{s絽ƌkssֽZccJRRBJJ{9BB)11)99!!))11!!k!JZ!)RcJccBcs)1c)JZ!BR!)BZ)99J!Rk9!c11B)Z{)9Bkc1kB9BZ!Z{9Rs)Jkksk9kB1s1Jk9Rƥc{k9s)Z{1k91)s1Rk)Jc1J!))BZ!1k{csc{)19B!)Bcsc{ksc{kZs!RkJkJkքc{9Zks{ck9R)Bks9R9R1J!)Z1B!)c)9)99BR19kksBBJcc{ccBBZ))9kk!!199c11ZBB{9!!R!!Z!!c))!!kR!!s!!BcksRZ1c9B)R91c1)Z!R9B9k1)RcZ{)!1B9JB9B)!)J9BH`\Ȑ:pظа"A6DBH,V@Dڹ'G"v Æ ܥ;n;!;>xAܽ[G.\rQC wr}BŊQ A9ᾑ#5Y0VȒj0l-GqF>ZpM rb ;=.ސW-WѻWo ha!}~ْ ; t 53 :\ 4PcD,0 4*_l0K3-`l.j!c Aa|2L4/1C`@@md;(H*80L0L(h*҇҆o#N84pC (xO@ A)J6rVlF r  fry†$r_pl5xhA+@A=F rGU a 1х4s&H Bdzt x#H%Rr (Ѐ7P`#Rщ'x" #0`@~i `HA'Tk?3!$`-A@1l"P LhʖRG&8A`0DcBH sq@AXB4@&yQhPAppxCQ(rBW00@DP1E?@lP1%T` 0 WB~nQ@;PKGC PK"+AOEBPS/dcommon/rarrow.gif/GIF87a絵ƌֵƽ{{ss֜ƔZZ{{{{ZZssZZccJJJJRRBBJJJJ991111))!!{,@pH,Ȥrl:ШLlԸ NCqWEd)#34vwwpN|0yhX!'+-[F 'n5 H $/14w3% C .90" qF 7&E "D mnB|,c96) I @0BW{ᢦdN p!5"D`0 T 0-]ʜ$;PKJV^PK"+AOEBPS/dcommon/mix.gifkGIF89aZZZBBBJJJkkk999sss!!!111cccֽ{{{RRR)))猌ƭ{s{sks!,@@pH,B$ 8 t:<8 *'ntPP DQ@rIBJLNPTVEMOQUWfj^!  hhG H  kCúk_a Ǥ^ h`B BeH mm  #F` I lpǎ,p B J\Y!T\(dǏ!Gdˆ R53ټ R;iʲ)G=@-xn.4Y BuU(*BL0PX v`[D! | >!/;xP` (Jj"M6 ;PK枰pkPK"+AOEBPS/dcommon/doccd_epub.jsM /* Copyright 2006, 2012, Oracle and/or its affiliates. All rights reserved. Author: Robert Crews Version: 2012.3.17 */ function addLoadEvent(func) { var oldOnload = window.onload; if (typeof(window.onload) != "function") window.onload = func; else window.onload = function() { oldOnload(); func(); } } function compactLists() { var lists = []; var ul = document.getElementsByTagName("ul"); for (var i = 0; i < ul.length; i++) lists.push(ul[i]); var ol = document.getElementsByTagName("ol"); for (var i = 0; i < ol.length; i++) lists.push(ol[i]); for (var i = 0; i < lists.length; i++) { var collapsible = true, c = []; var li = lists[i].getElementsByTagName("li"); for (var j = 0; j < li.length; j++) { var p = li[j].getElementsByTagName("p"); if (p.length > 1) collapsible = false; for (var k = 0; k < p.length; k++) { if ( getTextContent(p[k]).split(" ").length > 12 ) collapsible = false; c.push(p[k]); } } if (collapsible) { for (var j = 0; j < c.length; j++) { c[j].style.margin = "0"; } } } function getTextContent(e) { if (e.textContent) return e.textContent; if (e.innerText) return e.innerText; } } addLoadEvent(compactLists); function processIndex() { try { if (!/\/index.htm(?:|#.*)$/.test(window.location.href)) return false; } catch(e) {} var shortcut = []; lastPrefix = ""; var dd = document.getElementsByTagName("dd"); for (var i = 0; i < dd.length; i++) { if (dd[i].className != 'l1ix') continue; var prefix = getTextContent(dd[i]).substring(0, 2).toUpperCase(); if (!prefix.match(/^([A-Z0-9]{2})/)) continue; if (prefix == lastPrefix) continue; dd[i].id = prefix; var s = document.createElement("a"); s.href = "#" + prefix; s.appendChild(document.createTextNode(prefix)); shortcut.push(s); lastPrefix = prefix; } var h2 = document.getElementsByTagName("h2"); for (var i = 0; i < h2.length; i++) { var nav = document.createElement("div"); nav.style.position = "relative"; nav.style.top = "-1.5ex"; nav.style.left = "1.5em"; nav.style.width = "90%"; while (shortcut[0] && shortcut[0].toString().charAt(shortcut[0].toString().length - 2) == getTextContent(h2[i])) { nav.appendChild(shortcut.shift()); nav.appendChild(document.createTextNode("\u00A0 ")); } h2[i].parentNode.insertBefore(nav, h2[i].nextSibling); } function getTextContent(e) { if (e.textContent) return e.textContent; if (e.innerText) return e.innerText; } } addLoadEvent(processIndex); PKo"nR M PK"+AOEBPS/dcommon/toc.gifGIF89a1ΥΥ{c{Z{JkJk1Rk,@IK% 0| eJB,K-1i']Bt9dz0&pZ1o'q(؟dQ=3S SZC8db f&3v2@VPsuk2Gsiw`"IzE%< C !.hC IQ 3o?39T ҍ;PKv I PK"+AOEBPS/dcommon/topnav.gifGIF89a1ֽ筽ޭƔkZZk{Bc{,@ ) l)-'KR$&84 SI) XF P8te NRtHPp;Q%Q@'#rR4P fSQ o0MX[) v + `i9gda/&L9i*1$#"%+ ( E' n7Ȇ(,҅(L@(Q$\x 8=6 'נ9tJ&"[Epljt p#ѣHb :f F`A =l|;&9lDP2ncH R `qtp!dȐYH›+?$4mBA9 i@@ ]@ꃤFxAD*^Ŵ#,(ε  $H}F.xf,BD Z;PK1FAPK"+AOEBPS/dcommon/bp_layout.css# @charset "utf-8"; /* bp_layout.css Copyright 2007, Oracle and/or its affiliates. All rights reserved. */ body { margin: 0ex; padding: 0ex; } h1 { display: none; } #FOOTER { border-top: #0d4988 solid 10px; background-color: inherit; color: #e4edf3; clear: both; } #FOOTER p { font-size: 80%; margin-top: 0em; margin-left: 1em; } #FOOTER a { background-color: inherit; color: gray; } #LEFTCOLUMN { float: left; width: 50%; } #RIGHTCOLUMN { float: right; width: 50%; clear: right; /* IE hack */ } #LEFTCOLUMN div.portlet { margin-left: 2ex; margin-right: 1ex; } #RIGHTCOLUMN div.portlet { margin-left: 1ex; margin-right: 2ex; } div.portlet { margin: 2ex 1ex; padding-left: 0.5em; padding-right: 0.5em; border: 1px #bcc solid; background-color: #f6f6ff; color: black; } div.portlet h2 { margin-top: 0.5ex; margin-bottom: 0ex; font-size: 110%; } div.portlet p { margin-top: 0ex; } div.portlet ul { list-style-type: none; padding-left: 0em; margin-left: 0em; /* IE Hack */ } div.portlet li { text-align: right; } div.portlet li cite { font-style: normal; float: left; } div.portlet li a { margin: 0px 0.2ex; padding: 0px 0.2ex; font-size: 95%; } #NAME { margin: 0em; padding: 0em; position: relative; top: 0.6ex; left: 10px; width: 80%; } #PRODUCT { font-size: 180%; } #LIBRARY { color: #0b3d73; background: inherit; font-size: 180%; font-family: serif; } #RELEASE { position: absolute; top: 28px; font-size: 80%; font-weight: bold; } #TOOLS { list-style-type: none; position: absolute; top: 1ex; right: 2em; margin: 0em; padding: 0em; background: inherit; color: black; } #TOOLS a { background: inherit; color: black; } #NAV { float: left; width: 96%; margin: 3ex 0em 0ex 0em; padding: 2ex 0em 0ex 4%; /* Avoiding horizontal scroll bars. */ list-style-type: none; background: transparent url(../gifs/nav_bg.gif) repeat-x bottom; } #NAV li { float: left; margin: 0ex 0.1em 0ex 0em; padding: 0ex 0em 0ex 0em; } #NAV li a { display: block; margin: 0em; padding: 3px 0.7em; border-top: 1px solid gray; border-right: 1px solid gray; border-bottom: none; border-left: 1px solid gray; background-color: #a6b3c8; color: #333; } #SUBNAV { float: right; width: 96%; margin: 0ex 0em 0ex 0em; padding: 0.1ex 4% 0.2ex 0em; /* Avoiding horizontal scroll bars. */ list-style-type: none; background-color: #0d4988; color: #e4edf3; } #SUBNAV li { float: right; } #SUBNAV li a { display: block; margin: 0em; padding: 0ex 0.5em; background-color: inherit; color: #e4edf3; } #SIMPLESEARCH { position: absolute; top: 5ex; right: 1em; } #CONTENT { clear: both; } #NAV a:hover, #PORTAL_1 #OVERVIEW a, #PORTAL_2 #OVERVIEW a, #PORTAL_3 #OVERVIEW a, #PORTAL_4 #ADMINISTRATION a, #PORTAL_5 #DEVELOPMENT a, #PORTAL_6 #DEVELOPMENT a, #PORTAL_7 #DEVELOPMENT a, #PORTAL_11 #INSTALLATION a, #PORTAL_15 #ADMINISTRATION a, #PORTAL_16 #ADMINISTRATION a { background-color: #0d4988; color: #e4edf3; padding-bottom: 4px; border-color: gray; } #SUBNAV a:hover, #PORTAL_2 #SEARCH a, #PORTAL_3 #BOOKS a, #PORTAL_6 #WAREHOUSING a, #PORTAL_7 #UNSTRUCTURED a, #PORTAL_15 #INTEGRATION a, #PORTAL_16 #GRID a { position: relative; top: 2px; background-color: white; color: #0a4e89; } PK3( # PK"+AOEBPS/dcommon/bookicon.gif:GIF87a!!!)))111999BBBJJJRRRZZZccckkksss{{{ޭ{{ZRRcZZRJJJBB)!!skRB9{sν{skskcZRJ1)!֭ƽ{ZZRccZJJBBB999111)JJ9BB1ZZB!!ﭵBJJ9BB!!))Jk{)1!)BRZJ{BsR!RRJsJ!J{s!JsBkks{RsB{J{c1RBs1ZB{9BJ9JZ!1BJRRs!9R!!9Z9!1)J19JJRk19R1Z)!1B9R1RB!)J!J1R)J119!9J91!9BkksBBJ119BBR!))9!!!JB1JJ!)19BJRZckތ1)1J9B,H*\hp >"p`ƒFF "a"E|ժOC&xCRz OBtX>XE*O>tdqAJ +,WxP!CYpQ HQzDHP)T njJM2ꔀJ2T0d#+I:<жk 'ꤱF AB @@nh Wz' H|-7f\A#yNR5 /PM09u UjćT|q~Yq@&0YZAPa`EzI /$AD Al!AAal 2H@$ PVAB&c*ؠ p @% p-`@b`uBa l&`3Ap8槖X~ vX$Eh`.JhAepA\"Bl, :Hk;PKx[?:PK"+AOEBPS/dcommon/conticon.gif^GIF87a!!!)))111999BBBJJJRRRZZZccckkksss{{{ZRR޽{{ssskkkcccZ991ccRZZBBJJZck)19ZcsBJZ19J!k{k)Z1RZs1!B)!J91{k{)J!B!B911)k{cs!1s!9)s!9!B!k)k1c!)Z!R{9BJcckZZcBBJ99B119{{!!)BBRBBZ!))999R99Z!!999c1!9!)19B1)!B9R,  oua\h2SYPa aowwxYi 9SwyyxxyYSd $'^qYȵYvh ч,/?g{н.J5fe{ڶyY#%/}‚e,Z|pAܠ `KYx,ĉ&@iX9|`p ]lR1khٜ'E 6ÅB0J;t X b RP(*MÄ!2cLhPC <0Ⴁ  $4!B 6lHC%<1e H 4p" L`P!/,m*1F`#D0D^!AO@..(``_؅QWK>_*OY0J@pw'tVh;PKp*c^PK"+AOEBPS/dcommon/blafdoc.cssL@charset "utf-8"; /* Copyright 2002, 2011, Oracle and/or its affiliates. All rights reserved. Author: Robert Crews Version: 2011.10.7 */ body { font-family: Tahoma, sans-serif; /* line-height: 125%; */ color: black; background-color: white; font-size: small; } * html body { /* http://www.info.com.ph/~etan/w3pantheon/style/modifiedsbmh.html */ font-size: x-small; /* for IE5.x/win */ f\ont-size: small; /* for other IE versions */ } h1 { font-size: 165%; font-weight: bold; border-bottom: 1px solid #ddd; width: 100%; } h2 { font-size: 152%; font-weight: bold; } h3 { font-size: 139%; font-weight: bold; } h4 { font-size: 126%; font-weight: bold; } h5 { font-size: 113%; font-weight: bold; display: inline; } h6 { font-size: 100%; font-weight: bold; font-style: italic; display: inline; } a:link { color: #039; background: inherit; } a:visited { color: #72007C; background: inherit; } a:hover { text-decoration: underline; } a img, img[usemap] { border-style: none; } code, pre, samp, tt { font-family: monospace; font-size: 110%; } caption { text-align: center; font-weight: bold; width: auto; } dt { font-weight: bold; } table { font-size: small; /* for ICEBrowser */ } td { vertical-align: top; } th { font-weight: bold; text-align: left; vertical-align: bottom; } ol ol { list-style-type: lower-alpha; } ol ol ol { list-style-type: lower-roman; } td p:first-child, td pre:first-child { margin-top: 0px; margin-bottom: 0px; } table.table-border { border-collapse: collapse; border-top: 1px solid #ccc; border-left: 1px solid #ccc; } table.table-border th { padding: 0.5ex 0.25em; color: black; background-color: #f7f7ea; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; } table.table-border td { padding: 0.5ex 0.25em; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; } span.gui-object, span.gui-object-action { font-weight: bold; } span.gui-object-title { } p.horizontal-rule { width: 100%; border: solid #cc9; border-width: 0px 0px 1px 0px; margin-bottom: 4ex; } div.zz-skip-header { display: none; } td.zz-nav-header-cell { text-align: left; font-size: 95%; width: 99%; color: black; background: inherit; font-weight: normal; vertical-align: top; margin-top: 0ex; padding-top: 0ex; } a.zz-nav-header-link { font-size: 95%; } td.zz-nav-button-cell { white-space: nowrap; text-align: center; width: 1%; vertical-align: top; padding-left: 4px; padding-right: 4px; margin-top: 0ex; padding-top: 0ex; } a.zz-nav-button-link { font-size: 90%; } div.zz-nav-footer-menu { width: 100%; text-align: center; margin-top: 2ex; margin-bottom: 4ex; } p.zz-legal-notice, a.zz-legal-notice-link { font-size: 85%; /* display: none; */ /* Uncomment to hide legal notice */ } /*************************************/ /* Begin DARB Formats */ /*************************************/ .bold, .codeinlinebold, .syntaxinlinebold, .term, .glossterm, .seghead, .glossaryterm, .keyword, .msg, .msgexplankw, .msgactionkw, .notep1, .xreftitlebold { font-weight: bold; } .italic, .codeinlineitalic, .syntaxinlineitalic, .variable, .xreftitleitalic { font-style: italic; } .bolditalic, .codeinlineboldital, .syntaxinlineboldital, .titleinfigure, .titleinexample, .titleintable, .titleinequation, .xreftitleboldital { font-weight: bold; font-style: italic; } .itemizedlisttitle, .orderedlisttitle, .segmentedlisttitle, .variablelisttitle { font-weight: bold; } .bridgehead, .titleinrefsubsect3 { font-weight: bold; } .titleinrefsubsect { font-size: 126%; font-weight: bold; } .titleinrefsubsect2 { font-size: 113%; font-weight: bold; } .subhead1 { display: block; font-size: 139%; font-weight: bold; } .subhead2 { display: block; font-weight: bold; } .subhead3 { font-weight: bold; } .underline { text-decoration: underline; } .superscript { vertical-align: super; } .subscript { vertical-align: sub; } .listofeft { border: none; } .betadraft, .alphabetanotice, .revenuerecognitionnotice { color: #e00; background: inherit; } .betadraftsubtitle { text-align: center; font-weight: bold; color: #e00; background: inherit; } .comment { color: #080; background: inherit; font-weight: bold; } .copyrightlogo { text-align: center; font-size: 85%; } .tocsubheader { list-style-type: none; } table.icons td { padding-left: 6px; padding-right: 6px; } .l1ix dd, dd dl.l2ix, dd dl.l3ix { margin-top: 0ex; margin-bottom: 0ex; } div.infoboxnote, div.infoboxnotewarn, div.infoboxnotealso { margin-top: 4ex; margin-right: 10%; margin-left: 10%; margin-bottom: 4ex; padding: 0.25em; border-top: 1pt solid gray; border-bottom: 1pt solid gray; } p.notep1 { margin-top: 0px; margin-bottom: 0px; } .tahiti-highlight-example { background: #ff9; text-decoration: inherit; } .tahiti-highlight-search { background: #9cf; text-decoration: inherit; } .tahiti-sidebar-heading { font-size: 110%; margin-bottom: 0px; padding-bottom: 0px; } /*************************************/ /* End DARB Formats */ /*************************************/ @media all { /* * * { line-height: 120%; } */ dd { margin-bottom: 2ex; } dl:first-child { margin-top: 2ex; } } @media print { body { font-size: 11pt; padding: 0px !important; } a:link, a:visited { color: black; background: inherit; } code, pre, samp, tt { font-size: 10pt; } #nav, #search_this_book, #comment_form, #comment_announcement, #flipNav, .noprint { display: none !important; } body#left-nav-present { overflow: visible !important; } } PKʍPK"+AOEBPS/dcommon/rightnav.gif&GIF89a1ֽ筽ޭƔkZZk{Bc{,@ ) l)- $CҠҀ ! D1 #:aS( c4B0 AC8 ְ9!%MLj Z * ctypJBa H t>#Sb(clhUԂ̗4DztSԙ9ZQҀEPEPEPEPEPEPEPM=iԍP Gii c*yF 1׆@\&o!QY00_rlgV;)DGhCq7~..p&1c:u֫{fI>fJL$}BBP?JRWc<^j+χ5b[hֿ- 5_j?POkeQ^hֿ1L^ H ?Qi?z?+_xɔŪ\썽O]χ>)xxV/s)e6MI7*ߊޛv֗2J,;~E4yi3[nI`Ѱe9@zXF*W +]7QJ$$=&`a۾?]N T䏟'X)Ɣkf:j |>NBWzYx0t!* _KkoTZ?K Gc+UyڹgNuh^iSo5{\ܹ3Yos}.>if FqR5\/TӮ#]HS0DKu{($"2xִ{SBJ8=}Y=.|Tsц2UЫ%.InaegKo z ݎ3ֹxxwM&2S%';+I',kW&-"_¿_ Vq^ܫ6pfT2RV A^6RKetto^[{w\jPZ@ޢN4/XN#\42j\(z'j =~-I#:q[Eh|X:sp* bifp$TspZ-}NM*B-bb&*xUr#*$M|QWY ~p~- fTED6O.#$m+t$˙H"Gk=t9r娮Y? CzE[/*-{c*[w~o_?%ƔxZ:/5𨴟q}/]22p qD\H"K]ZMKR&\C3zĽ[PJm]AS)Ia^km M@dК)fT[ijW*hnu Ͳiw/bkExG£@f?Zu.s0(<`0ֹoxOaDx\zT-^ѧʧ_1+CP/p[w 9~U^[U<[tĽwPv[yzD1W='u$Oeak[^ |Gk2xv#2?¹TkSݕ| rݞ[Vi _Kz*{\c(Ck_܏|?u jVڔ6f t?3nmZ6f%QAjJf9Rq _j7Z-y.pG$Xb]0')[_k;$̭?&"0FOew7 z-cIX岛;$u=\an$ zmrILu uٞ% _1xcUW%dtÀx885Y^gn;}ӭ)場QEQ@Q@Q@Q@Q@Q@!4xPm3w*]b`F_931˜[ן+(> E ly;<;MF-qst+}DH @YKlLmؤciN<|]IU)Lw(8t9FS(=>og<\Z~u_+X1ylsj'eՃ*U3`C!N9Q_WܱhKc93^ua>H ƕGk=8~e#_?{ǀe-[2ٔ7;=&K挑5zsLdx(e8#{1wS+ΝVkXq9>&yஏh$zq^0~/j@:/«Vnce$$uoPp}MC{$-akH@ɫ1O !8R9s5ԦYmϧ'OUṡ5T,!Ԛ+s#1Veo=[)g>#< s)ƽُA^䠮ωFUj(ǩ|N3Jڷ睁ϱuږZYGOTsI<&drav?A^_f׻B$,O__ԿC`it{6>G׈C~&$y؎v1q9Sc1fH[ѽ>,gG'0'@Vw,BO [#>ﱺg5ΒFVD%Yr:O5 Tu+O멃]ی38Ze}R&ѝ_xzc1DXgس;<,_,{ƽY'AS#oF.M#~cBuEx7G+Y)(5q+GCV;qF+CLQ)qEC&6z𿊘z}?&w=+)??&\g{;V??׻xGœdٿ׼-Nc')3K]N)iLTӿCdb7Q^a N sd>Fz[0S^s'Zi 77D}kWus ab~~H(>.fif9,~|Jk;YN3H8Y(t6Q݉k͇_÷Z+2߄&[ +Tr^藺97~c܎=[f1RrBǓ^kEMhxYVm<[џ6| kqbѱ| YA{G8p?\UM7Z66 g1U1igU69 u5Pƪ:VVZC=[@ҹ¨$kSmɳО\vFz~i3^a Osŧυ9Q}_3 όO{/wgoet39 vO2ea;Ύ7$U#?k+Ek&dpzbӱ+TaB0gN{[N7Gי}U7&@?>Fz~E!a@s ?'67XxO*!?qi]֏TQN@tI+\^s8l0)2k!!iW8F$(yOּT.k,/#1:}8uT˾+5=O/`IW G֯b.-<= HOm;~so~hW5+kS8s.zwE| ?4ӿw/K N 9?j(#0UT` Wzw}:_*9m>󑓀F?ELzv=8q:=WgJ`nDr Zе<ֹ](Q@Q@Q@Q@Q@Q@Q@Q@ 'IdC0EYJVcMty_~u+Sw-aO n<[YJgL#6i g5ЖDZ14cʝ!!\/M}/_AYR__>oC? _?7_G#RERW쏞KB}JxGSkǕA pƱơP m]hwB7U$Zq M95"3q1ioATߚ{g.t uu2k=;h#YB= fgS :TdLԃ!44mFK{Hrd^7oz|BVr<{)6AXգV»|>*/hS܏z͆OM=Εq (s|s׊LKQI :9NJ)P+!ʣoAF>+=@I}"x/}۠1aנc¹4emC:>p_xWKX` >R3_S½èųp3޺u3N e یbmͺ<_ mnݮ1Op?Gm)Qb%N585'%Ahs\6yw!"&Ɨ._wk)}GP;Z!#\"< *oƾ\)}N>"լ/~]Lg}pBG X?<zZ#x69S=6) jzx=y9O&>+e!!? ?s~k5Gʏ)?*ce7Ox~k5􇔾Q/e7/Ԑ#3OgNC0] ;_FiRl>Q.g>!%k#ú:Kn'&}?U@\pџPtp)v<{_i}Oվֲ3XIYIx~b<D?(=_JXH=bbi=Oh?_ C_O)}oW쏜? %Ƶ;-RYFi`wۭ{ϖZMtQ$"c_+ԃx1*0b;ԕ݋ESQEQEQEQEQEQEQEQEQEQZ(1F)h1K@XLRE&9P (bf{RӨ&)PEPEPbԴPGKZ(iإbn(:A%S0(-&)P+ ڎԴP11F)h&:LRmQ@Q@Š(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((PKje88PK"+AOEBPS/dcommon/help.gif!GIF89a1εֵ֜֜{kZsBc{,@ )sƠTQ$8(4ʔ%ŌCK$A HP`$h8ŒSd+ɡ\ H@%' 6M HO3SJM /:Zi[7 \( R9r ERI%  N=aq   qƦs *q-n/Sqj D XZ;PKއ{&!PK"+A OEBPS/toc.htmh Table of Contents

Contents

List of Examples

List of Figures

List of Tables

Title and Copyright Information

Preface

What's New in Oracle Multimedia?

1 Introduction to Oracle Multimedia

2 Oracle Multimedia Application Development

3 Oracle Multimedia Photo Album Sample Applications

4 Oracle Multimedia Code Wizard Sample Application for the PL/SQL Gateway

5 Oracle Multimedia Java API Sample Application

6 Working with Metadata in Oracle Multimedia Images

7 Extending Oracle Multimedia

8 Oracle Multimedia Tuning Tips for DBAs

9 Oracle Multimedia Examples

A Oracle Multimedia Sample Applications

B Managing Oracle Multimedia Installations

Glossary

Index

PKX֙hhPK"+AOEBPS/im_newftrs.htm What's New in Oracle Multimedia?

What's New in Oracle Multimedia?

This document summarizes new features, enhancements, APIs, and Oracle Database support introduced with Oracle Multimedia in the current release. It also describes a feature that is no longer being enhanced, beginning with the current release.

New Features for Release 11.2

Oracle Database 11g Release 2 (11.2) added new features for Oracle Multimedia, and new enhancements for Oracle Multimedia DICOM. The following subsections list these features and enhancements.

See Oracle Multimedia Reference for more information about the Oracle Multimedia features. See Oracle Multimedia DICOM Developer's Guide for more information about the DICOM enhancements.


See Also:

Oracle Multimedia Mid-Tier Java API Reference for reference information about the new mid-tier Java API

Oracle Multimedia DICOM Java API Reference for reference information about the Oracle Multimedia DICOM Java API


Oracle Multimedia Features

The following new features for Oracle Multimedia are described in Oracle Multimedia Reference:

  • New constructor functions for BLOBs and other sources, for these object types:

    • ORDAudio

    • ORDDoc

    • ORDImage

    • ORDVideo

  • Support for image watermarking

  • New image processing operators:

    • nometadata

    • sharpen

    • transparencyFillColor

  • Support for the CMYK content format

Oracle Multimedia DICOM Enhancements

The following enhancements for Oracle Multimedia DICOM are described in Oracle Multimedia DICOM Developer's Guide:

  • Recursive calls within constraint definitions

  • Limiting the list of DICOM attributes for extraction

  • Oracle Multimedia Mid-Tier Java API

  • DICOM value locator type syntax

  • Wildcard character syntax

  • New preference parameters to define run-time behavior:

    • BINARY_SKIP_INVALID_ATTR

    • MANDATE_ATTR_TAGS_IN_STL

    • MAX_RECURSION_DEPTH

    • SPECIFIC_CHARACTER_SET

    • SQ_WRITE_LEN

  • DICOM to AVI conversion

  • DEFLATE compression format

  • RLE compression format

  • YBR photometric interpretation

  • Encoding of multibit monochrome raw content

  • Oracle Data Pump Utilities support for the DICOM data model repository

Status of ORDImage Support for DICOM in Release 11.2

Beginning with Oracle Database 11g, Release 2 (11.2), the DICOM support in ORDImage objects that was introduced in Oracle Database 10g, Release 2 (10.2) was not enhanced. The DICOM support in ORDImage objects is still available in Release 11.2, but Oracle recommends taking the following actions for medical imaging applications.

  • For new applications:

    Use the new DICOM support that was introduced in Oracle Database 11g, Release 1 (11.1).

  • For existing applications that use the DICOM support in ORDImage objects:

    Migrate to the new DICOM support that was introduced in Release 11.1.

See Section 1.6.4 for more information about the status of this feature and its enhancements.


See Also:

Oracle Multimedia DICOM Developer's Guide for complete information about Oracle Multimedia DICOM features and enhancements


PK) PK"+AOEBPS/ch_cdwizapp.htm Oracle Multimedia Code Wizard Sample Application for the PL/SQL Gateway

4 Oracle Multimedia Code Wizard Sample Application for the PL/SQL Gateway

This chapter describes the Oracle Multimedia Code Wizard sample application. The Oracle Multimedia Code Wizard sample application for the PL/SQL Gateway is a media upload and retrieval Web application that uses these Oracle Multimedia image, audio, video, and heterogeneous media object types.

This chapter assumes the following:

  • You are familiar with developing PL/SQL applications using the PL/SQL Gateway.

  • You have installed and configured the Oracle Multimedia Code Wizard sample application.

You can install the Oracle Multimedia Code Wizard sample application from the Oracle Database Examples media, which is available for download from the Oracle Technology Network (OTN). After installing the Oracle Database Examples media, the sample application files and README.txt file are located at:

<ORACLE_HOME>/ord/http/demo/plsgwycw (on Linux and UNIX)

<ORACLE_HOME>\ord\http\demo\plsgwycw (on Windows)

This chapter describes how to run the Code Wizard Photo Album application. See the README.txt file for additional requirements and instructions on installing and configuring this sample application.


Note:

This discussion assumes that the Code Wizard has been installed in the ORDSYS schema.

This chapter includes these sections:

More Sample Applications

See these chapters for more sample applications:

Chapter 3 describes these Photo Album sample Web applications, which use PL/SQL scripts, Java servlet files, and JSP files to demonstrate various ways to upload and retrieve media using Oracle Multimedia object types:

  • Oracle Multimedia PL/SQL Web Toolkit Photo Album application (Section 3.1)

  • Oracle Multimedia Java Servlet Photo Album application (Section 3.2)

  • Oracle Multimedia JSP Photo Album application (Section 3.3)

Chapter 5 describes the Oracle Multimedia Java API sample application. This sample application lets you retrieve, save, play, and delete multimedia data from the Oracle Database sample schemas using Oracle Multimedia Java classes and Oracle Multimedia object types.

4.1 Running the Code Wizard Sample Application

To use the Code Wizard sample application to create and test media access procedures, you must perform these steps:

  1. Create a new database access descriptor (DAD) or choose an existing DAD for use with the Code Wizard.

  2. Authorize use of the DAD using the Code Wizard's administration function.

  3. Create and test media upload and retrieval procedures.

The following sections describe these steps and other related topics in more detail.

4.2 Description of the Code Wizard Sample Application

The Oracle Multimedia Code Wizard sample application lets you create PL/SQL stored procedures for the PL/SQL Gateway to upload and retrieve media data (images, audio, video, and general media) stored in a database using these Oracle Multimedia object types and their respective methods:

  • ORDImage

  • ORDAudio

  • ORDVideo

  • ORDDoc

The Code Wizard guides you through a series of self-explanatory steps to create either a media retrieval procedure or a media upload procedure. You can create and compile standalone media access procedures. Or, you can create the source of media access procedures for inclusion in a PL/SQL package. Finally, after creating media access procedures, you can customize them to meet your specific application requirements.

These processes are similar to how the Oracle Multimedia PL/SQL Web Toolkit Photo Album application uses the insert_new_photo procedure as the image upload procedure, and the deliver_media procedure as the image retrieval procedure (see Section 3.1).

The following subsections describe how to use the Code Wizard application:

4.2.1 Creating a New DAD or Choosing an Existing DAD

To create media upload or retrieval procedures, you must select one or more DADs for use with the Code Wizard. To prevent the unauthorized browsing of schema tables and to prevent the unauthorized creation of media access procedures, you must authorize each DAD using the Code Wizard administration function. Depending on your database and application security requirements, you can create and authorize one or more new DADs specifically for use with the Code Wizard. Or, you can authorize the use of one or more existing DADs.

Oracle recommends that any DAD authorized for use with the Code Wizard employ some form of user authentication mechanism. The simplest approach is to create or use a DAD that uses database authentication. To use this approach, select Basic Authentication Mode and omit the password in the DAD specification. Alternatively, you can use a DAD that specifies an existing application-specific authentication mechanism.


See Also:

Oracle Fusion Middleware Administrator's Guide for Oracle HTTP Server in the Oracle Fusion Middleware Online Documentation Library for more information about configuring DADs


The following example describes how to create a DAD that enables you to create and test media upload and retrieval procedures in the SCOTT schema.


Note:

To test media upload procedures, you must specify the name of a document table in the DAD. When testing an upload procedure, you can choose either the DAD you used to create the procedure or the DAD you used to access the application. You can choose a document table name when you create a DAD, edit a DAD to specify the document table name at a later time, or use an existing DAD that specifies a document table name. This example shows how to specify the document table name when you create the DAD.

  1. Set your Web browser to the Oracle HTTP Server Home page. Select PL/SQL Properties in the Administration page to open the mod_plsql Services page.

  2. Scroll to the DAD Status section on the mod_plsql Services page. Then, click Create to open the DAD Type page.

  3. Select the DAD type to be General. Then, click Next to open the Database Connection page.

  4. Enter /scottcw in the DAD Name field. Enter SCOTT for the database account, and leave the password blank. Enter the connection information in the Database Connectivity Information section. Enter ORDCWPKG.MENU in the Default page field, and leave the other fields blank. Then, click Next to open the Document, Alias, and Session page.

  5. Enter MEDIA_UPLOAD_TABLE for the Document Table on the Document, Alias, and Session page. Then, click Apply.

  6. Restart Oracle HTTP Server for the changes to take effect.

4.2.2 Authorizing a DAD

To authorize a DAD for use with the Code Wizard, perform these steps:

  1. Enter the Code Wizard's administration URL into the location bar for your browser. For example:

    http://<host-name>:<port-number>/ordcwadmin
    
  2. Enter the user name and password when prompted by the browser.

  3. Select DAD authorization from the Main menu, as shown in Figure 4-1. Then, click Next.

    Figure 4-1 Main Menu for the Code Wizard

    Description of Figure 4-1 follows
    Description of "Figure 4-1 Main Menu for the Code Wizard "

  4. Enter the name of the DAD you want to authorize along with the user name, as shown in Figure 4-2. Then, click Apply.

    Figure 4-2 Authorize the SCOTTCW DAD

    Description of Figure 4-2 follows
    Description of "Figure 4-2 Authorize the SCOTTCW DAD"


    Note:

    Duplicate DADs are not permitted, and each authorized DAD must indicate which database schema the user is authorized to access with the Code Wizard, using the DAD. Use this same page to delete the authorization for any existing DADs that no longer require the Code Wizard.

  5. Review the updated list of DADs that are authorized to use the Oracle Multimedia Code Wizard, as shown in Figure 4-3. Then, click Done.

    Figure 4-3 List of Authorized DADs

    Description of Figure 4-3 follows
    Description of "Figure 4-3 List of Authorized DADs"

  6. Select Logout from the Main menu to log out (clear HTTP authentication information), then click Next. The log out operation redirects the request to the PL/SQL Gateway built-in logmeoff function.


See Also:

Oracle Fusion Middleware User's Guide for mod_plsql in the Oracle Fusion Middleware Online Documentation Library


4.2.3 Creating and Testing Media Upload and Retrieval Procedures

After you have completed the setup tasks (as described in Section 4.2.1, Section 4.2.2, and the README.txt file), you are ready to run this application.

To start the Code Wizard, follow these steps:

  1. Enter the appropriate URL into the address field of your Web browser.

    For example:

    http://<hostname>:<port-number>/scottcw

    or

    http://<hostname>:<port-number>/mediadad/ordcwpkg.menu

  2. Enter the user name and password when prompted by the browser. The Main menu page of the Oracle Multimedia Code Wizard for the PL/SQL Gateway is displayed, as shown in Figure 4-4.

    Figure 4-4 Use the SCOTTCW DAD

    Description of Figure 4-4 follows
    Description of "Figure 4-4 Use the SCOTTCW DAD"

  3. If the DAD is configured specifically for use with the Code Wizard, enter the DAD name. To use another DAD, enter the DAD name along with the Code Wizard package name and Main menu procedure name (ORDCWPKG.MENU) after the DAD name.

  4. After logging in, you can log out (clear HTTP authentication information) at any time by selecting Logout from the Main menu, then clicking Next. The logout operation redirects the request to the PL/SQL Gateway's built-in logmeoff function.


    See Also:

    Oracle Fusion Middleware User's Guide for mod_plsql in the Oracle Fusion Middleware Online Documentation Library


To create a media upload procedure (see Section 4.2.4) or a media retrieval procedure (see Section 4.2.5), select the appropriate option from the Main menu page, then click Next. The Code Wizard then guides you through a series of self-explanatory steps to create the procedure.

If you create a standalone media upload or retrieval procedure, you will have the opportunity to view the contents of the procedure and test it. Section 4.3 and Section 4.4, respectively, include sample sessions that demonstrate how to create and test a media upload procedure and a media retrieval procedure.

4.2.4 Creating a Media Upload Procedure

To create a media upload procedure using the Oracle Multimedia Code Wizard for the PL/SQL Gateway, perform these steps:

  1. Select Create media upload procedure from the Main menu page, as shown in Figure 4-5. Then, click Next.

    Figure 4-5 Create a Media Upload Procedure

    Description of Figure 4-5 follows
    Description of "Figure 4-5 Create a Media Upload Procedure"

  2. Select PHOTOS and Standalone procedure from Step 1: Select database table and procedure type, as shown in Figure 4-6. Then, click Next.

    Figure 4-6 Media Upload Step 1: Select Database Table and Procedure Type

    Description of Figure 4-6 follows
    Description of "Figure 4-6 Media Upload Step 1: Select Database Table and Procedure Type"

  3. Select Use existing document table from Step 2: Select PL/SQL Gateway document upload table, as shown in Figure 4-7, because the SCOTTCW DAD is configured to use this document table. Then, click Next.

    Figure 4-7 Media Upload Step 2: Select PL/SQL Gateway Document Upload Table

    Description of Figure 4-7 follows
    Description of "Figure 4-7 Media Upload Step 2: Select PL/SQL Gateway Document Upload Table"

  4. Check PHOTO (ORDIMAGE), select ID (Primary key), and select Conditional insert or update from Step 3: Select data access and media column(s), as shown in Figure 4-8. Then, click Next.

    Figure 4-8 Media Upload Step 3: Select Data Access and Media Column(s)

    Description of Figure 4-8 follows
    Description of "Figure 4-8 Media Upload Step 3: Select Data Access and Media Column(s)"

  5. Check DESCRIPTION, accept the default procedure name, UPLOAD_PHOTOS_PHOTO, and select Create procedure in the database from Step 4: Select additional columns and procedure name, as shown in Figure 4-9. Then, click Next.

    Figure 4-9 Media Upload Step 4: Select Additional Columns and Procedure Name

    Description of Figure 4-9 follows
    Description of "Figure 4-9 Media Upload Step 4: Select Additional Columns and Procedure Name"

  6. Review the options you selected from Step 5: Review selected options, as shown in Figure 4-10. If the options selected are correct, click Finish.

    Figure 4-10 Media Upload Step 5: Review Selected Options

    Description of Figure 4-10 follows
    Description of "Figure 4-10 Media Upload Step 5: Review Selected Options"

  7. The message Procedure created successfully: UPLOAD_PHOTOS_PHOTO is displayed on the Compile procedure and review generated source page, as shown in Figure 4-11.

    Figure 4-11 Compiled Upload Procedure with Success Message

    Description of Figure 4-11 follows
    Description of "Figure 4-11 Compiled Upload Procedure with Success Message"

    To review the compiled PL/SQL source code in another window, click View (see Example 4-1 for a copy of the generated upload procedure). Assuming you have configured the SCOTTCW DAD and specified MEDIA_UPLOAD_TABLE as the document table, in the DAD: field, the DAD name scottcw is displayed by default.

    To test the PL/SQL procedure created, click Test.

    The Oracle Multimedia Code Wizard: Template Upload Form is displayed in another window.

  8. Enter the value 1 in the ID field on the Oracle Multimedia Code Wizard: Template Upload Form window. Click Browse... to find and select the image you want to upload in the PHOTO field, and enter a brief description of the image to be uploaded in the DESCRIPTION field, as shown in Figure 4-12. Then, click Upload media.

    Figure 4-12 Template Upload Form for the Code Wizard

    Description of Figure 4-12 follows
    Description of "Figure 4-12 Template Upload Form for the Code Wizard"

    The image is uploaded into the table row, and this message is displayed:

    Media uploaded successfully.

  9. Return to the Compile procedure and review generated source page. If you are finished testing, click Done to return to the Main menu page.

4.2.5 Creating a Media Retrieval Procedure

To create a media retrieval procedure using the Oracle Multimedia Code Wizard for the PL/SQL Gateway, perform these steps:

  1. Select Create media retrieval procedure from the Main menu page, as shown in Figure 4-13. Then, click Next.

    Figure 4-13 Create a Media Retrieval Procedure

    Description of Figure 4-13 follows
    Description of "Figure 4-13 Create a Media Retrieval Procedure"

  2. Select PHOTOS and Standalone procedure from Step 1: Select database table and procedure type, as shown in Figure 4-14. Then, click Next.

    Figure 4-14 Media Retrieval Step 1: Select Database Table and Procedure Type

    Description of Figure 4-14 follows
    Description of "Figure 4-14 Media Retrieval Step 1: Select Database Table and Procedure Type"

  3. Select PHOTO (ORDIMAGE) and ID (Primary key) from Step 2: Select media column and key column, as shown in Figure 4-15. Then, click Next.

    Figure 4-15 Media Retrieval Step 2: Select Media Column and Key Column

    Description of Figure 4-15 follows
    Description of "Figure 4-15 Media Retrieval Step 2: Select Media Column and Key Column"

  4. Accept the default procedure name, GET_PHOTOS_PHOTO, the default parameter name, MEDIA_ID, and Create procedure in the database from Step 3: Select procedure name and parameter name, as shown in Figure 4-16. Then, click Next.

    Figure 4-16 Media Retrieval Step 3: Select Procedure Name and Parameter Name

    Description of Figure 4-16 follows
    Description of "Figure 4-16 Media Retrieval Step 3: Select Procedure Name and Parameter Name"

  5. Review the options you selected from Step 4: Review Selected Options, as shown in Figure 4-17. If the options selected are correct, click Finish.

    Figure 4-17 Media Retrieval Step 4: Review Selected Options

    Description of Figure 4-17 follows
    Description of "Figure 4-17 Media Retrieval Step 4: Review Selected Options"

  6. The message Procedure created successfully: GET_PHOTOS_PHOTO is displayed in the Compile procedure and review generated source page, as shown in Figure 4-18.

    Figure 4-18 Compiled Retrieval Procedure with Success Message

    Description of Figure 4-18 follows
    Description of "Figure 4-18 Compiled Retrieval Procedure with Success Message"

    To review the compiled PL/SQL source code in another window, click View (see Example 4-2 for a copy of the generated retrieval procedure).

    To test the PL/SQL procedure created, assuming you have an image loaded in the database with an ID value of 1, enter the value 1 for the Key parameter (MEDIA_ID), then click Test.

    The image is retrieved from the table row and displayed in another window.

  7. Click Done to return to the Main menu page.

4.2.6 Using the PL/SQL Gateway Document Table

All files uploaded using the PL/SQL Gateway are stored in a document table. Media upload procedures created by the Code Wizard automatically move uploaded media from the specified document table to the application's table. To avoid transient files from appearing temporarily in a document table used by another application component, use a document table that is not being used to store documents permanently.

Specify the selected document table in the application's database access descriptor (DAD). If the DAD specifies a different document table, create a new DAD for media upload procedures. If you choose to create a new document table, the Code Wizard creates a table with the following format:

CREATE TABLE document-table-name
  ( name           VARCHAR2(256) UNIQUE NOT NULL,
    mime_type      VARCHAR2(128),
    doc_size       NUMBER,
    dad_charset    VARCHAR2(128),
    last_updated   DATE,
    content_type   VARCHAR2(128),
    blob_content   BLOB )
-- 
-- store BLOBs as SecureFile LOBs
-- 
LOB(blob_content)  STORE AS SECUREFILE;

See Also:

Oracle Fusion Middleware User's Guide for mod_plsql in the Oracle Fusion Middleware Online Documentation Library for more information about file upload and document tables


4.2.7 How Time Zone Information Is Used to Support Browser Caching

User response times are improved and network traffic is reduced if a browser can cache resources received from a Web server and subsequently use those cached resources to satisfy future requests. This section describes at a very high level, how the browser caching mechanism works and how the Code Wizard utility package is used to support that mechanism. When reading this discussion, keep in mind that all HTTP date and time stamps are expressed in Coordinated Universal Time (UTC).

All HTTP responses include a Date header, which indicates the date and time when the response was generated. When a Web server sends a resource in response to a request from a browser, it can also include the Last-Modified HTTP response header, which indicates the date and time when the requested resource was last modified. The Last-Modified header must not be later than the Date header.

After receiving and caching a resource, if a browser must retrieve the same resource again, it sends a request to the Web server with the If-Modified-Since request header specified as the value of the Last-Modified date, which was returned by the application server when the resource was previously retrieved and cached. When the Web server receives the request, it compares the date in the If-Modified-Since request header with the last update time of the resource. Assuming the resource still exists, if the resource has not changed since it was cached by the browser, the Web server responds with an HTTP 304 Not Modified status with no response body, which indicates that the browser can use the resource currently stored in its cache. Assuming again that the resource still exists, if the request does not include an If-Modified-Since header or if the resource has been updated since it was cached by the browser, the Web server responds with an HTTP 200 OK status and sends the resource to the browser.

The ORDImage, ORDAudio, ORDVideo, and ORDDoc objects all possess an updateTime attribute stored as a DATE in the embedded ORDSource object. Although the DATE data type has no support for time zones or daylight savings time, the Oracle9i and later database versions do support time zones and also provide functions for converting a DATE value stored in a database to UTC.

When a response is first returned to a browser, a media retrieval procedure sets the Last-Modified HTTP response header based on the updateTime attribute. If a request for media data includes an If-Modified-Since header, the media retrieval procedure compares the value with the updateTime attribute and returns an appropriate response. If the resource in the browser's cache is still valid, an HTTP 304 Not Modified status is returned with no response body. If the resource has been updated since it was cached by the browser, then an HTTP 200 OK status is returned with the media resource as the response body.Media retrieval procedures created by the Code Wizard call the utility package to convert a DATE value stored in the database to UTC. The utility package uses the time zone information stored with an Oracle9i or later database and the date and time functions to convert database date and time stamps to UTC. To ensure the resulting date conforms to the rule for the Last-Modified date described previously, the time zone information must be specified correctly.


See Also:


4.3 Sample Session 1: Using Images

The following sample session uses the SCOTT schema to demonstrate the creation of image media upload and retrieval procedures. To use a different schema, substitute a different schema name and password. Or, if you have changed the password for the SCOTT schema, use your new password.


See Also:

Oracle Database Security Guide for more information about creating secure passwords


This sample session assumes the Oracle Multimedia Code Wizard has been installed in the ORDSYS schema.

Perform these steps:

Step 1   Create a table to store images for the application by starting SQL*Plus and connecting to the SCOTT (or other) schema in the database.

For example:

sqlplus SCOTT [@<connect_identifer>]

Enter password: password

SQL> CREATE TABLE cw_images_table( id NUMBER PRIMARY KEY,
                                  description VARCHAR2(30) NOT NULL,
                                  location VARCHAR2(30),
                                  image ORDSYS.ORDIMAGE )
--
-- store media as SecureFile LOBs
--
LOB(image.source.localdata)  STORE AS SECUREFILE;
Step 2   Create the SCOTTCW DAD to be used to create the procedures.
  1. Set your Web browser to the Oracle HTTP Server Home page. Select PL/SQL Properties in the Administration page to open the mod_plsql Services page.

  2. On the mod_plsql Services page, scroll to the DAD Status section. Then, click Create to open the DAD Type page.

  3. Select the DAD type to be General. Then, click Next to open the Database Connection page.

  4. Enter /scottcw in the DAD Name field. Enter SCOTT for the database account, and leave the password blank. Enter the connection information in the Database Connectivity Information section. Enter ORDCWPKG.MENU in the Default page field, and leave the other fields blank. Then, click Next to open the Document, Alias, and Session page.

  5. On the Document, Alias, and Session page, enter MEDIA_UPLOAD_TABLE for the Document Table. Then, click Apply.

  6. Restart Oracle HTTP Server for the changes to take effect.

Step 3   Authorize the use of the SCOTTCW DAD and SCOTT schema with the Code Wizard.
  1. Enter the Code Wizard's administration URL into your browser's location bar, then enter the ORDSYS user name and password when prompted by the browser, for example:

    http://<hostname>:<port-number>/ordcwadmin
    
  2. Select the DAD authorization function from the Code Wizard's Main menu and click Next. Enter the name of the demonstration DAD, SCOTTCW, and the user name SCOTT, then click Apply. Click Done when the confirmation window is displayed.

Step 4   Change DADs to the SCOTTCW DAD.
  1. Click Change DAD from the Code Wizard's Main menu.

  2. Click Change to SCOTTCW, if it is not already selected, then click Next.

  3. Enter the user name SCOTT and the password for the user SCOTT when prompted for the user name and password, then click OK.

    The Main menu now displays the current DAD as SCOTTCW and the current schema as SCOTT.

Step 5   Create and test the media upload procedure.

Click Create media upload procedure from the Main menu, then click Next.

  1. Select the database table and procedure type.

    1. Click the CW_IMAGES_TABLE database table.

    2. Click Standalone procedure.

    3. Click Next.

  2. Select the PL/SQL document upload table.

    If there are no document tables in the SCOTT schema, the Code Wizard displays a message indicating this situation. In this case, accept the default table name provided, CW_SAMPLE_UPLOAD_TABLE, then click Next.

    If there are existing document tables, but the CW_SAMPLE_UPLOAD_TABLE is not among them, click Create new document table, accept the default table name provided, CW_SAMPLE_UPLOAD_TABLE, then click Next.

    If the CW_SAMPLE_UPLOAD_TABLE document table already exists, ensure that the Use existing document table and the CW_SAMPLE_UPLOAD_TABLE options are selected. Click Next.

  3. Select the data access and media columns.

    1. Click IMAGE (ORDIMAGE).

    2. Click ID (Primary key).

    3. Click Conditional insert or update.

    4. Click Next.

  4. Select additional columns and procedure names.

    1. Ensure that DESCRIPTION checkmarked because this column has a NOT NULL constraint. (The LOCATION column is not checkmarked by default as there are no constraints on this column.)

    2. Accept the procedure name provided, UPLOAD_CW_IMAGES_TABLE_IMAGE.

    3. Click Create procedure in the database.

    4. Click Next.

  5. Review the following selected procedure creation options that are displayed:

    Procedure type:        Standalone
    Table name:            CW_IMAGES_TABLE
    Media column(s):       IMAGE (ORDIMAGE)
    Key column:            ID
    Additional column(s):  DESCRIPTION
    Table access mode:     Conditional update or insert
    Procedure name:        UPLOAD_CW_IMAGES_TABLE_IMAGE
    Function:              Create procedure in the database
    

    Click Finish.

  6. Compile the procedure and review the generated source information.

    The Code Wizard displays this message:

    Procedure created successfully: UPLOAD_CW_IMAGES_TABLE_IMAGE
    
    1. At the option Click to display generated source:, click View to view the generated source in another window. A copy of the generated source is shown at the end of Step 5, substep 6g.

    2. Close the window after looking at the generated source.

    3. Accept the DAD: name provided, SCOTTCW, then click Test to produce another window that displays a template file upload form that you can use to test the generated procedure.

    4. To customize the template file upload form, select Save As... from your browser's File menu to save the HTML source for editing.

    5. To test the template upload form, enter this information:

      • For the ID: column, enter the number 1 as the row's primary key.

      • For the IMAGE column, click Browse... and choose an image file to upload to the database.

      • For the DESCRIPTION column, enter a brief description of the image.

      • Click Upload media.

      The Code Wizard displays a template completion window with the heading Oracle Multimedia Code Wizard: Template Upload Procedure, and, if the procedure is successful, the message: Media uploaded successfully.

    6. Close the window.

    7. Click Done on the Compile procedure and review generated source window to return to the Main menu of the Code Wizard.

    Example 4-1 shows a copy of the generated image upload procedure:

    Example 4-1 Image Upload Procedure Generated in Sample Session 1

    CREATE OR REPLACE PROCEDURE UPLOAD_CW_IMAGES_TABLE_IMAGE
      ( in_ID IN VARCHAR2,
        in_IMAGE IN VARCHAR2 DEFAULT NULL,
        in_DESCRIPTION IN VARCHAR2 DEFAULT NULL )
    AS
      local_IMAGE ORDSYS.ORDIMAGE := ORDSYS.ORDIMAGE.init();
      local_ID CW_IMAGES_TABLE.ID%TYPE := NULL;
      upload_size     INTEGER;
      upload_mimetype VARCHAR2( 128 );
      upload_blob     BLOB;
    BEGIN
      --
      -- Update the existing row.
      --
      UPDATE CW_IMAGES_TABLE mtbl
        SET mtbl.IMAGE = local_IMAGE,
            mtbl.DESCRIPTION = in_DESCRIPTION
        WHERE mtbl.ID = in_ID
        RETURN mtbl.ID INTO local_ID;
      --
      -- Conditionally insert a new row if no existing row is updated.
      --
      IF local_ID IS NULL
      THEN
        --
        -- Insert the new row into the table.
        --
        INSERT INTO CW_IMAGES_TABLE ( ID, IMAGE, DESCRIPTION )
          VALUES ( in_ID, local_IMAGE, in_DESCRIPTION );
      END IF;
      --
      -- Select Oracle Multimedia object(s) for update.
      --
      SELECT mtbl.IMAGE INTO local_IMAGE
        FROM CW_IMAGES_TABLE mtbl WHERE mtbl.ID = in_ID FOR UPDATE;
      --
      -- Store media data for the column in_IMAGE.
      --
      IF in_IMAGE IS NOT NULL
      THEN
        SELECT dtbl.doc_size, dtbl.mime_type, dtbl.blob_content INTO
               upload_size, upload_mimetype, upload_blob
          FROM CW_IMAGE_UPLOAD_TABLE dtbl WHERE dtbl.name = in_IMAGE;
        IF upload_size &gt; 0
        THEN
          dbms_lob.copy( local_IMAGE.source.localData, 
                         upload_blob, 
                         upload_size );
          local_IMAGE.setLocal();
          BEGIN
            local_IMAGE.setProperties();
          EXCEPTION
            WHEN OTHERS THEN
              local_IMAGE.contentLength := upload_size;
              local_IMAGE.mimeType := upload_mimetype;
          END;
        END IF;
        DELETE FROM CW_IMAGE_UPLOAD_TABLE dtbl WHERE dtbl.name = in_IMAGE;
      END IF;
      --
      -- Update Oracle Multimedia objects in the table.
      --
      UPDATE CW_IMAGES_TABLE mtbl
        SET mtbl.IMAGE = local_IMAGE
        WHERE mtbl.ID = in_ID;
      --
      -- Display the template completion message.
      --
      htp.print( '&lt;html&gt;' );
      htp.print( '&lt;title&gt;Oracle Multimedia Code Wizard: Template Upload
    Procedure&lt;/title&gt;' );
      htp.print( '&lt;body&gt;' );
      htp.print( '&lt;h2&gt; Oracle Multimedia Code Wizard:
    Template Upload Procedure&lt;/h2&gt;' );
      htp.print( 'Media uploaded successfully.' );
      htp.print( '&lt;/body&gt;' );
      htp.print( '&lt;/html&gt;' );
    END UPLOAD_CW_IMAGES_TABLE_IMAGE;
    

    The image upload procedure shown in Example 4-1 declares these input parameters and variables:

    1. In the declaration section, the procedure declares three input parameters: in_ID, in_IMAGE, and in_DESCRIPTION, then initializes the latter two to NULL.

    2. In the subprogram section, the following variables are declared:

      • The variable local_IMAGE is assigned the data type ORDSYS.ORDIMAGE and initialized with an empty BLOB using the ORDIMAGE.init( ) method.

      • The variable local_ID takes the same data type as the ID column in the table CW_IMAGES_TABLE and is initialized to NULL.

      • Three additional variables are declared upload_size, upload_mimetype, and upload_blob, which are later given values from comparable column names doc_size, mime_type, and blob_content from the document table CW_IMAGE_UPLOAD_TABLE, using a SELECT statement in preparation for copying the content of the image BLOB data to the ORDSYS.ORDIMAGE.source.localData attribute.

    Within the outer BEGIN...END executable statement section, the following operations are executed:

    1. Update the existing row in the table CW_IMAGES_TABLE for the IMAGE and DESCRIPTION columns and return the value of local_ID where the value of the ID column is the value of the in_ID input parameter.

    2. If the value returned of local_ID is NULL, conditionally insert a new row into the table CW_IMAGES_TABLE and initialize the instance of the ORDImage object type in the image column with an empty BLOB.

    3. Select the ORDImage object column IMAGE in the table CW_IMAGES_TABLE for update where the value of the ID column is the value of the in_ID input parameter.

    4. Select a row for the doc_size, mime_type, and blob_content columns from the document table and pass the values to the upload_size, upload_mimetype, and upload_blob variables where the value of the document table Name column is the value of the in_IMAGE input parameter.

    5. Perform a DBMS_LOB copy of the BLOB data from the table CW_IMAGE_UPLOAD_TABLE into the ORDSYS.ORDIMAGE.source.localData attribute, then call the setLocal( ) method to indicate that the image data is stored locally in the BLOB, and ORDImage methods are to look for corresponding data in the source.localData attribute.

    6. In the inner executable block, call the ORDImage setProperties( ) method to read the image data to get the values of the object attributes and store them in the image object attributes for the ORDImage object.

    7. If the setProperties( ) call fails, catch the exception and call the contentLength( ) method to get the size of the image and call the mimeType( ) method to get the MIME type of the image.

    8. Delete the row of data from the document table CW_IMAGE_UPLOAD_TABLE that was copied to the row in the table CW_IMAGES_TABLE where the value of the Name column is the value of the in_IMAGE input parameter.

    9. Update the ORDImage object IMAGE column in the table CW_IMAGES_TABLE with the content of the variable local_IMAGE where the value of the ID column is the value of the in_ID input parameter.

    10. Display a completion message on the HTML page to indicate that the media uploaded successfully using the htp.print function from the PL/SQL Web Toolkit.

Step 6   Create and test a media retrieval.

Select Create media retrieval procedure from the Main menu, then click Next.

  1. Select the database table and procedure type.

    1. Click CW_IMAGES_TABLE.

    2. Click Standalone procedure.

    3. Click Next.

  2. Select the media column and key column.

    1. Click IMAGE (ORDIMAGE).

    2. Click ID (Primary key).

    3. Click Next.

  3. Select the procedure name and parameter name.

    1. Accept the procedure name provided, GET_CW_IMAGES_TABLE_IMAGE.

    2. Accept the parameter name provided, MEDIA_ID.

    3. Click Create procedure in the database.

    4. Click Next.

  4. Review the following selected procedure creation options:

  5. Procedure type:        Standalone
    Table name:            CW_IMAGES_TABLE
    Media column(s):       IMAGE (ORDIMAGE)
    Key column:            ID
    Procedure name:        GET_CW_IMAGES_TABLE_IMAGE
    Parameter Name:        MEDIA_ID
    Function:              Create procedure in the database
    

    Click Next.

  6. Compile the procedure and review the generated source.

    The Code Wizard displays this message:

    Procedure created successfully: GET_CW_IMAGES_TABLE_IMAGE
    
    1. Click View to view the generated source in another window. Close the window after looking at the generated source. A copy of the generated source is shown at the end of Step 6, substep 5e.

    2. Review the URL format used to retrieve images using the GET_CW_IMAGES_TABLE_IMAGE procedure.

    3. Enter the number 1 as the Key parameter, then click Test to test the procedure by retrieving the image uploaded previously.

      The retrieved image is displayed in another window.

    4. Close the window.

    5. Click Done to return to the Main menu.

    Example 4-2 shows a copy of the generated image retrieval procedure:

    Example 4-2 Image Retrieval Procedure Generated in Sample Session 1

    CREATE OR REPLACE PROCEDURE GET_CW_IMAGES_TABLE_IMAGE (
     MEDIA_ID IN VARCHAR2 )
    AS
      localObject ORDSYS.ORDIMAGE;
      localBlob  BLOB;
      localBfile BFILE;
      httpStatus NUMBER;
      lastModDate VARCHAR2(256);
    BEGIN
      --
      -- Retrieve the object from the database into a local object.
      --
      BEGIN
        SELECT mtbl.IMAGE INTO localObject FROM CW_IMAGES_TABLE mtbl
          WHERE mtbl.ID = MEDIA_ID;
      EXCEPTION
        WHEN NO_DATA_FOUND THEN
          ordplsgwyutil.resource_not_found( 'MEDIA_ID', MEDIA_ID );
          RETURN;
      END;
    
      --
      -- Check the update time if the browser sent an If-Modified-Since header.
      --
      IF ordplsgwyutil.cache_is_valid( localObject.getUpdateTime() )
      THEN
        owa_util.status_line( ordplsgwyutil.http_status_not_modified );
        RETURN;
      END IF;
    
      --
      -- Figure out where the image is.
      --
      IF localObject.isLocal() THEN
        --
        -- Data is stored locally in the localData BLOB attribute.
        --
        localBlob := localObject.getContent();
        owa_util.mime_header( localObject.getMimeType(), FALSE );
        ordplsgwyutil.set_last_modified( localObject.getUpdateTime() );
        owa_util.http_header_close();
        IF owa_util.get_cgi_env( 'REQUEST_METHOD' ) &lt;&gt; 'HEAD' THEN
          wpg_docload.download_file( localBlob );
        END IF;
      ELSIF UPPER( localObject.getSourceType() ) = 'FILE' THEN
    
        --
        -- Data is stored as a file from which ORDSource creates 
        -- a BFILE.
        --
        localBfile  := localObject.getBFILE();
        owa_util.mime_header( localObject.getMimeType(), FALSE );
        ordplsgwyutil.set_last_modified( localObject.getUpdateTime() );
        owa_util.http_header_close();
        IF owa_util.get_cgi_env( 'REQUEST_METHOD' ) &lt;&gt; 'HEAD' THEN
          wpg_docload.download_file( localBfile );
        END IF;
    
      ELSIF UPPER( localObject.getSourceType() ) = 'HTTP' THEN    --
        -- The image is referenced as an HTTP entity, so we have to 
        -- redirect the client to the URL that ORDSource provides.
        --
        owa_util.redirect_url( localObject.getSource() );
      ELSE
        --
        -- The image is stored in an application-specific data
        -- source type for which no default action is available.
        --
        NULL;
      END IF;
    END GET_CW_IMAGES_TABLE_IMAGE;
    

    The image retrieval procedure shown in Example 4-2 declares these input parameters and variables:

    1. In the declaration section, the procedure declares one input parameter: MEDIA_ID.

    2. In the subprogram section, the following variables are declared:

      • The variable localObject is assigned the data type ORDSYS.ORDIMAGE.

      • The variable localBlob is a BLOB data type, the variable localBfile is a BFILE data type, httpStatus is a NUMBER, and lastModDate is a VARCHAR2 with a maximum size of 256 characters.

    Within the outer BEGIN...END executable statement section, the following operations are executed:

    1. Select the ORDImage object column IMAGE in the table CW_IMAGES_TABLE where the value of the ID column is the value of the MEDIA_ID input parameter.

    2. In the inner executable block, when no data is found, raise an exception and call the resource_not_found function of the PL/SQL Gateway and get the value of the MEDIA_ID input parameter.

    3. Check the update time if the browser sent an If-Modified-Since header by calling the getUpdateTime( ) method passed into the cache_is_valid function of the PL/SQL Gateway.

    4. If the cache is valid, send an HTTP status code to the client using the PL/SQL Web Toolkit owa_util package status_line procedure passing in the call to the http_status_not_modified function.

    5. Determine where the image data is stored; call the ORDImage isLocal( ) method, which returns a Boolean expression of true if the image data is stored locally in the BLOB, then get the handle to the local BLOB.

      • If the value is true, assign the variable localBlob the ORDImage getContent( ) method to get the handle of the local BLOB containing the image data.

      • Call the ORDImage getMimeType( ) method to determine the image's MIME type and pass this to the owa_util.mime_header procedure and keep the HTTP header open.

      • Call the ORDImage getUpdateTime( ) method to get the time the image was last modified and pass this to the ordplsgwyutil.set_last_modified procedure.

      • Close the HTTP header by calling the owa_util.http_header_close( ) procedure.

      • Call the owa_util.get_cgi_env procedure and if the value of the request method is not HEAD, then use the wpg_docload.download_file procedure to pass in the value of localBlob that contains the LOB locator of the BLOB containing the image data to download the image from the database.

    6. If the ORDImage isLocal( ) method returns false, call the ORDImage getSourceType( ) method to determine if the value is FILE; if so, then the image data is stored as an external file on the local file system. Then, get the LOB locator of the BFILE containing the image data.

      • Assign the variable localBfile the ORDImage getBfile( ) method to get the LOB locator of the BFILE containing the image data.

      • Call the ORDImage getMimeType( ) method to determine the image's MIME type and pass this to the owa_util.mime_header procedure and keep the HTTP header open.

      • Call the ORDImage getUpdateTime( ) method to get the time the image was last modified and pass this to the ordplsgwyutil.set_last_modified procedure.

      • Close the HTTP header by calling the owa_util.http_header_close() procedure.

      • Call the owa_util.get_cgi_env procedure and if the value of the request method is not HEAD, then use the wpg_docload.download_file procedure to pass in the value of localBfile that contains the LOB locator of the BFILE containing the image data to download the image from the file.

    7. If the ORDImage isLocal( ) method returns false, call the ORDImage getSourceType( ) method to determine if the value is HTTP; if so, then the image data is stored at an HTTP URL location, which then redirects the client to the URL that ORDSource provides using the owa_util.redirect_url procedure.

    8. If the ORDImage isLocal( ) method returns false, call the ORDImage getSourceType( ) method to determine if the value is FILE or HTTP; if it is neither, then the image is stored in an application-specific data source type that is not recognized or supported by Oracle Multimedia.

4.4 Sample Session 2: Using Multiple Object Columns

The following sample session uses the SCOTT schema to demonstrate the creation of a multiple media (multiple Oracle Multimedia object columns) upload procedure and a single media retrieval procedure. To use a different schema, substitute a different schema name and password. Or, if you have changed the password for the SCOTT schema, use your new password.


See Also:

Oracle Database Security Guide for more information about creating secure passwords


This sample session assumes the Oracle Multimedia Code Wizard has been installed.

Perform these steps:

Step 1   Create a table to store audio for the application by starting SQL*Plus and connecting to the SCOTT (or other) schema in the database.

For example:

sqlplus SCOTT [@<connect_identifer>]

Enter password: password

SQL> CREATE TABLE cw_media_table( id NUMBER PRIMARY KEY,
                                 description VARCHAR2(30) NOT NULL,
                                 location VARCHAR2(30),
                                 image ORDSYS.ORDIMAGE,
                                 thumb ORDSYS.ORDIMAGE,
                                 audio ORDSYS.ORDAUDIO,
                                 video ORDSYS.ORDVIDEO,
                                 media ORDSYS.ORDDOC )
--
-- store media as SecureFile LOBs
--
LOB(image.source.localdata) STORE AS SECUREFILE
LOB(thumb.source.localdata) STORE AS SECUREFILE
LOB(audio.source.localdata) STORE AS SECUREFILE
LOB(video.source.localdata) STORE AS SECUREFILE
LOB(media.source.localdata) STORE AS SECUREFILE;
Step 2   Use the SCOTTCW DAD you created in Step 2. Then, authorize the use of it in Step 3.

If you have not created the SCOTTCW DAD and authorized the use of this DAD, perform Steps 2 and 3 in this section, then continue to next step that follows in this section.

Step 3   Change DADs to the SCOTTCW DAD.
  1. Enter the Code Wizard's administration URL into your browser's location bar, then enter the ORDSYS user name and password when prompted by the browser, for example:

    http://<hostname>:<port-number>/ordcwadmin
    
  2. Click Change DAD from the Code Wizard's Main menu.

  3. Click Change to SCOTTCW, if it is not already selected, then click Next.

  4. Enter the user name SCOTT and the password for the user SCOTT when prompted for the user name and password, then press OK.

    The Main menu now displays the current DAD as SCOTTCW and the current schema as SCOTT.

Step 4   Create and test the media upload procedure.

Click Create media upload procedure from the Main menu, then click Next.

  1. Select the database table and procedure Type.

    1. Click CW_MEDIA_TABLE.

    2. Click Standalone procedure.

    3. Click Next.

  2. Select the PL/SQL document upload table.

    If there are no document tables in the SCOTT schema, the Code Wizard displays a message indicating this situation. In this case, accept the default table name provided, CW_MEDIA_UPLOAD_TABLE, then click Next.

    If there are existing document tables, but the table CW_MEDIA_UPLOAD_TABLE is not among them, click Create new document table, accept the default table name provided, CW_MEDIA_UPLOAD_TABLE, then click Next.

    If the CW_MEDIA_UPLOAD_TABLE document table already exists, select Use existing document table and CW_MEDIA_UPLOAD_TABLE, then click Next.

  3. Select the data access and media columns.

    1. Ensure that IMAGE (ORDIMAGE), THUMB (ORDIMAGE), AUDIO (ORDAUDIO), VIDEO (ORDVIDEO), and MEDIA (ORDDOC) are all checkmarked.

    2. Click ID (Primary key).

    3. Click Conditional insert or update.

    4. Click Next.

  4. Select additional columns and procedure names.

    1. Ensure that DESCRIPTION is checkmarked because this column has a NOT NULL constraint. (The LOCATION column is not checkmarked by default as there are no constraints on this column.)

    2. Accept the procedure name provided, UPLOAD_CW_MEDIA_TABLE_IMAGE.

    3. Click Create procedure in the database.

    4. Click Next.

  5. Review the following selected procedure creation options that are displayed:

    Procedure type:        Standalone
    Table name:            CW_MEDIA_TABLE
    Media column(s):       IMAGE (ORDIMAGE)
                           THUMB (ORDIMAGE)
                           AUDIO (ORDAUDIO)
                           VIDEO (ORDVIDEO)
                           MEDIA (ORDDOC)
    Key column:            ID
    Additional column(s):  DESCRIPTION
    Table access mode:     Conditional update or insert
    Procedure name:        UPLOAD_CW_MEDIA_TABLE_IMAGE
    Function:              Create procedure in the database
    

    Click Finish.

  6. Compile the procedure and review the generated source information.

    The Code Wizard displays this message:

    Procedure created successfully: UPLOAD_CW_MEDIA_TABLE_IMAGE
    
    1. At the option Click to display generated source:, click View to view the generated source in another window. A copy of the generated source is shown at the end of Step 4, substep 6g.

    2. Close the window after looking at the generated source.

    3. Accept the DAD: name provided, SCOTTCW, then click Test to display in another window a template file upload form that you can use to test the generated procedure.

    4. To customize the template file upload form, select Save As... from your browser's File menu to save the HTML source for editing.

    5. To test the template upload form, enter the following information:

      • For the ID: column, enter the number 1 as the row's primary key.

      • For each Oracle Multimedia object column, click Browse... and choose the appropriate media to upload to each column of the table. You can choose one or more or all columns to test.

      • For the DESCRIPTION column, enter a brief description of the media.

      • Click Upload media.

      The Code Wizard displays a template completion window with the heading Oracle Multimedia Code Wizard: Template Upload Procedure, and, if the procedure is successful, the message: Media uploaded successfully.

    6. Close the window.

    7. Click Done on the Compile procedure and review generated source window to return to the Main menu of the Code Wizard.

    Example 4-3 shows a copy of the generated multiple media upload procedure:

    Example 4-3 Multiple Media Upload Procedure Generated in Sample Session 2

    CREATE OR REPLACE PROCEDURE UPLOAD_CW_MEDIA_TABLE_IMAGE
      ( in_ID IN VARCHAR2,
        in_IMAGE IN VARCHAR2 DEFAULT NULL,
        in_THUMB IN VARCHAR2 DEFAULT NULL,
        in_AUDIO IN VARCHAR2 DEFAULT NULL,
        in_VIDEO IN VARCHAR2 DEFAULT NULL,
        in_MEDIA IN VARCHAR2 DEFAULT NULL,
        in_DESCRIPTION IN VARCHAR2 DEFAULT NULL )
    AS
      local_IMAGE ORDSYS.ORDIMAGE := ORDSYS.ORDIMAGE.init();
      local_THUMB ORDSYS.ORDIMAGE := ORDSYS.ORDIMAGE.init();
      local_AUDIO ORDSYS.ORDAUDIO := ORDSYS.ORDAUDIO.init();
      local_AUDIO_ctx RAW( 64 );
      local_VIDEO ORDSYS.ORDVIDEO := ORDSYS.ORDVIDEO.init();
      local_VIDEO_ctx RAW( 64 );
      local_MEDIA ORDSYS.ORDDOC := ORDSYS.ORDDOC.init();
      local_MEDIA_ctx RAW( 64 );
      local_ID CW_MEDIA_TABLE.ID%TYPE := NULL;
      upload_size     INTEGER;
      upload_mimetype VARCHAR2( 128 );
      upload_blob     BLOB;
    BEGIN
      --
      -- Update the existing row.
      --
      UPDATE CW_MEDIA_TABLE mtbl
        SET mtbl.IMAGE = local_IMAGE,
            mtbl.THUMB = local_THUMB,
            mtbl.AUDIO = local_AUDIO,
            mtbl.VIDEO = local_VIDEO,
            mtbl.MEDIA = local_MEDIA,
            mtbl.DESCRIPTION = in_DESCRIPTION
        WHERE mtbl.ID = in_ID
        RETURN mtbl.ID INTO local_ID;
      --
      -- Conditionally insert a new row if no existing row is updated.
      --
      IF local_ID IS NULL
      THEN
        --
        -- Insert a new row into the table.
        --
        INSERT INTO CW_MEDIA_TABLE ( ID, IMAGE, THUMB, AUDIO, VIDEO, MEDIA,
     DESCRIPTION )
          VALUES ( in_ID, local_IMAGE, local_THUMB, local_AUDIO, 
                   local_VIDEO, local_MEDIA, in_DESCRIPTION );
      END IF;
      --
      -- Select Oracle Multimedia object(s) for update.
      --
      SELECT mtbl.IMAGE, mtbl.THUMB, mtbl.AUDIO, mtbl.VIDEO, mtbl.MEDIA INTO
     local_IMAGE, local_THUMB, local_AUDIO, local_VIDEO, local_MEDIA
        FROM CW_MEDIA_TABLE mtbl WHERE mtbl.ID = in_ID FOR UPDATE;
      --
      -- Store media data for the column in_IMAGE.
      --
      IF in_IMAGE IS NOT NULL
      THEN
        SELECT dtbl.doc_size, dtbl.mime_type, dtbl.blob_content INTO
               upload_size, upload_mimetype, upload_blob
          FROM MEDIA_UPLOAD_TABLE dtbl WHERE dtbl.name = in_IMAGE;
        IF upload_size &gt; 0
        THEN
          dbms_lob.copy( local_IMAGE.source.localData, 
                         upload_blob, 
                         upload_size );
          local_IMAGE.setLocal();
          BEGIN
            local_IMAGE.setProperties();
          EXCEPTION
            WHEN OTHERS THEN
              local_IMAGE.contentLength := upload_size;
              local_IMAGE.mimeType := upload_mimetype;
          END;
        END IF;
        DELETE FROM MEDIA_UPLOAD_TABLE dtbl WHERE dtbl.name = in_IMAGE;
      END IF;
      --
      -- Store media data for the column in_THUMB.
      --
      IF in_THUMB IS NOT NULL
      THEN
        SELECT dtbl.doc_size, dtbl.mime_type, dtbl.blob_content INTO
               upload_size, upload_mimetype, upload_blob
          FROM MEDIA_UPLOAD_TABLE dtbl WHERE dtbl.name = in_THUMB;
        IF upload_size &gt; 0
        THEN
          dbms_lob.copy( local_THUMB.source.localData, 
                         upload_blob, 
                         upload_size );
          local_THUMB.setLocal();
          BEGIN
            local_THUMB.setProperties();
          EXCEPTION
            WHEN OTHERS THEN
              local_THUMB.contentLength := upload_size;
              local_THUMB.mimeType := upload_mimetype;
          END;
        END IF;
        DELETE FROM MEDIA_UPLOAD_TABLE dtbl WHERE dtbl.name = in_THUMB;
      END IF;
      --
      -- Store media data for the column in_AUDIO.
      --
      IF in_AUDIO IS NOT NULL
      THEN
        SELECT dtbl.doc_size, dtbl.mime_type, dtbl.blob_content INTO
               upload_size, upload_mimetype, upload_blob
          FROM MEDIA_UPLOAD_TABLE dtbl WHERE dtbl.name = in_AUDIO;
        IF upload_size &gt; 0
        THEN
          dbms_lob.copy( local_AUDIO.source.localData, 
                         upload_blob, 
                         upload_size );
          local_AUDIO.setLocal();
          BEGIN
            local_AUDIO.setProperties(local_AUDIO_ctx);
          EXCEPTION
            WHEN OTHERS THEN
              local_AUDIO.mimeType := upload_mimetype;
          END;
        END IF;
        DELETE FROM MEDIA_UPLOAD_TABLE dtbl WHERE dtbl.name = in_AUDIO;
      END IF;
      --
      -- Store media data for the column in_VIDEO.
      --
      IF in_VIDEO IS NOT NULL
      THEN
        SELECT dtbl.doc_size, dtbl.mime_type, dtbl.blob_content INTO
               upload_size, upload_mimetype, upload_blob
          FROM MEDIA_UPLOAD_TABLE dtbl WHERE dtbl.name = in_VIDEO;
        IF upload_size &gt; 0
        THEN
          dbms_lob.copy( local_VIDEO.source.localData, 
                         upload_blob, 
                         upload_size );
          local_VIDEO.setLocal();
          BEGIN
            local_VIDEO.setProperties(local_VIDEO_ctx);
          EXCEPTION
            WHEN OTHERS THEN
              local_VIDEO.mimeType := upload_mimetype;
          END;
        END IF;
        DELETE FROM MEDIA_UPLOAD_TABLE dtbl WHERE dtbl.name = in_VIDEO;
      END IF;
      --
      -- Store media data for the column in_MEDIA.
      --
      IF in_MEDIA IS NOT NULL
      THEN
        SELECT dtbl.doc_size, dtbl.mime_type, dtbl.blob_content INTO
               upload_size, upload_mimetype, upload_blob
          FROM MEDIA_UPLOAD_TABLE dtbl WHERE dtbl.name = in_MEDIA;
        IF upload_size &gt; 0
        THEN
          dbms_lob.copy( local_MEDIA.source.localData, 
                         upload_blob, 
                         upload_size );
          local_MEDIA.setLocal();
          BEGIN
            local_MEDIA.setProperties(local_MEDIA_ctx, FALSE);
          EXCEPTION
            WHEN OTHERS THEN
              local_MEDIA.contentLength := upload_size;
              local_MEDIA.mimeType := upload_mimetype;
          END;
        END IF;
        DELETE FROM MEDIA_UPLOAD_TABLE dtbl WHERE dtbl.name = in_MEDIA;
      END IF;
      --
      -- Update Oracle Multimedia objects in the table.
      --
      UPDATE CW_MEDIA_TABLE mtbl
        SET mtbl.IMAGE = local_IMAGE,
            mtbl.THUMB = local_THUMB,
            mtbl.AUDIO = local_AUDIO,
            mtbl.VIDEO = local_VIDEO,
            mtbl.MEDIA = local_MEDIA
        WHERE mtbl.ID = in_ID;
      --
      -- Display the template completion message.
      --
      htp.print( '&lt;html&gt;' );
      htp.print( '&lt;title&gt;Oracle Multimedia Code Wizard: Template Upload
     Procedure&lt;/title&gt;' );
      htp.print( '&lt;body&gt;' );
      htp.print( '&lt;h2&gt; Oracle Multimedia Code Wizard:
     Template Upload Procedure&lt;/h2&gt;' );
      htp.print( 'Media uploaded successfully.' );
      htp.print( '&lt;/body&gt;' );
      htp.print( '&lt;/html&gt;' );
    
    END UPLOAD_CW_MEDIA_TABLE_IMAGE;
    

    The multiple media upload procedure shown in Example 4-3 declares these input parameters and variables:

    1. In the declaration section, the procedure declares seven input parameters: in_ID, in_IMAGE, in_THUMB, in_AUDIO, in_VIDEO, in_MEDIA, and in_DESCRIPTION, then initializes the last six to NULL.

    2. In the subprogram section, the following variables are declared:

      • The variables local_IMAGE and local_THUMB are assigned the data type ORDSYS.ORDIMAGE and initialized with an empty BLOB using the ORDIMAGE.init( ) method.

      • The variable local_AUDIO is assigned the data type ORDSYS.ORDAUDIO and initialized with an empty BLOB using the ORDAUDIO.init( ) method. Also a context variable local_AUDIO_ctx is assigned the data type RAW(64).

      • The variable local_VIDEO is assigned the data type ORDSYS.ORDVIDEO and initialized with an empty BLOB using the ORDVIDEO.init( ) method. Also, a context variable local_VIDEO_ctx is assigned the data type RAW(64).

      • The variable local_MEDIA is assigned the data type ORDSYS.ORDDOC and initialized with an empty BLOB using the ORDDOC.init( ) method. Also, a context variable local_MEDIA_ctx is assigned the data type RAW(64).

      • The variable local_ID takes the same data type as the ID column in the table CW_MEDIA_TABLE and is initialized to NULL.

      • Three additional variables are declared upload_size, upload_mimetype, and upload_blob, which are later given values from comparable column names doc_size, mime_type, and blob_content from the document table MEDIA_UPLOAD_TABLE using a SELECT statement. This is all in preparation for copying the content of the image, thumb, audio, video, and media BLOB data to the respective ORDSYS.ORDIMAGE.source.localData, ORDSYS.ORDIMAGE.source.localData, ORDSYS.ORDAUDIO.source.localData, ORDSYS.ORDVIDEO.source.localData, and ORDSYS.ORDDOC.source.localData attributes.

    Within the outer BEGIN...END executable statement section, the following operations are executed:

    1. Update the existing row in the table CW_MEDIA_TABLE for the IMAGE, THUMB, AUDIO, VIDEO, MEDIA, and DESCRIPTION columns and return the value of local_ID where the value of the ID column is the value of the in_ID input parameter.

    2. If the value returned of local_ID is NULL, conditionally insert a new row into the table CW_MEDIA_TABLE and initialize the instance of the ORDImage object type in the IMAGE column with an empty BLOB, the instance of the ORDImage object type in the THUMB column with an empty BLOB, the instance of the ORDAudio object type in the AUDIO column with an empty BLOB, the instance of the ORDVideo object type in the VIDEO column with an empty BLOB, and the instance of the ORDDoc object type in the MEDIA column with an empty BLOB.

    3. Select the ORDImage object column IMAGE, ORDImage object column THUMB, ORDAudio object column AUDIO, ORDVideo object column VIDEO, and ORDDoc object column MEDIA in the table CW_MEDIA_TABLE for update where the value of the ID column is the value of the in_ID input parameter.

    4. Select a row for the doc_size, mime_type, and blob_content columns from the document table and pass the values to the upload_size, upload_mimetype, and upload_blob variables where the value of the Name column is the value of one of these input parameters: in_IMAGE; in_THUMB; in_AUDIO; in_VIDEO; or in_MEDIA.

    5. Perform a DBMS LOB copy of the BLOB data from the table MEDIA_UPLOAD_TABLE into the ORDSYS.ORDIMAGE.source.localData, ORDSYS.ORDIMAGE.source.localData, ORDSYS.ORDAUDIO.source.localData, ORDSYS.ORDVIDEO.source.localData, and ORDSYS.ORDDoc.source.localData attribute, then call the setLocal( ) method to indicate that the image, audio, and video data are stored locally in the BLOB, and ORDImage, ORDAudio, ORDVideo, and ORDDoc methods are to look for corresponding data in the source.localData attribute.

    6. In the inner executable block, call the respective ORDImage, ORDAudio, ORDVideo, and ORDDoc setProperties( ) method to read the image, audio, and video data to get the values of the object attributes and store them in the image, audio, video, and media object attributes for the ORDImage, ORDAudio, ORDVideo, and ORDDoc objects.

    7. If the setProperties( ) call fails, catch the exception and call the contentLength( ) method to get the size of the media data and call the mimeType( ) method to get the MIME type of the media data.

    8. Delete the row of data from the document table MEDIA_UPLOAD_TABLE hat was copied to the row in the table CW_MEDIA_TABLE where the value of the Name column is the value of the respective in_IMAGE, in_THUMB, in_AUDIO, in_VIDEO, and in_MEDIA input parameter.

    9. Update the ORDImage object IMAGE column, the ORDImage object THUMB column, the ORDAudio object AUDIO column, the ORDVideo object VIDEO column, and the ORDDoc object MEDIA column in the table CW_MEDIA_TABLE with the content of the variables local_IMAGE, local_THUMB, local_AUDIO, local_VIDEO, and local_MEDIA respectively, where the value of the ID column is the value of the in_ID input parameter.

    10. Display a completion message on the HTML page to indicate that the media uploaded successfully using the htp.print function from the PL/SQL Web Toolkit.

Step 5   Create and test a media retrieval.

Select Create media retrieval procedure from the Main menu, then click Next.

  1. Select the database table and procedure type.

    1. Click CW_MEDIA_TABLE.

    2. Click Standalone procedure.

    3. Click Next.

  2. Select the media column and key column.

    1. Ensure that one the following object columns is checkmarked. For example, if you loaded media data into the media column in Step 4, substep 6e, then select the MEDIA (ORDDOC) column.

    2. Click ID (Primary key).

    3. Click Next.

  3. Select the procedure name and parameter name.

    1. Accept the procedure name provided, GET_CW_MEDIA_TABLE_IMAGE.

    2. Accept the parameter name provided, MEDIA_ID.

    3. Click Create procedure in the database.

    4. Click Next.

  4. Review the following selected procedure creation options:

  5. Procedure type:        Standalone
    Table name:            CW_MEDIA_TABLE
    Key column:            ID
    Media column:          IMAGE (ORDDOC)
    Procedure name:        GET_CW_MEDIA_TABLE_IMAGE
    Parameter name:        MEDIA_ID
    Function:              Create procedure in the database
    

    Click Finish.

  6. Compile the procedure and review the generated source.

    The Code Wizard displays this message:

    Procedure created successfully: GET_CW_MEDIA_TABLE_IMAGE
    
    1. Click View to view the generated source in another window. Close the window after looking at the generated source. A copy of the generated source is shown at the end of this step.

    2. Review the URL format used to retrieve images using the GET_CW_MEDIA_TABLE_IMAGE procedure.

    3. Enter the number 1 as the Key parameter, then click Test to test the procedure by retrieving the image uploaded previously.

    4. The retrieved image is displayed in another window.

    5. Close the window.

    6. Click Done to return to the Main menu.


    Note:

    A generated media retrieval script, unlike the multiple media upload script shown at the end of Step 4, handles only the type of media data designed for that Oracle Multimedia object type. To retrieve media data stored in other Oracle Multimedia object types, generate a retrieval script for each desired media data type and add it to your PL/SQL package.

    Example 4-4 shows a copy of the generated media retrieval procedure:

    Example 4-4 Media Retrieval Procedure Generated in Sample Session 2

    CREATE OR REPLACE PROCEDURE GET_CW_MEDIA_TABLE_MEDIA ( MEDIA_ID
     IN VARCHAR2 )
    AS
      localObject ORDSYS.ORDDOC;
      localBlob  BLOB;
      localBfile BFILE;
      httpStatus NUMBER;
      lastModDate VARCHAR2(256);
    
    BEGIN
      --
      -- Retrieve the object from the database into a local object.
      --
      BEGIN
        SELECT mtbl.MEDIA INTO localObject FROM CW_MEDIA_TABLE mtbl 
          WHERE mtbl.ID = MEDIA_ID;
      EXCEPTION
        WHEN NO_DATA_FOUND THEN
          ordplsgwyutil.resource_not_found( 'MEDIA_ID', MEDIA_ID );
          RETURN;
      END;
      --  -- Check the update time if the browser sent an If-Modified-Since header.
      --
      IF ordplsgwyutil.cache_is_valid( localObject.getUpdateTime() )
      THEN
        owa_util.status_line( ordplsgwyutil.http_status_not_modified );
        RETURN;
      END IF;
      --
      -- Figure out where the image is.
      --
      IF localObject.isLocal() THEN
        --
        -- Data is stored locally in the localData BLOB attribute.
        --
        localBlob := localObject.getContent();
        owa_util.mime_header( localObject.getMimeType(), FALSE );
        ordplsgwyutil.set_last_modified( localObject.getUpdateTime() );
        owa_util.http_header_close();
        IF owa_util.get_cgi_env( 'REQUEST_METHOD' ) &lt;&gt; 'HEAD' THEN
          wpg_docload.download_file( localBlob );
        END IF;
    
      ELSIF UPPER( localObject.getSourceType() ) = 'FILE' THEN
        --
        -- Data is stored as a file from which ORDSource creates 
        -- a BFILE.
        --
        localBfile  := localObject.getBFILE();
        owa_util.mime_header( localObject.getMimeType(), FALSE );
        ordplsgwyutil.set_last_modified( localObject.getUpdateTime() );
        owa_util.http_header_close();
        IF owa_util.get_cgi_env( 'REQUEST_METHOD' ) &lt;&gt; 'HEAD' THEN
          wpg_docload.download_file( localBfile );
        END IF;
    
      ELSIF UPPER( localObject.getSourceType() ) = 'HTTP' THEN
        --
        -- The image is referenced as an HTTP entity, so we have to 
        -- redirect the client to the URL that ORDSource provides.
        --
        owa_util.redirect_url( localObject.getSource() );
      ELSE
        --
        -- The image is stored in an application-specific data
        -- source type for which no default action is available.
        --
        NULL;
      END IF;
    END GET_CW_MEDIA_TABLE_MEDIA;
    

    For a description of the media retrieval procedure shown in Example 4-4, see the description that follows Example 4-2 (in Section 4.3). The only difference between these two retrieval procedures is the type of object that is retrieved. Example 4-2 uses an ORDImage object type; Example 4-4 uses an ORDDoc object type.

4.5 Known Restrictions of the Oracle Multimedia Code Wizard

The following restrictions are known for the Oracle Multimedia Code Wizard:

  • Tables with composite primary keys are not supported.

    To use a table with a composite primary key, create an upload or download procedure, then edit the generated source to support all the primary key columns. For example, for a media retrieval procedure, this might involve adding an additional parameter, then specifying that parameter in the where clause of the SELECT statement.

  • User object types containing embedded Oracle Multimedia object types are not recognized by the Oracle Multimedia Code Wizard.

PKQrrPK"+A OEBPS/lot.htm List of Tables PKŬP  PK"+AOEBPS/ch_intr.htm Introduction to Oracle Multimedia

1 Introduction to Oracle Multimedia

Oracle Multimedia (formerly Oracle interMedia) enables Oracle Database to store, manage, and retrieve images, DICOM format medical images and other objects, audio, video, or other heterogeneous media data in an integrated fashion with other enterprise information.

Oracle Multimedia extends Oracle Database reliability, availability, and data management to multimedia content in traditional, medical, Internet, electronic commerce, and media-rich applications. Oracle Multimedia does not control media capture or output devices; this function is left to application software.

Oracle Multimedia provides these services and support:

  • Image services for the storage, retrieval, metadata extraction, and processing of two-dimensional, static, bit-mapped images. Images are stored efficiently using popular compression schemes in industry-standard image formats for desktop publishing.

  • Digital Imaging and Communications in Medicine (DICOM) support for the storage, retrieval, metadata extraction, processing, writing, conformance validation, and making anonymous of medical images and other DICOM content.

  • Audio and video services for the storage, retrieval, and metadata extraction of popular audio and video file formats.

  • Media content services to Oracle JDeveloper, Oracle Portal, and Oracle partners.

This chapter includes these sections:


See Also:


1.1 Oracle Multimedia Architecture

Oracle Multimedia is a single, integrated feature that extends the database by storing, managing, and retrieving image, audio, and video data, and by supporting Web technologies for multimedia data.

The Oracle Multimedia architecture defines the framework (see Figure 1-1) through which media-rich content is supported in the database, along with traditional data. This content can then be securely shared across multiple applications written with popular languages and tools, easily managed and administered by relational database management and administration technologies, and offered on a scalable database that supports thousands of users.

Figure 1-1 illustrates the Oracle Multimedia architecture from a three-tier perspective:

  1. Database tier (Oracle Database)

  2. Middle tier (Oracle Fusion Middleware)

  3. Client tier (Thin Client and Thick Clients)

In the database tier, using Oracle Multimedia, Oracle Database holds rich content in tables along with traditional data. Through a database-embedded JVM, a server-side media parser and an image processor are supported. The media parser has object-oriented and relational interfaces, supports format and application metadata parsing, and can be extended to support additional formats. The image processor includes JAI. It also provides image processing for operations such as producing thumbnail-size images, converting image formats, and image watermarking.

Using Oracle Multimedia methods, import and export operations between the database and operating system files (external file storage) are possible. Oracle Multimedia also supports special delivery types of servers, such as streaming content from a database. Using the Oracle Multimedia Plug-ins for RealNetworks or Windows Media Services, the Helix Universal Server or Windows Media Streaming Server can stream multimedia data to a client directly out of the database using Real-Time Streaming Protocol (RTSP). In addition, third-party media processors such as speech recognition engines can run external to the database to process media stored in the database and return results to the database.

In the middle tier, Oracle Fusion Middleware provides access to Oracle Multimedia through Oracle Multimedia Java classes, which enable Java applications on any tier (client, application server, or database) to access, manipulate, and modify audio, image, and video data stored in a database. In addition, Oracle Multimedia Java classes facilitate the upload and retrieval of multimedia data stored in a database using the Oracle Multimedia OrdAudio, OrdDoc, OrdImage, and OrdVideo object types. And, Oracle Multimedia Java classes can access data stored in the Oracle Multimedia objects or BLOBs or BFILEs directly.

Developers can also use Oracle JDeveloper and Oracle Multimedia to build media-rich Java applications quickly and easily using the Oracle Multimedia/ADF Business Components integration package. Oracle Multimedia rich content can also be easily and transparently incorporated into Oracle Portal forms and reports, which can then be published as portlets.

SQL developers familiar with the database can develop Web applications that use Oracle Fusion Middleware exclusively, and Oracle Database using the PL/SQL development environment. The steps include using the PL/SQL Gateway (mod_plsql) feature of the Oracle HTTP Server and the PL/SQL Web Toolkit. Web application developers can write PL/SQL servlets and PL/SQL server pages (PSP) that invoke PL/SQL procedures stored in the database through an Oracle Net connection and OCI.

In the client tier, the ability to perform local processing is supported through Oracle Multimedia Java classes and Java Advanced Imaging (JAI). Oracle Multimedia Java classes supply direct access to all media types from the client. JAI provides a set of APIs for media processing on the client.

Figure 1-1 Oracle Multimedia Architecture

Description of Figure 1-1 follows
Description of "Figure 1-1 Oracle Multimedia Architecture"

Oracle Multimedia features available only on Oracle Technology Network (OTN) include the following:

  • Oracle Multimedia Plug-in for RealNetworks Streaming Servers (see Section 1.10.2)

  • Oracle Multimedia Plug-in for Microsoft Windows Media Services (see Section 1.10.2)

1.2 Object Relational Technology

Oracle Database is an object relational database management system. Thus, in addition to its traditional role in the safe and efficient management of relational data, Oracle Database provides support for the definition of object types, including the data associated with objects and the operations (methods) that can be performed on them.

Object relational technology includes integral support for BLOBs to provide the basis for adding complex objects to databases. Complex objects include: digitized audio, image, video, and Digital Imaging and Communications in Medicine (DICOM) format medical images and other data.

Oracle Multimedia provides four object relational types, which store data source information in an object relational type known as ORDSource:

  • ORDAudio for audio data characteristics

  • ORDDoc for heterogeneous data characteristics

  • ORDImage for image data characteristics

  • ORDVideo for video data characteristics

In addition, Oracle Multimedia provides the ORDDicom object relational type for characteristics of DICOM content produced by medical devices.


See Also:


1.3 Oracle Multimedia Capabilities

The capabilities of Oracle Multimedia include the storage, retrieval, management, and manipulation of multimedia data managed by Oracle Database.

Multimedia applications have common and unique requirements. Oracle Multimedia object types support common application requirements and can be extended to address application-specific requirements. With Oracle Multimedia, multimedia data can be managed as easily as standard attribute data.

Oracle Multimedia is accessible to applications through both relational and object interfaces. Database applications written in Java, C++, or traditional third-generation languages (3GLs) can interact with Oracle Multimedia through modern class library interfaces, or PL/SQL and Oracle Call Interface (OCI).

Oracle Multimedia supports storage of the popular file formats, including desktop publishing images, and streaming audio and video formats in databases. Oracle Multimedia provides the means to add audio, image, and video, or other heterogeneous media columns or objects to existing tables, and insert and retrieve multimedia data. This support enables database designers to extend existing databases with multimedia data, or to build new end-user multimedia database applications. Oracle Multimedia developers can use the basic functions provided here to build specialized multimedia applications.

Oracle Multimedia uses object types, similar to Java or C++ classes, to describe multimedia data. These object types are called ORDAudio, ORDDoc, ORDImage, and ORDVideo. An instance of these object types consists of attributes, including metadata and the media data, and methods. Media data is the actual audio, image, or video, or other heterogeneous media data. Metadata is information about the data, such as object length, compression type, or format. Methods are procedures that can be performed on objects, such as getContent( ) and setProperties( ).

The Oracle Multimedia objects have a common media data storage model. The media data component of these objects can be stored in the database, in a BLOB under transaction control. The media data can also be stored outside the database, without transaction control. In this case, a pointer is stored in the database under transaction control, and the media data is stored in:

  • File-based large object (BFILE)

  • An HTTP server-based URL

  • A user-defined source on a specialized media data server, or other server

Media data stored outside the database can provide a convenient mechanism for managing large, existing or new, media repositories that reside as flat files on erasable or read-only media. This data can be imported into BLOBs at any time for transaction control. Section 1.8 describes several ways of loading multimedia data into a database.

Media metadata is stored in the database under Oracle Multimedia control. Whether media data is stored within or outside the database, Oracle Multimedia manages metadata for all the media types and might automatically extract it for audio, image, and video. This metadata includes these attributes:

  • Storage information about audio, image, and video, or other heterogeneous media data, including the source type, location, and source name, and whether the data is stored locally (in the database) or externally

  • Update time stamp information for audio, image, and video, or other heterogeneous media data

  • Audio and video data description

  • Audio, image, and video, or other heterogeneous media data format

  • MIME type of the audio, image, and video, or other heterogeneous media data

  • Audio characteristics: encoding type, number of channels, sampling rate, sample size, compression type, and play time (duration)

  • Image characteristics: height and width, image content length, image content format, and image compression format

  • Video characteristics: frame width and height, frame resolution, frame rate, play time (duration), number of frames, compression type, number of colors, and bit rate

  • Extracted metadata in XML, such as the director or producer of a movie

In addition to metadata extraction methods, a minimal set of image manipulation methods is provided. For images, this includes format conversion, page selection, quantize operations, compression, scaling, cropping, copying, flipping, mirroring, rotating, sharpening, adjusting the gamma (brightness), adding watermarks to images, removing metadata from images, and embedding metadata into images.


See Also:

Oracle Multimedia Reference for more information about image processing operations


Oracle Multimedia is extensible. It supports a base set of popular audio, image, and video data formats for multimedia processing that also can be extended, for example, to support additional formats, new digital compression and decompression schemes (codecs), data sources, and even specialized data processing algorithms for audio and video data. See Chapter 7 for more information about extending Oracle Multimedia.

Oracle Multimedia is a building block for various multimedia applications, rather than an end-user application. It consists of object types and their respective methods for managing and processing multimedia data. Some example applications for Oracle Multimedia are:

  • Repositories for digital check images

  • Electronic health records, including DICOM medical images

  • Call centers (for example, 911 and product call centers)

  • Physical asset inventories

  • Distance learning and online learning

  • Real estate marketing

  • Stock photography archives (for example, digital art galleries and professional photographers)

  • Document imaging archives

  • Financial news service customer information

  • Web publishing

  • Audio and video Web stores

1.4 Audio Concepts

This section contains information about digitized audio concepts, and information about using the ORDAudio object type to build audio applications or specialized ORDAudio objects, in these subsections:

1.4.1 Digitized Audio

ORDAudio integrates the storage, retrieval, and management of digitized audio data in a database.

Audio may be produced by an audio recorder, an audio source such as a microphone, digitized audio, other specialized audio recording devices, or even by program algorithms. Audio recording devices take an analog or continuous signal, such as the sound picked up by a microphone or sound recorded on magnetic media, and convert it into digital values with specific audio characteristics such as format, encoding type, number of channels, sampling rate, sample size, compression type, and audio duration.

1.4.2 Audio Components

Digitized audio consists of the audio data (digitized bits) and attributes that describe and characterize the audio data. Audio applications sometimes associate application-specific information, such as the description of the audio clip, date recorded, author or artist, and so on, with audio data by storing descriptive text in an attribute or column in the database table.

The audio data can have different formats, encoding types, compression types, numbers of channels, sampling rates, sample sizes, and playing times (duration) depending upon how the audio data was digitally recorded. ORDAudio can store and retrieve audio data of any supported data format. ORDAudio can automatically extract metadata from audio data of a variety of popular audio formats. ORDAudio can also extract application attributes and store them in the comments field of the object in XML form. ORDAudio is extensible and can be made to recognize and support additional audio formats.

The size of digitized audio (number of bytes) tends to be large compared to traditional computer objects, such as numbers and text. Therefore, several encoding schemes are used that squeeze audio data into fewer bytes, thus putting a smaller load on storage devices and networks.


See Also:

Oracle Multimedia Reference for a list of supported data formats from which ORDAudio can extract and store attributes and other audio features


1.5 ORDDoc or Heterogeneous Media Data Concepts

This section contains information about heterogeneous media data concepts, and information about using the ORDDoc object type to build applications or specialized ORDDoc objects, in these subsections:

1.5.1 Digitized Heterogeneous Media Data

ORDDoc integrates the storage, retrieval, and management of heterogeneous media data in a database.

The ORDDoc type can store any heterogeneous media data including audio, image, and video data in a database column. Instead of having separate columns for audio, image, text, and video objects, you can use one column of ORDDoc objects to represent all types of multimedia.

1.5.2 Heterogeneous Media Data Components

Heterogeneous media data components consist of the data (digitized bits) and attributes that describe and characterize the heterogeneous media data.

Heterogeneous media data can have different formats, depending upon the application generating the media data. Oracle Multimedia can store and retrieve media data of any supported data format. The ORDDoc type can be used in applications that require you to store different types of heterogeneous media data (such as audio, image, video, and any other type of media data) in the same column so you can build a common metadata index on all the different types of media data. Using this index, you can search across all the different types of heterogeneous media data. You cannot use this same search technique if the different types of heterogeneous media data are stored in different types of objects, in different columns of relational tables.

ORDDoc can automatically extract metadata from data of a variety of popular audio, image, and video data formats. ORDDoc can also extract application attributes and store them in the comments attribute of the object in XML form. ORDDoc is extensible and can be made to recognize and support other heterogeneous media data formats.


See Also:

Oracle Multimedia Reference for a list of supported data formats from which ORDDoc can extract and store attributes


1.6 Image Concepts

This section contains information about digitized image concepts, and information about using the ORDImage object type to build image applications or specialized ORDImage objects, in these subsections:

1.6.1 Digitized Images

ORDImage integrates the storage, retrieval, and management of digitized images in a database.

ORDImage supports two-dimensional, static, digitized raster images stored as binary representations of real-world objects or scenes. Images may be produced by a document or photograph scanner, a video source such as a digital camera or VCR connected to a video digitizer or frame grabber, other specialized image capture devices, or even by program algorithms. Capture devices take an analog or continuous signal such as the light that falls onto the film in a camera, and convert it into digital values on a two-dimensional grid of data points known as pixels. Devices involved in the capture and display of images are under application control.

1.6.2 Image Components

Digitized images consist of the image data (digitized bits) and attributes that describe and characterize the image data. Image applications sometimes associate application-specific information, such as the name of the person pictured in a photograph, description of the image, date photographed, photographer, and so on, with image data by storing this descriptive text in an attribute or column in the database table.

The image data (pixels) can have varying depths (bits per pixel) depending on how the image was captured, and can be organized in various ways. The organization of the image data is known as the data format. ORDImage can store and retrieve image data of any data format. ORDImage can process and automatically extract properties of images of a variety of popular data formats. In addition, certain foreign images (formats not natively supported by ORDImage) have limited support for image processing.

The storage space required for digitized images can be large compared to traditional attribute data such as numbers and text. Many compression schemes are available to squeeze an image into fewer bytes, thus reducing storage device and network load. Lossless compression schemes squeeze an image so that when it is decompressed, the resulting image is bit-for-bit identical with the original. Lossy compression schemes do not result in an identical image when decompressed, but rather, one in which the changes may be imperceptible to the human eye. As compared with lossless compression schemes, lossy compression schemes generally provide higher compression.

The image interchange format describes a well-defined organization and use of image attributes, data, and often compression schemes, enabling different applications to create, exchange, and use images. Interchange formats are often stored as disk files. They can also be exchanged in a sequential fashion over a network and be referred to as protocols. There are many application subdomains within the digitized imaging world and many applications that create or use digitized images within these. ORDImage supports storage and retrieval of all image data formats, and processing and attribute extraction of many image data formats.


See Also:

Oracle Multimedia Reference for a list of supported data formats from which ORDImage can process, extract, and store attributes and other image features


1.6.3 Metadata in Images

Oracle Database 10g, Release 2 added an image metadata feature to Oracle Multimedia. The metadata feature enhanced the behavior of the Oracle Multimedia ORDImage object type by adding the ability to read (or extract) and write (or embed) application metadata in images. In addition, this feature adopted a standard way to represent metadata when it is separate from an image file. Metadata can be stored in a database, indexed, searched, and made available to applications using the standard mechanisms of Oracle Database. See Chapter 6 for more information about the image metadata feature.

1.6.4 Medical Imaging

Oracle Database 10g, Release 2 (10.2) added the Digital Imaging and Communications in Medicine (DICOM) feature to Oracle Multimedia. The Oracle Multimedia feature enhanced the behavior of the Oracle Multimedia ORDImage object type by enabling Oracle Multimedia to recognize standalone DICOM objects and extract a subset of embedded DICOM attributes relating to patient, study, and series.


Note:

In Oracle Database 11g, Release 1 (11.1), Oracle introduced new and substantially enhanced features to support DICOM content. As a result, beginning with Oracle Database 11g, Release 2 (11.2), the DICOM support in ORDImage objects that was introduced in Oracle Database 10g, Release 2 (10.2) is not being enhanced, and may be deprecated in a future release.

The Oracle Database 10g, Release 2 DICOM support is still available in Oracle Database 11g, Release 2. However, Oracle recommends writing new medical imaging applications to use the DICOM support that was introduced in Oracle Database 11g, Release 1. Oracle also recommends migrating existing applications from the DICOM support in Oracle Database 10g, Release 2 (ORDImage objects) to the DICOM support in Oracle Database 11g, Release 1 at your convenience. See "Migrating from Release 10.2 DICOM Support" in Oracle Multimedia DICOM Developer's Guide for instructions.


Oracle Database 11g, Release 1 (11.1) substantially enhanced the medical imaging format support for Oracle Multimedia DICOM by providing the following:

  • Storage and retrieval of medical imaging data in the database to synchronize the DICOM data with the associated business data

  • Full object and relational interfaces to Oracle Multimedia DICOM services

  • Extraction of DICOM metadata according to user-specifiable XML documents

  • Querying using associated relational data and extracted metadata

  • Image processing, such as thumbnail generation

  • Creation of new DICOM objects

  • Conformance validation based on a set of user-specified conformance rules

  • Making DICOM objects anonymous based on user-defined rules that specify the set of attributes to be made anonymous and how to make those attributes anonymous

  • The ability to update run-time behaviors, such as the version of the DICOM standard supported, without installing a new release of Oracle Database


See Also:

Oracle Multimedia DICOM Developer's Guide for more information about Oracle Multimedia DICOM features and enhancements


1.6.5 Metadata Extraction

Oracle Multimedia provides the ability to extract content and format metadata from media sources (audio and video files), and collects and organizes this metadata as an XML formatted CLOB. Once metadata has been extracted and stored, you can index the metadata for powerful full text and thematic media searches using Oracle Text. Thus, the database can be queried to locate the media data based on the metadata extracted from the media.


See Also:

The setProperties( ) method inOracle Multimedia Reference for more information about metadata extraction


1.6.6 Image Processing

Oracle Multimedia supports image processing, such as format transcoding, cutting, scaling, generating thumbnail images, and applying watermarks. In addition, when the destination image file format is RAW Pixel (RPIX) or Microsoft Windows Bitmap (BMPF), Oracle Multimedia supports several operators for changing the format characteristics.


See Also:

Oracle Multimedia Reference for more information about image processing


1.6.7 SQL/MM Still Image Standard Support

Oracle Multimedia also provides support for the first edition of the ISO/IEC 13249-5:2001 SQL MM Part5:StillImage standard (commonly referred to as the SQL/MM Still Image standard), which includes these object relational types for image characteristics: SI_StillImage, SI_AverageColor, SI_Color, SI_ColorHistogram, SI_FeatureList, SI_PositionalColor, and SI_Texture.

The following ORDImage features are not specified by the SQL/MM Still Image Standard, and therefore are not available for StillImage objects:

  • Storing image data outside the database

  • Image processing operations (such as scaling up, compressing, and so on) that are specific to ORDImage

  • Java client API


See Also:

Oracle Multimedia Reference for more information about the SQL/MM Still Image Standard object types


1.7 Video Concepts

This section contains information about digitized video concepts, and information about using ORDVideo to build video applications or specialized ORDVideo objects, in these subsections:

1.7.1 Digitized Video

ORDVideo integrates the storage, retrieval, and management of digitized video data in a database.

Video may be produced by a video recorder, a video camera, digitized animation video, other specialized video recording devices, or even by program algorithms. Some video recording devices take an analog or continuous signal, such as the video picked up by a video camera or video recorded on magnetic media, and convert it into digital values with specific video characteristics such as format, encoding type, frame rate, frame size (width and height), frame resolution, video length, compression type, number of colors, and bit rate.

1.7.2 Video Components

Digitized video consists of the video data (digitized bits) and the attributes that describe and characterize the video data. Video applications sometimes associate application-specific information, such as the description of the video training tape, date recorded, instructor's name, producer's name, and so on, within the video data.

The video data can have different formats, compression types, frame rates, frame sizes, frame resolutions, playing times, compression types, number of colors, and bit rates depending upon how the video data was digitally recorded. ORDVideo can store and retrieve video data of any supported data format. ORDVideo can:

  • Automatically extract metadata from video data of a variety of popular video formats

  • Extract application attributes and store them in the comments attribute of the object in XML form

  • Be made to recognize and support additional video formats (because it is extensible)

The size of digitized video (number of bytes) tends to be large compared to traditional computer objects, such as numbers and text. Therefore, several encoding schemes are used that squeeze video data into fewer bytes, thus putting a smaller load on storage devices and networks.


See Also:

Oracle Multimedia Reference for a list of supported data formats from which ORDVideo can extract and store attributes and other video features


1.8 Loading Multimedia Data

Multimedia data can be managed best by Oracle Database. Load your multimedia data into the database to take advantage of its reliability, scalability, availability, and data management capabilities. To bulk load multimedia data into the database, you can use:

  • SQL*Loader

    SQL*Loader is an Oracle utility that lets you load data, and in this case, multimedia data (LOB data), from external multimedia files into a table of a database containing Oracle Multimedia object type columns.

  • PL/SQL

    A procedural extension to SQL, PL/SQL is an advanced fourth-generation programming language (4GL) of Oracle. You can write PL/SQL procedures to load multimedia data from BLOB, file system, and URL media data sources into Oracle Multimedia object type columns.

An advantage of using SQL*Loader is that it is easy to create and test the control file that controls your data loading operation.

An advantage of using PL/SQL scripts to load your data is that you can call methods as you load data to generate thumbnail images, or extract properties.


See Also:


1.9 Multimedia Storage and Querying

Media can be stored in Oracle Multimedia object types, or directly in BLOBs or BFILEs. You can realize the most benefit by storing media in Oracle Multimedia object types. However, many of the features of Oracle Multimedia are available to media stored in BLOBs and BFILEs using the relational interface.

The Oracle Multimedia relational interface lets developers use static methods of Oracle Multimedia object types with existing and new media stored in BLOBs and BFILEs. Specifically, developers can move media data between the local file system and the database; parse and extract the properties of the media data; and store these properties in an XMLType or an XML formatted CLOB, and optionally, in individual relational columns. Developers are not required to make changes to their existing application schema or to instantiate Oracle Multimedia object types to take advantage of this relational interface. Oracle Multimedia static methods can also be used to perform image processing operations such as cut, scale, compress, and convert format.

The ORDAudio, ORDDoc, ORDImage, and ORDVideo object types all contain an attribute of type ORDSource and methods for multimedia data source manipulation.


Note:

Do not call ORDSource methods directly. Instead, invoke the wrapper method of the media object corresponding to the ORDSource method. This information is presented for users who want to write their own user-defined sources.

The following subsections briefly describe storage and querying:


See Also:


1.9.1 Storing Multimedia Data

Oracle Multimedia can store multimedia data as an internal source within the database, under transactional control as a BLOB. It can also externally reference digitized multimedia data stored as an external source in an operating system-specific file in a local file system, as a URL on an HTTP server, or as a user-defined source on other servers, such as media servers. Although these external storage mechanisms are particularly convenient for integrating existing sets of multimedia data with a database, the multimedia data is not under transactional control if it is not stored in the database.

BLOBs are stored in the database tablespaces in a way that optimizes space and provides efficient access. Large BLOBs cannot be stored inline (BLOBs under 4 kilobytes can be stored inline) with other row data. Depending on the size of the BLOB, a locator is stored in the row and the actual BLOB (up to 8 terabytes to 128 terabytes, depending on the block size) is stored in other tablespaces. The locator can be considered a pointer to the actual location of the BLOB value. When you select a BLOB, you are selecting the locator instead of the value, although this is done transparently. An advantage of this design is that multiple BLOB locators can exist in a single row. For example, you might want to store a short video clip of a training tape, an audio recording containing a brief description of its contents, a syllabus of the course, a picture of the instructor, and a set of maps and directions to each training center all in the same row.

Because BFILEs are not under the transactional control of the database, users could change the external source without updating the database, thus causing an inconsistency with the BFILE locator.

Oracle Multimedia ORDAudio, ORDDoc, ORDImage, and ORDVideo object types provide wrapper methods to perform these functions:

  • Set the source of the data as local or external

  • Modify the time an object was last updated

  • Set information about the external source type, location, and name of the data

  • Transfer data into or out of the database

  • Obtain information about the local data content such as its length, location, or its handle to the BLOB, put the content into a temporary BLOB, or delete it

  • Access source data by opening it, reading it, writing to it, trimming it, and closing it


See Also:

Both manuals provide detailed information about using BLOBs and BFILEs.


1.9.2 Querying Multimedia Data

Once stored within a database, multimedia data can be queried and retrieved by using the various alphanumeric columns or object attributes of the table to find a row that contains the desired data. For example, you can select a video clip from the Training table where the course name is 'Oracle Database Concepts'.

Multimedia data can be queried by extracted metadata, by other relational table columns, and by content, such as image content-based retrieval.

1.10 Accessing Multimedia Data

Applications access and manipulate multimedia data using SQL, PL/SQL, OCI, or Java through the object relational types OrdAudio, OrdDoc, OrdImage, and OrdVideo.

The following subsections describe ways in which applications, Oracle development tools, and third-party development tools can access multimedia data stored in the database using Oracle Multimedia object types:

1.10.1 Oracle Multimedia Java API

Oracle Multimedia Java API enables Java applications on any tier (client, application server, or database) to manipulate and modify audio, image, and video data, or heterogeneous media data stored in a database. Oracle Multimedia Java API makes it possible for Java database connectivity (JDBC) result sets to include both traditional relational data and Oracle Multimedia media objects. This support enables applications to easily select and operate on a result set that contains sets of Oracle Multimedia columns plus other relational data. These classes also enable access to object attributes and invocation of object methods.


See Also:

Oracle Multimedia Java API Reference for more information about this Java API


1.10.2 Streaming Content from Oracle Database

You can stream audio and video content stored in Oracle Database using an Oracle Multimedia plug-in that supports a third-party streaming server, and deliver this content for play on a client that uses the browser-supported streaming player. Oracle Multimedia provides two plug-ins to stream content from Oracle Database: Oracle Multimedia Plug-in for RealNetworks Streaming Servers and Oracle Multimedia Plug-in for Windows Media Services.

To download these plug-ins, see the Oracle Multimedia Software section of the Oracle Technology Network Web site at

http://www.oracle.com/technology/products/multimedia/

Oracle Multimedia Plug-in for RealNetworks Streaming Servers

Oracle Multimedia Plug-in for RealNetworks Streaming Servers is a data source plug-in that enables RealNetworks servers to stream media data directly from Oracle Database to a media player client. The plug-in is installed with RealNetworks Streaming Server, and configured and managed using the administration tool of the streaming server. See Oracle Multimedia Plug-in for RealNetworks Streaming Servers Readme for more information.


See Also:

http://www.realnetworks.com/ for more information about streaming servers from RealNetworks


Oracle Multimedia Plug-in for Microsoft Windows Media Services

Oracle Multimedia Plug-in for Microsoft Windows Media Services enables Microsoft Windows Media servers to stream multimedia content to a client directly from Oracle Database. This package also includes a Plug-in Property Page that can be accessed from the Windows Media Services Administrative interfaces. The Plug-in Property Page enables users to inspect, define, and edit the Plug-in mount points that map to media content in Oracle Database. The Plug-in mount points are used to configure the source URL of a server publishing point, from which a Microsoft Windows Media Player client requests media content stored in Oracle Database. See Oracle Multimedia Plug-in for Microsoft Windows Media Services Readme for more information.

1.10.3 Support for Web Technologies

Using Oracle Multimedia support for Web technologies, you can easily integrate multimedia data into Web and Java applications. You can also store, retrieve, and manage rich media content in a database.

Oracle Multimedia Servlets and JSP Java API

Oracle Multimedia Servlets and JSP Java API facilitates the upload and retrieval of multimedia data stored in a database using the Oracle Multimedia OrdAudio, OrdDoc, OrdImage, and OrdVideo object types. Oracle Multimedia Servlets and JSP Java API uses Oracle Multimedia Java API to access data stored in the Oracle Multimedia object types. However, Oracle Multimedia Servlets and JSP Java API can also be used to handle upload and retrieval of data using BLOBs directly.

The OrdHttpResponseHandler class facilitates the retrieval of multimedia data from a database and its delivery to a browser or other HTTP client from Java servlets. The OrdHttpJspResponseHandler class provides the same features for JavaServer Pages (JSP).


Note:

JSP engines are not required to support access to the servlet binary output stream. Therefore, not all JSP engines support the delivery of multimedia data using the OrdHttpJspResponseHandler class.

Form-based file uploading using HTML forms encodes form data and uploaded files in Post requests using the multipart/form-data format. The OrdHttpUploadFormData class facilitates the processing of such requests by parsing the Post data and making the contents of regular form fields and the contents of uploaded files readily accessible to a Java servlet or JSP. The handling of uploaded files is facilitated by the OrdHttpUploadFile class, which provides an easy-to-use API that applications call to load audio, image, and video data, or heterogeneous media data into a database.


See Also:

Oracle Multimedia Servlets and JSP Java API Reference for more information about this Java API


Integration with Oracle Portal

Oracle Portal enables you to create useful and appealing enterprise portals. A key feature of the Oracle Portal framework are portlets, which provide convenient access to any type of data stored in database tables including rich content such as image, audio, and video data.

Oracle Portal has components that enable developers to create objects that capture, act upon, and display data from Oracle Database tables or views. You can connect these Oracle Portal components to create Web applications that can interact directly with enterprise databases. Because Oracle Multimedia objects are stored in Oracle Database tables, they can be included in the types of data available to Oracle Portal components.

Two Oracle Portal components are predefined: Forms and Reports. Oracle Portal wizards help you create forms and reports.

The Forms component builds a Web interface that lets users interact with data -- they can add, query, update, and delete information stored in the database. To enable users to upload and download rich content between the database and the portal framework, build a form on tables containing Oracle Multimedia objects.

The Reports component displays dynamic data in a columnar report format through a Web interface. A report build on tables containing Oracle Multimedia objects enables users to download rich media content from the database tables to the Oracle Portal framework.


See Also:

Oracle Fusion Middleware Developer's Guide for Oracle Portal in the Oracle Fusion Middleware Online Documentation Library for more information about Oracle Portal


Integration with Oracle Application Development Framework Business Components

For rapid development of media-rich Web applications, Oracle offers developers a Java integrated development environment (IDE), Oracle JDeveloper, that maximizes developer productivity. Oracle JDeveloper enables developers to build multitier, component-based Internet applications in Java that use Oracle Multimedia features to create visually attractive applications. Oracle Application Development Framework Business Components (ADF Business Components) is the component of JDeveloper that provides a set of intelligent software building blocks to manage common facilities. An Oracle Multimedia/ADF Business Components integration package includes media-specific domain classes and a set of utilities. The domain classes are wrappers of the classes of Oracle Multimedia Java API, and inherit all the underlying multimedia retrieval, upload, and manipulation methods. The domain classes support the ADF Business Components APIs and provide built-in integrated multimedia capabilities, while the utility classes support the retrieval, rendering, and uploading of multimedia content. Together, they provide a fully featured, integrated application development environment that enables a developer to create a wide variety of media-rich applications.

For more information about using Oracle Multimedia with Oracle JDeveloper and Oracle ADF Business Components, see the Oracle Multimedia/ADF Business Components Interactive Demonstration in the Oracle Multimedia Training section on the Oracle Technology Network Web site at

http://www.oracle.com/technology/products/multimedia/

1.10.4 Oracle Multimedia Support for Java Advanced Imaging (JAI)

Oracle Multimedia Java API describes three types of stream objects, which provide interfaces to BLOB and BFILE data that can be used by Java Advanced Imaging (JAI). These Java classes enable a JAI application to read and: write image data stored in a database using Oracle Multimedia OrdImage objects, or in BLOBs or BFILEs.


See Also:


1.11 Extending Oracle Multimedia

Oracle Multimedia can be extended to support:

  • Other external sources of media data not currently supported (other than BLOB, BFILE, or URL)

  • Other media data formats not currently supported


    Note:

    Oracle Multimedia can store any format. However, it can only extract metadata and process (image only) media data for formats that are supported or known to Oracle Multimedia.

  • Audio and video data processing

See Chapter 7 for more information about extending Oracle Multimedia.


See Also:

See the audio, image, and video data format appendixes in Oracle Multimedia Reference for the lists of supported formats


PK~I : PK"+AOEBPS/ap_demos.htm,7 Oracle Multimedia Sample Applications

A Oracle Multimedia Sample Applications

Oracle Multimedia provides several scripts and sample applications, written in C, SQL, PL/SQL, and Java. Most of them are available after you install the Oracle Database Examples media, which you can download from the Oracle Technology Network (OTN), in the locations shown in Table A-1.

Table A-1 Oracle Multimedia Sample Applications in Oracle Database Examples Media

NameLocation

ORDImage OCI C

Linux and UNIX: <ORACLE_HOME>/ord/img/demo

Windows: <ORACLE_HOME>\ord\img\demo

PL/SQL Web Toolkit Photo Album

Linux and UNIX: <ORACLE_HOME>/ord/http/demo/plsqlwtk

Windows: <ORACLE_HOME>\ord\http\demo\plsqlwtk

Code Wizard for the PL/SQL Gateway

Linux and UNIX: <ORACLE_HOME>/ord/http/demo/plsgwycw

Windows: <ORACLE_HOME>\ord\http\demo\plsgwycw

Oracle Multimedia Java API

Linux and UNIX: <ORACLE_HOME>/ord/im/demo/java

Windows: <ORACLE_HOME>\ord\im\demo\java

Oracle Multimedia Java Servlet Photo Album

Linux and UNIX: <ORACLE_HOME>/ord/http/demo/servlet

Windows: <ORACLE_HOME>\ord\http\demo\servlet

Oracle Multimedia JSP Photo Album

Linux and UNIX: <ORACLE_HOME>/ord/http/demo/jsp

Windows: <ORACLE_HOME>\ord\http\demo\jsp


You can download additional sample applications from the Oracle Multimedia OTN Web site (in the Software and Sample Code sections) at

http://www.oracle.com/technology/products/multimedia/

This appendix includes these sections:

A.1 Oracle Multimedia ORDImage OCI C Sample Application

After installing the Oracle Database Examples media, you can run the Oracle Multimedia ORDImage OCI C sample application to modify images. This sample application is written in C, and uses Oracle Call Interface (OCI) to access the database and process images using Oracle Multimedia.


See Also:

The README.txt file in the demo directory for more information about this sample application


A.2 Oracle Multimedia PL/SQL Sample Applications

These PL/SQL sample applications are available after installing the Oracle Database Examples media:

Oracle Multimedia PL/SQL Web Toolkit Photo Album Sample Application

The Oracle Multimedia PL/SQL Web Toolkit Photo Album sample application shows how to upload and retrieve media data using the PL/SQL Web Toolkit and PL/SQL Gateway. See Section 3.1 for more information about installing and using this application.


See Also:

The README.txt file in the demo directory for requirements and instructions for running this application


Oracle Multimedia Code Wizard Sample Application for the PL/SQL Gateway

The Oracle Multimedia Code Wizard sample application for the PL/SQL Gateway lets you create PL/SQL procedures for the PL/SQL Gateway to upload and retrieve media data stored in the database using any of the Oracle Multimedia object types. See Chapter 4 for more information about installing and using this application.


See Also:

The README.txt file in the demo directory for requirements and instructions for running this application


A.3 Oracle Multimedia Java Sample Applications

These Java sample applications are available after installing the Oracle Database Examples media:

Oracle Multimedia Java API Sample Application

The Oracle Multimedia Java API sample application shows how to use the audio, video, image, and media (ORDDoc) client-side Java classes to build your own Java applications. This Java sample application uses the sample schemas to demonstrate the use of the OrdAudio, OrdVideo, OrdImage, and OrdDoc Java objects. See Chapter 5 for more information about installing and using this application.


See Also:

The README.txt file in the demo directory for requirements and instructions for running this application


Oracle Multimedia Java Servlet Photo Album Sample Application

The Oracle Multimedia Java Servlet Photo Album sample application shows how to use Oracle Multimedia Servlets and JSP Java API to upload and retrieve multimedia data. See Section 3.2 for more information about installing and using this application.


See Also:

The README.txt file in the demo directory for requirements and instructions for running this application


Oracle Multimedia JavaServer Pages (JSP) Photo Album Sample Application

The Oracle Multimedia JSP Photo Album sample application shows how to use Oracle Multimedia Servlets and JSP Java API to upload and retrieve multimedia data. See Section 3.3 for more information about installing and using this application.


See Also:

The README.txt file in the demo directory for requirements and instructions for running this application


A.4 Other Oracle Multimedia Sample Applications

Additional Oracle Multimedia sample applications are available for download from the Oracle Multimedia OTN Web site (in the Software and Sample Code sections) at

http://www.oracle.com/technology/products/multimedia/

One of these OTN applications is the Oracle Multimedia JSP Tag Library Photo Album sample application. This Java sample application shows how to use tags from the Oracle Multimedia JSP Tag Library to retrieve media data from the database and deliver it to a browser, and how to upload media files into a database.


See Also:

  • Oracle Multimedia JSP Tag Library Guide for more information about installing and using this application

  • The README.txt file for requirements and instructions for running this application


PK? 17,7PK "+Aoa,mimetypePK"+AdޅID:iTunesMetadata.plistPK"+AYuMETA-INF/container.xmlPK"+A[pTOOEBPS/cover.htmPK"+AwpiZ~K~OEBPS/ch_appdev.htmPK"+Alo$++OEBPS/im_glossary.htmPK"+AOEBPS/title.htmPK"+A` kOEBPS/loe.htmPK"+AVjZZeOEBPS/ch_metadata.htmPK"+A-X^te8OEBPS/ch_imexapp.htmPK"+Aet/w.r.?MOEBPS/preface.htmPK"+Ao95L0L{OEBPS/ap_instl_upgrd.htmPK"+AbƻpOEBPS/ch_phtalbapps.htmPK"+A9K4KpOEBPS/index.htmPK"+A͇0z0OEBPS/img/cw14.gifPK"+AHO&,,OEBPS/img/cw1.gifPK"+A~=BBJOEBPS/img/cw16.gifPK"+Ai܈_[[OEBPS/img/view_album.gifPK"+AVmI*D*,OEBPS/img/cw4.gifPK"+Av̔pLLOEBPS/img/cw8.gifPK"+AU ͝&&aOEBPS/img/upload_photo.gifPK"+A5'="=OEBPS/img/cw2.gifPK"+A:88OEBPS/img/search_metadata.gifPK"+A0;,6,1OEBPS/img/cw17.gifPK"+AFDD+OEBPS/img/view_metadata.gifPK"+A00pOEBPS/img/view_entry.gifPK"+A2 % OEBPS/img/cw5.gifPK"+AC>0 OEBPS/img/cw12.gifPK"+A\g#b# OEBPS/img/cw3.gifPK"+A[n<00Y OEBPS/img/cw6.gifPK"+A>>8 OEBPS/img/cw11.gifPK"+A}sIWDWVX OEBPS/img/cw7.gifPK"+AP ޯ OEBPS/img/cw13.gifPK"+Ae 44޼ OEBPS/img/imurg001.gifPK"+A 3.33 OEBPS/img/write_metadata.gifPK"+Aٸ}BxB% OEBPS/img/cw18.gifPK"+ATa%\%Ph OEBPS/img/search_album.gifPK"+A_0Z0 OEBPS/img/cw10.gifPK"+A1@SZHH OEBPS/img/cw9.gifPK"+APQ;262 OEBPS/img/cw15.gifPK"+ACϲ@: OEBPS/img/imurg002.gifPK"+A6 OEBPS/img_text/search_album.htmPK"+AA$S OEBPS/img_text/cw12.htmPK"+Aƙ5d_t OEBPS/img_text/cw1.htmPK"+A\{%  OEBPS/img_text/imurg002.htmPK"+Aa \ ! OEBPS/img_text/write_metadata.htmPK"+Arֺ: OEBPS/img_text/cw6.htmPK"+Awl OEBPS/img_text/cw11.htmPK"+Ae? OEBPS/img_text/cw15.htmPK"+Az 7 OEBPS/img_text/cw3.htmPK"+A  OEBPS/img_text/cw10.htmPK"+Aq5  OEBPS/img_text/view_album.htmPK"+A[ͽ P OEBPS/img_text/view_metadata.htmPK"+A័̌ OEBPS/img_text/imurg001.htmPK"+A6