/*
* Copyright 2000 Draagon Software, Inc. All Rights Reserved.
*
* This software is the proprietary information of Draagon Software, Inc.
* Use is subject to license terms.
*
*/
package com.draagon.wii;
import com.draagon.wii.internal.*;
import com.draagon.wii.util.*;
import com.draagon.timers.MethodTimer;
import java.io.*;
import java.util.Date;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* This WIIKernel is the core of the Draagon Web Integrator integration product. It
* handles the incoming requests, routing them to the external systems, parsing
* the response data and returning the response to the client.
*
* @author Doug Mealing
* @version 1.3, 12/17/00
* @since JDK1.2
*/
public class WIIKernel
{
/**
* The string representing the kernel version.
*/
public final static String VERSION = "Draagon Web Integrator Version 1.8.0";
private static Log log = LogFactory.getLog( WIIKernel.class );
/**
* Empty constructor
*/
public WIIKernel()
{
}
public void serviceInternal( WIIRequest req, WIIResponse res, InternalService is )
throws IOException, WIIException
{
if ( log.isDebugEnabled() )
log.debug( "(serviceInternal) Processing Internal Service: [" + is.getName() + "]" );
req.setAttribute( "wii.request", req );
req.setAttribute( "wii.response", res );
req.setAttribute( "internal.service", is );
if ( is.canAccess( req.getUser() ))
{
MethodTimer mt = new MethodTimer( is, "service" );
is.service( req, res );
mt.done();
}
else
{
String name = req.getUser().get( WIIUser.WII_USERNAME );
if ( log.isDebugEnabled() )
log.debug( "(serviceInternal) User [" + name + "] did not have correct roles" );
req.getDevice().returnAccessError( req, res, "No Access", "The user [" + name + "] may not access the [" + is.getName() + "] internal service" );
}
}
/**
* This is the main method in the kernel and performs all needed actions to
* process a request.
*
* @param req The WIIRequest object that can be used to access additional
* information about the request.
* @param res The WIIResponse object that is used to return the response to
* the client.
* @exception WIIException This exception is used if any errors are
* encountered.
*/
public void serviceExternal( WIIRequest req, WIIResponse res )
throws IOException, WIIException
{
if ( log.isDebugEnabled() )
{
String tmp = req.getPathInfo();
if ( req.getQueryString() != null ) tmp += req.getQueryString();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter( sw );
pw.println( "(serviceExternal) ------------------------------------------------------" );
pw.println( "Timestamp: " + ( new Date() ).toString() );
pw.println( "Request: {" + req.getMethod() + "} " + tmp );
pw.println( "Site: {" + req.getSite().getName() + "} " + req.getSite().getExternalURL( req.getPathInfo() ));
pw.println( "User: " + req.getUser().get( WIIUser.WII_USERNAME ) + " - " + req.getUser().get( WIIUser.WII_REALNAME ));
pw.close();
log.debug( sw.toString() );
}
// Perform the security check
if ( !req.getSite().canAccess( req.getUser() ))
{
String name = req.getUser().get( WIIUser.WII_USERNAME );
if ( log.isDebugEnabled() )
log.debug( "(serviceExternal) User [" + name + "] did not have correct roles" );
req.getDevice().returnAccessError( req, res, "No Access", "The user [" + name + "] may not access the [" + req.getSite().getName() + "] site" );
return;
}
InputStream is = null;
//OutputStream out = null;
//String errorStr = null;
WIIConnector connector = null;
List<NameValuePair> reqHeaders = req.getRequestHeaders();
// MethodTimer mt = new MethodTimer( "com.draagon.wii.WIIKernel.processParameters" );
MethodTimer mt = new MethodTimer ( this, "processReqParams" );
// Get all the request parameters
for(WIIRequestHeaders f : req.getWIIRequestHeaders() ) {
// System.out.println( "getHeadereters: " + f.getClass().getName() );
f.processRequestHeaders( req, reqHeaders );
if ( log.isDebugEnabled() )
log.debug( "(serviceExternal) Request Header class: " + f.getClass().getName() );
}
mt.done();
// Get the connector module
connector = req.getWIIConnector();
if ( log.isDebugEnabled() )
log.debug( "(serviceExternal) Connector class: " + connector.getClass().getName() );
// Connect to the external system and retrieve the input stream
//mt = new MethodTimer( "com.draagon.wii.WIIKernel.connector.doRequest" );
mt = new MethodTimer( connector, "doRequest" ) ;
is = connector.doRequest( req, reqHeaders );
req.setExternalInputStream( is );
mt.done();
// Get the HTTP response headers
//mt = new MethodTimer( "com.draagon.wii.WIIKernel.connector.getResponse" );
mt = new MethodTimer( this, "getResponse" );
List<NameValuePair> retHeaders = connector.getResponseHeaders();
mt.done();
// Set the default for text/html
String content = connector.getContentType();
req.setExternalContentType( content );
if ( log.isDebugEnabled() )
log.debug( "(serviceExternal) Content Type: " + content );
// Set the default for text/html
int code = connector.getStatusCode();
req.setExternalStatusCode( code );
if ( log.isDebugEnabled() )
log.debug( "(serviceExternal) Status Code: " + code );
// Handle all the response headers
mt = new MethodTimer ( this, "processResHeaders" );
for( WIIResponseHeaders f : req.getWIIResponseHeaders() )
{
if ( log.isDebugEnabled() )
log.debug( "(serviceExternal) Response Header class: " + f.getClass().getName() );
f.processResponseHeaders( req, res, retHeaders );
}
mt.done();
// Set the response headers
setHeaders( req, res, retHeaders );
// Add the header
if ( log.isDebugEnabled() )
log.debug( "(serviceExternal) Adding header" );
if ( req.getTemplate() != null )
{
MethodTimer mt4 = new MethodTimer( req, "addHeader" );
req.getTemplate().addHeader( res );
res.flush();
mt4.done();
}
// Process the data
processData( req, res );
// Flush the processed data
res.flush();
// Add the footer
if ( log.isDebugEnabled() )
log.debug( "(serviceExternal) Adding footer" );
if ( req.getTemplate() != null )
{
// Add the footer
MethodTimer mt4 = new MethodTimer( req, "addFooter" );
req.getTemplate().addFooter( res );
res.flush();
mt4.done();
}
if ( log.isDebugEnabled() )
log.debug( "(serviceExternal) Closing streams" );
// Don't worry about an exception here
try {
res.close();
} catch( Exception e ) {
if ( log.isDebugEnabled() ) log.debug( "Could not close output: " + e.getMessage(), e );
}
// Don't worry about an exception here
try {
is.close();
} catch( Exception e ) {
if ( log.isDebugEnabled() ) log.debug( "Could not close input: " + e.getMessage(), e );
}
if ( log.isDebugEnabled() )
log.debug("(serviceExternal) Exiting...");
}
public void setHeaders( WIIRequest req, WIIResponse res, List<NameValuePair> retHeaders )
throws IOException, WIIException
{
// Set the status code
int code = req.getExternalStatusCode();
if ( log.isDebugEnabled() )
log.debug("(setHeaders) Setting the status code: " + code );
res.setStatusCode( code );
// Set the content type
String content = req.getExternalContentType();
if ( content != null && !content.equals( "" ))
{
if ( log.isDebugEnabled() )
log.debug("(setHeaders) Setting content type: " + content );
res.setContentType( content );
}
else if ( log.isDebugEnabled() )
log.debug("(setHeaders) The content type not specified" );
// Set the HTTP response headers
for( NameValuePair pair : retHeaders )
{
res.addHeader( pair.getName(), pair.getValue() );
if ( log.isDebugEnabled() )
log.debug( "(setHeaders) Setting response headers [" + pair.getName() + ":" + pair.getValue() + "]" );
}
// PrintWriter out = res.getWriter();
}
public void processData( WIIRequest req, WIIResponse res )
throws IOException, WIIException
{
String content = req.getExternalContentType();
// InputStream is = req.getExternalInputStream();
// Create the WIIStream for parsing
WIIStream stream = req.getWIIStream( content );
if ( log.isDebugEnabled() )
log.debug("(processData) Processing data with stream: " + stream.getClass().getName() );
// Process the actual data
MethodTimer mt = new MethodTimer( stream, "process" );
stream.process( res );
mt.done();
if ( log.isDebugEnabled() )
log.debug( "(processData) Data processing completed" );
}
}