// ---------------------------------------------------------------------------
// - XmlContent.cpp -
// - afnix:xpe module - xml content class implementation -
// ---------------------------------------------------------------------------
// - This program is free software; you can redistribute it and/or modify -
// - it provided that this copyright notice is kept intact. -
// - -
// - This program is distributed in the hope that it will be useful, but -
// - without any warranty; without even the implied warranty of -
// - merchantability or fitness for a particular purpose. In no event shall -
// - the copyright holder be liable for any direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software. -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2007 amaury darsch -
// ---------------------------------------------------------------------------
#include "Uri.hpp"
#include "Runnable.hpp"
#include "InputFile.hpp"
#include "TcpClient.hpp"
#include "QuarkZone.hpp"
#include "Exception.hpp"
#include "XmlContent.hpp"
#include "HttpRequest.hpp"
#include "HttpResponse.hpp"
namespace afnix {
// -------------------------------------------------------------------------
// - private section -
// -------------------------------------------------------------------------
// the uri file scheme
static const String URI_FILE_SCHM = "file";
// the uri http scheme
static const String URI_HTTP_SCHM = "http";
// the uri default path
static const String URI_PATH_XDEF = "/";
// the uri default port
static const long URI_PORT_XDEF = 80;
// get an input file stream
static Input* get_file_stream (const Uri& uri) {
try {
// get the system path from the uri path
String path = uri.getsysp ();
// open a file for input
return new InputFile (path);
} catch (...) {
throw Exception ("file-error", "cannot access uri", uri.getname ());
}
}
// get an input http stream
static Input* get_http_stream (const Uri& uri) {
// create a http request by uri
HttpRequest hrq (uri);
// get the uri host
String host = uri.gethost ();
// get the port
long port = uri.getport ();
// open a tcp socket
TcpClient* s = new TcpClient (host, port);
// write the request
hrq.write (*s);
// create a response
HttpResponse* hrs = new HttpResponse (s);
try {
// check for ok
if (hrs->isok () == true) return hrs;
// check for another location
if (hrs->ishloc () == true) {
Uri huri = hrs->gethloc ();
delete hrs;
return get_http_stream (huri);
}
// invalid response
throw Exception ("http-error", "cannot access uri", uri.getname ());
} catch (...) {
delete hrs;
throw;
}
}
// get the content stream by uri name
static Input* get_content_stream (const String& unam) {
// create a uri by name
Uri uri = unam;
// get the uri scheme
String sch = uri.getscheme ();
// select from the uri scheme
if (sch == URI_FILE_SCHM) return get_file_stream (uri);
if (sch == URI_HTTP_SCHM) return get_http_stream (uri);
// invalid uri scheme to process
throw Exception ("scheme-error", "invalid xml content uri scheme", sch);
}
// -------------------------------------------------------------------------
// - class section -
// -------------------------------------------------------------------------
// create a xml content by name
XmlContent::XmlContent (const String& name) {
// save the name
d_name = name;
// normalize the document name
String unam = Uri::sysname (name);
// get the input stream
Input* is = get_content_stream (unam);
// set the document root
setroot (unam, is);
}
// create a xml content by name and document name
XmlContent::XmlContent (const String& name, const String& docn) {
// save the name
d_name = name;
// normalize the document name
String unam = Uri::sysname (docn);
// get the input stream
Input* is = get_content_stream (unam);
// set the document root
setroot (unam, is);
}
// create a xml content by name, document name and encoding mode
XmlContent::XmlContent (const String& name, const String& docn,
const String& emod) {
// save the name
d_name = name;
// normalize the document name
String unam = Uri::sysname (docn);
// get the input stream
Input* is = get_content_stream (unam);
// set the encoding mode
is->setemod (emod);
// set the document root text
setrtxt (unam, is);
}
// copy construct this content
XmlContent::XmlContent (const XmlContent& that) : XmlDocument (that) {
that.rdlock ();
d_name = that.d_name;
that.unlock ();
}
// get the content name
String XmlContent::getname (void) const {
rdlock ();
String result = d_name;
unlock ();
return result;
}
// get the document name
String XmlContent::getdocn (void) const {
rdlock ();
try {
String result = XmlDocument::getname ();
unlock ();
return result;
} catch(...) {
unlock ();
throw;
}
}
// -------------------------------------------------------------------------
// - object section -
// -------------------------------------------------------------------------
// the quark zone
static const long QUARK_ZONE_LENGTH = 1;
static QuarkZone zone (QUARK_ZONE_LENGTH);
// the object supported quarks
static const long QUARK_GETDOCN = zone.intern ("get-document-name");
// create a new object in a generic way
Object* XmlContent::mknew (Vector* argv) {
long argc = (argv == nilp) ? 0 : argv->length ();
// check for 1 argument
if (argc == 1) {
String name = argv->getstring (0);
return new XmlContent (name);
}
// wrong arguments
throw Exception ("argument-error",
"too many arguments with xml processor constructor");
}
// return true if the given quark is defined
bool XmlContent::isquark (const long quark, const bool hflg) const {
rdlock ();
if (zone.exists (quark) == true) {
unlock ();
return true;
}
bool result = hflg ? XmlDocument::isquark (quark, hflg) : false;
unlock ();
return result;
}
// apply this object with a set of arguments and a quark
Object* XmlContent::apply (Runnable* robj, Nameset* nset, const long quark,
Vector* argv) {
// get the number of arguments
long argc = (argv == nilp) ? 0 : argv->length ();
// check for 0 argument
if (argc == 0) {
if (quark == QUARK_GETDOCN) return new String (getdocn ());
}
// call the xml document method
return XmlDocument::apply (robj, nset, quark, argv);
}
}
syntax highlighted by Code2HTML, v. 0.9.1