I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit 418facc7 authored by aum's avatar aum Committed by zzz
Browse files

Added apps/q - the Q distributed file store framework, by aum

parent 7f3c953e
No related branches found
No related tags found
No related merge requests found
Showing
with 4151 additions and 0 deletions
apps/q/doc/client.jpg

31.5 KiB

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Q System Diagrams</title>
</head>
<body>
<h1>Q Diagrams</h1>
Informal system diagrams of Q network, hubs and clients.
<center>
<hr>
<img src="overall.jpg">
<hr>
<img src="client.jpg">
<hr>
<img src="hub.jpg">
</center>
<hr>
<address><a href="mailto:aum@mail.i2p">aum</a></address>
<!-- Created: Sat Apr 16 17:24:02 NZST 2005 -->
<!-- hhmts start -->
Last modified: Mon Apr 18 14:06:02 NZST 2005
<!-- hhmts end -->
</body>
</html>
apps/q/doc/hub.jpg

27.1 KiB

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Quartermaster - I2P Distributed File Store</title>
</head>
<body>
<center>
<h1>Quartermaster<br>an I2P Distributed File Store</h1>
<h3>STATUS<h3>
<i>Whole new (incompatible) version currently in development;
ETA for release approx 4-7 days;
view screenshots <a href="screenshots.html">here</a>
</i>
<br>
<hr>
<small>
<a href="manual/index.html">User Manual</a> |
<a href="spec/index.html">Protocol Spec</a> |
<a href="metadata.html">Metadata Spec</a> |
<a href="diagrams.html">Q Pr0n (diagrams)</a> |
<a href="api/index.html">API Spec</a> |
<a href="qnoderefs.txt">qnoderefs.txt</a> |
Full Download |
Updated jar
</small>
</center>
<hr>
<h2>Intro</h2>
Quartermaster, or Q for short, is a distributed file storage framework for I2P.
<h2>Features</h2>
<ul>
<li>Now features 'QSites' - the Q equivalent of Freenet freesites,
static websites which are retrievable even if author is offline</li>
<li>Easy web interface - interact with Q (and view/insert QSites)
from your web browser</li>
<li>Maximum expectations of content retrievability</li>
<li>Content security akin to Freenet CHK and SSK keys</li>
<li>Powerful, flexible search engine</li>
<li>Comfortably accommodates both permanent and transient
nodes without significant network disruption (for instance,
no flooding of the I2P network with futile
calls to offline nodes)</li>
<li>Rapid query resolution, due to distributed catalogue
mirroring which eliminates all in-network query traffic</li>
<li>Modular, extensible architecture</li>
<li>Simple interfaces for 3rd-party app developers</li>
<li>Is custom-designed and built around I2P, so no duplication of
I2P's encryption/anonymity features</li>
<li>Simple XML-RPC interface for all inter-node communication, makes it easy to
implement user-level clients in any language; also allows alternative
implementations of core server and/or client nodes.</li>
</ul>
<hr>
<h2>Status</h2>
Q is presently under development, and a test release is expected soon.
<hr>
<h2>Architecture</h2>
Refer to the <a href="spec/index.html">Protocol Specification</a> for more information.
<hr>
<!-- Created: Sat Mar 26 11:09:12 NZST 2005 -->
<!-- hhmts start -->
Last modified: Mon Apr 18 18:55:19 NZST 2005
<!-- hhmts end -->
</body>
</html>
This diff is collapsed.
rise on each hit:
dy = (1 - y) / kRise
fall after each time unit:
dy = y / kFall
fall after time dt:
dy = - y ** - (dt / kFall)
after the next hit:
y = y - y ** (- dt / kFall) + (1 - y) / kRise
first attempt at a load measurement algorithm:
- kFall is an arbitrary constant which dictates decay rate of load
in the absence of hits
- kRise is another constant which dictates rise of load with each hit
- dt is the time between each hit
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Q Metadata Specification</title>
<style type="text/css">
<!--
td { vertical-align: top; }
code { font-family: courier, monospace; font-weight: bolder; font-size:smaller }
-->
</style>
</head>
<body>
<h1>Q Metadata Specification</h1>
<h2>1. Introduction</h2>
This document lists the standard metadata keys for Q data items,
discussing the rules of metadata insertion, processing and validation.<br>
<hr>
<h3>1.1. Definitions</h3>
To avoid confusions in terminology, this document will strictly abide the following definitions:
<br>
<br>
<table width=80% cellspacing=0 cellpadding=4 border=1 align=center>
<tr style="font-weight: bold">
<td>Term</td>
<td>Definition</td>
</tr>
<tr>
<td><code>key</code></td>
<td>A metadata category name, technically a <code>key</code> as the word is used with
Java <code>Hashtable</code> and Python <code>dict</code> objects.</td>
</tr>
<tr>
<td><code>uri</code></td>
<td>A Uniform Resource Indicator for an item of content stored within the Q network.<br>
Q URIs have the form: <code>Q:&lt;basename&gt;[,&lt;cryptoKey&gt;][&lt;path&gt;]</code>
<br>
<br>
Some examples:
<ul>
<li><code>Q:fhvnr3HFSK234khsf90sdh42fsh</code> (a plain hash uri, no cryptoKey)</li>
<li><code>Q:e54fhjeo39schr2kcy4osEH478D/files/johnny.mp3</code> (a secure space URI,
no cryptoKey)</li>
<li><code>Q:vhfh4se987WwfkhwWFEwkh3234S,47fhh2dkhseiyu</code> (a plain hash URI, with
a cryptoKey)</li>
</td>
</tr>
<tr>
<td><code>basename</code></td>
<td>The basic element of a Q uri. This will be a base64-encoded hash - refer below to
URI calculation procedures</td>
</tr>
<tr>
<td><code>cryptoKey</code></td>
<td>An optional session encryption key for the stored data, encoded as base64.
This affords some protection to server node operators, and gives them a level
of plausible deniability for whatever gets stored in their server's
datastore without their direct human awareness.</td>
</tr>
<tr>
<td><code>path</code></td>
<td>Whever an item of content is inserted in <code>secure space</code> mode, this path
serves as a pseudo-pathname, and is conceptually similar to the <code>path</code>
component in (for example) standard HTTP URLs
<code>http://&lt;domainname&gt;[:&lt;port&gt;][&lt;path&gt;]</code>, such as
<code>http://slashdot.org/faq/editorial.shtml</code> (whose <code>path</code>
is <code>/faq/editorial.shtml</code>).<br>
<br>
Paths, if not empty, should contain a leading slash ("/").
If an application specifies a non-empty <code>path</code> that doesn't begin with a
leading '/', a '/' will be automatically prepended by the receiving node.
</td>
</tr>
<tr>
<td><code>plain hash</code></td>
<td>A mode of inserting items, whereby the security of the resulting URI comes from
computing the URI from a hash of the item's data and metadata (and imposing a
mathematical barrier against spoofing content under a given URI). Corresponds to
Freenet's <code>CHK@</code> keys.</td>
</tr>
<tr>
<td><code>secure space</code></td>
<td>A mode of inserting items where the security of the URI is based not on a hash of the
item's data and metadata (as with <code>plain hash</code> mode),
but on the <code>privateKey</code> provided by the
application, and a content signature created from that private key.
Corresponds to Freenet's <code>SSK@</code> keys. Within a secure space, you
can insert any number of items under different pseudo-pathnames (as is the case
with Freenet SSK keys).
</li>
</table>
<br><br>
<hr>
<h3>2.1. Keys Inserted By Application Before sending <code>putItem</code> RPCs</h3>
As the heading suggests, this is a list of metadata keys which should be inserted by a
Q application prior to invoking a <code>putItem</code> RPC on the local Q client node.<br>
<br>
<table width=80% cellspacing=0 cellpadding=4 border=1 align=center>
<tr style="font-weight: bold">
<td>Key</td>
<td>Data Type</td>
<td>Description</td>
</tr>
<tr>
<td><code>title</code></td>
<td>String</td>
<td>Optional but strongly recommended. A free-text short description of the item,
should be less than 80 characters. The idea is that applications should
support a 'view' of catalogue data that shows item titles. (Prior Q convention of
titles expressed as valid filename syntax has been abandoned).
</td>
</tr>
<tr>
<td><code>path</code></td>
<td>String</td>
<td>Optional but strongly recommended.
A virtual 'pathname' for the item, which should be in valid *nix
absolute pathname syntax (beginning with '/', containing no '//', consisting
only of alphanumerics, '-', '_', '.' and '/'.<br>
<br>
In Q web interfaces, the <code>filename</code> component of this path will
serve as the recommended filename when downloading/saving the item.<br>
<br>
If the application also provides a
<code>privateKey</code> key, the path
is used in conjunction with the private key to generate <code>publicKey</code>
and <code>signature</code> keys (see below), and ultimately the final <code>uri</code>
under which the item can be retrieved by others.<br>
<br>
Refer also to <code>mimetype</code> below.
</td>
</tr>
<tr>
<td><code>encrypt</code></td>
<td>String</td>
<td>Optional. If this key is present, and has a value "1", "yes" or "true",
this indicates that the application wishes the data to be stored on servers in
encrypted form.<br>
<br>
If this key is present and set to a positive value, the Q node, on receiving the
<code>putItem</code> RPC, will:
<ol>
<li>Generate a random symmetric encryption key</li>
<li>Encrypt the item's data using this encryption key</li>
<li>Delete the <code>encrypt</code> key from the metadata</li>
<li>Enclose a base64 representation of this encryption key in the RPC response
it sends back to the application (embedded in the <code>uri</code></li>
</ol>
</td>
</tr>
<tr>
<td><code>type</code></td>
<td>String</td>
<td>Optional but strongly recommended. A standard ed2k specifier, one of <code>text html image
audio video archive other</code></td>
</tr>
<tr>
<td><code>mimetype</code></td>
<td>String</td>
<td>Optional but moderately recommended. Mimetype designation of data, eg <code>text/html</code>,
<code>image/jpeg</code> etc. If not specified, an attempt will be made to guess
a mometype from the value of the <code>path</code> key. If this attempt fails, then
this key will be set to <code>application/x-octet-stream</code> by the node receiving
the <code>putItem</code> RPC.</td>
</tr>
<tr>
<td><code>keywords</code></td>
<td>String</td>
<td>Optional but moderately recommended.
A set of keywords, under which the inserting app would like this item to be
discoverable. Keywords should be entirely lower case and comma-separated. Content
inserts should consider keywords carefully, and only use space characters inside
keywords when necessary (eg, for flagging a distinctive phrase containing very
common words).</td>
<tr>
<td><code>privateKey</code></td>
<td>String</td>
<td>Optional. A Base64-encoded signing private key, in cases where the application wishes
to insert an item in <code>signed space</code> mode. This can be accompanied by another key,
<code>path</code>, indicating a 'path' within the signed space. If 'path'
is not given, it will default to '/'.<br>
<br>
Either way, when a node receives a
<code>putItem</code> RPC containing a <code>privateKey</code> in its metadata,
it removes this key and replaces it with <code>publicKey</code> and
<code>signature</code>.
</td>
</tr>
<tr>
<td><code>path</code></td>
<td>String</td>
<td>Optional. The virtual pathname, within signed space, under which to store the item.
This gets ignored and deleted unless the application also provides a
<code>privateKey</code> as well. But if the private key is given, the path
is used in conjunction with the private key to generate <code>publicKey</code>
and <code>signature</code> keys (see below).<br>
<code>path</code> should be a 'unix-style pathname', ie, containing only slashes
as (pseudo) directory delimiters, and alphanumeric, '-', '_' and '.' characters,
and preferably ending in a meaningful file extension such as <code>.html</code>
</td>
</tr>
<tr>
<td><code>expiry</code></td>
<td>int</td>
<td>Unixtime at which the inserted item should expire. When this expiry time
is reached, the item won't necessarily be deleted straight away, but may
be deleted whenever a node's data store is full.<br>
<br>
If this is not provided, it will default to a given duration according to
the client node's configuration.<br>
<br>
If it is provided, by an application, then the client node will transparently
generate the required 'rent payment' before caching the data item and uploading
it to servers.
</td>
</tr>
</table>
<br><br>
<hr>
<h3>2.2. Keys Inserted By Node Upon Receipt Of <code>putItem</code> RPC</h3>
<table width=80% cellspacing=0 cellpadding=4 border=1 align=center>
<tr style="font-weight: bold">
<td>Key</td>
<td>Data Type</td>
<td>Description</td>
</tr>
<tr>
<td><code>size</code></td>
<td>Integer</td>
<td>Size of the data to be inserted, in bytes.</td>
</tr>
<tr>
<td><code>dataHash</code></td>
<td>String</td>
<td>base64-encoded SHA256 hash of data.</td>
</tr>
<tr>
<td><code>uri</code></td>
<td>String</td>
<td>This depends on whether the item is being inserted in <i>plain</i> or
<i>signed space</i> mode.<br>
<br>
If inserting in <i>plain</i> mode, then the uri is in the form
<code>Q:somebase64hash</code>, where the hash is computed according to
the <a href="#plainhash">plain hash calculation procedure</a>.<br>
<br>
If inserting in <i>signed space</i> mode, then the uri will be in the form
<code>Q:somebase64hash/path.ext</code>, where the hash is computed as per
the <a href="#signedhash">signed space hash calculation procedure</a>, and
the <code>/path.ext</code> is the verbatim value of the app-supplied
<code>path</code> key.
</td>
</tr>
<tr>
<td><code>publicKey</code></td>
<td>String</td>
<td>Base64-encoded signing public key. In cases where app provides
<code>privateKey</code>,
a node will derive the signing public key from the private key,
delete the private key from the metadata, and replace it with its corresponding
public key
key.</td>
</tr>
<tr>
<td><code>signature</code></td>
<td>String</td>
<td>Base64-encoded signature of <code>path+dataHash</code>, created using
the app-provided <code>privateKey</code>.</td>
</tr>
<tr>
<td><code>rent</code></td>
<td>String</td>
<td>A rent payment for the data's accommodation on the server.<br>
Intention is to support a variety of payment tokens. Initially, the
only acceptable form of payment will be a hashcash-like token,
in the form <code>hashcash:base64string</code>. The <code>hashcash:</code>
prefix indicates that this payment is in hashcash currency, in which case
the <code>base64String</code> should decode to a 16-byte string whose
SHA256 hash partially collides with <code>dataHash</code>.
The greater the number of bits in the collision,
the longer the data's accommodation will be 'paid up for'.<br>
<br>
If this key is already present, a Q node will verify the hashcash,
and adjust the <code>expiry</code> key value to the time the item's accommodation
is paid up till.<br>
<br>
If the key is not present:
<ul>
<li>A client node will generate a value for this key with enough collision bits
to pay the accommodation up till the given app-specified <code>expiry</code> date.</li>
<li>A server node will grant temporary free accommodation, and adjust the <code>expiry</code>
key to the end of the free accommodation period.</li>
</ul>
</td>
</tr>
</table>
<br><br>
<a name="plainhash"/>
<hr>
<h2>3. URI Determination Procedures</h2>
<h3>3.1. Plain Hash URI Calculation Procedure</h3>
When items are inserted in <code>plain</code> mode, the final URI is determined from
a hash of the data and metadata. Security of the item is based on the mathematical difficulty
of creating an arbitrary data+metadata set whose hash collides with the target URI.<br>
<br>
Specifically, the recipe for calculating plain hash URIs is:
<ol>
<li>If the key <code>size</code> is missing, set this to the size of the data,
in bytes</li>
<li>If the key <code>dataHash</code> is missing, set this to the base64-encoded
SHA256(data)</li>
<li>If the key <code>title</code> is missing, set this to the value of <code>dataHash</code></li>
<li>From the metadata, create a set of strings, each in the form <code>key=value</code>,
where each line contains a metadata <code>key</code> and its <code>value</code>, and
is terminated by an ASCII linefeed (\n, 0x10).</li>
<li>Ensure that key <code>uri</code> is omitted</li>
<li>Sort the strings into ascending ASCII sort order</li>
<li>Concatenate the strings together into one big string</li>
<li>Calculate the SHA256 hash of this string</li>
<li>Encode the hash into Base64</li>
<li>Prepend the string <code>Q:</code> to this</li>
</ol>
<a name="signedhash"/>
<hr>
<h3>3.2. Signed Space URI Calculation Procedure</h3>
This is much simpler than determining plain hash URI, since the security of the URI
is based not on hashes of data and metadata, but on the cryptographic <code>privateKey</code>
given by the application.<br>
<br>
Calculation recipe for Signed Space URIs is:
<ol>
<li>Calculate the SHA256 hash of the private key's binary data (not its base64 representation)</li>
<li>Encode this hash into base64, dropping any trailing '=' characters</li>
<li>Append to this the value of metadata item <code>path</code> (recall that <code>path</code>,
if not empty, must begin with a '/')</li>
<li>Prepend the string <code>Q:</code> to this</li>
</ol>
The resulting URI then is in the form <code>Q:pubkeyHash/path.ext</code>
<hr>
<!-- Created: Tue Apr 5 00:56:45 NZST 2005 -->
<!-- hhmts start -->
Last modified: Wed Apr 6 00:36:37 NZST 2005
<!-- hhmts end -->
</body>
</html>
apps/q/doc/overall.jpg

36.1 KiB

rxvXpHKfWGWsql4PJaHglAERSUYyrdKKAzK6jPHT4QXRf9jgcVd4mInq0j6H4inVOzT9dG4L6c9GrlQwe4ysUm5jSTyZemxiZpQDCAazsoRzNDv6gevA40J6uGl10JtVtOjqXW8Ej0JUKubz88g~ogPb1h4Xibc-RrtqrvsJebg5xYFkLlnr7DxDtiWzIMRSZ9Ri2P~eq0SwZzd81tvASPj5fb3nySHeABAuY8HrNu0gqRLjeayDpd3OK1ogrxf1lMvfutn5pnLrlVcvKHa~6rNWWGSulsuEYWtpUd4Itj9aKqIgF9ES7RF77Z73W1f6NRTHO48ZLyLLaKVLjDIsHQP-0mOevszcPjFWtheqRKvT2D28WEMpVC-mPtfw91BkdgBa3pwWhwG~7KIhvWhGs8bj2NOKkqrwYU7xhNVaHdDDkzv4gsweCutHNiiCF~4yL54WzCIfSKDjcHjQxxVkh2NKeaItzgw9E~mPAKNZD22X~2oAuuL9i~0lldEV1ddUAAAA
\ No newline at end of file
apps/q/doc/screenshot-home.jpg

58.7 KiB

apps/q/doc/screenshot-iewarn.jpg

45.1 KiB

apps/q/doc/screenshot-qsite.jpg

45.7 KiB

apps/q/doc/screenshot-search.jpg

22.1 KiB

apps/q/doc/screenshot.jpg

29.9 KiB

apps/q/doc/screenshot.png

98.3 KiB

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Q Screenshots</title>
</head>
<body>
<h1>Q Screenshots</h1>
<ul>
<li><a href="screenshot-search.jpg">Search Screen</li>
<li><a href="screenshot-qsite.jpg">QSite Insertion Form</li>
<li><a href="screenshot-iewarn.jpg">Q Security Features</li>
</ul>
<hr>
<address><a href="mailto:aum@mail.i2p">aum</a></address>
<!-- Created: Sat Apr 16 17:24:02 NZST 2005 -->
<!-- hhmts start -->
Last modified: Mon Apr 18 14:06:02 NZST 2005
<!-- hhmts end -->
</body>
</html>
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="all" name="aum">
<!-- Written to assume that classpath is rooted in the current directory. -->
<!-- So this should be OK if you make this script in the root of a filesystem. -->
<!-- If not, just change src.dir to be the root of your sources' package tree -->
<!-- and use e.g. View over a Filesystem to mount that subdirectory with all capabilities. -->
<!-- The idea is that both Ant and NetBeans have to know what the package root is -->
<!-- for the classes in your application. -->
<!-- Don't worry if you don't know the Ant syntax completely or need help on some tasks! -->
<!-- The standard Ant documentation can be downloaded from AutoUpdate and -->
<!-- and then you can access the Ant manual in the online help. -->
<target name="init">
<property location="build" name="classes.dir"/>
<property location="src" name="src.dir"/>
<property location="doc/q/api" name="javadoc.dir"/>
<property name="project.name" value="${ant.project.name}"/>
<property location="${project.name}.jar" name="jar"/>
</target>
<target depends="init" name="compile">
<!-- Both srcdir and destdir should be package roots. -->
<mkdir dir="${classes.dir}"/>
<javac debug="true" deprecation="true" destdir="${classes.dir}" srcdir="${src.dir}">
<!-- To add something to the classpath: -->
<!-- <classpath><pathelement location="${mylib}"/></classpath> -->
<!-- To exclude some files: -->
<!-- <exclude name="com/foo/SomeFile.java"/><exclude name="com/foo/somepackage/"/> -->
</javac>
</target>
<target depends="init,compile" name="jar">
<!-- To make a standalone app, insert into <jar>: -->
<!-- <manifest><attribute name="Main-Class" value="com.foo.Main"/></manifest> -->
<!-- <jar basedir="${classes.dir}" compress="true" jarfile="${jar}"> -->
<jar compress="true" jarfile="${jar}">
<!-- <jar basedir="." compress="true" jarfile="${jar}" includes="**/*.class,doc/**/*.html"> -->
<fileset dir="${classes.dir}"/>
<fileset dir="." includes="qresources/**"/>
<manifest>
<attribute name="Main-Class" value="net.i2p.aum.q.QMgr"/>
<attribute name="Class-Path" value="i2p.jar xmlrpc.jar mstreaming.jar streaming.jar jbigi.jar"/>
</manifest>
</jar>
</target>
<target depends="init,jar" description="Build everything." name="all"/>
<target depends="init" description="Javadoc for my API." name="javadoc">
<mkdir dir="${javadoc.dir}"/>
<javadoc destdir="${javadoc.dir}" packagenames="*">
<sourcepath>
<pathelement location="${src.dir}"/>
</sourcepath>
<sourcepath>
<pathelement location="/java/xmlrpc-1.2-b1/src/java"/>
</sourcepath>
</javadoc>
</target>
<target depends="init" description="Clean all build products." name="clean">
<delete dir="${classes.dir}"/>
<delete dir="${javadoc.dir}"/>
<delete file="${jar}"/>
</target>
</project>
This diff is collapsed.
/*
* HTML.Template: A module for using HTML Templates with java
*
* Copyright (c) 2002 Philip S Tellis (philip.tellis@iname.com)
*
* This module is free software; you can redistribute it
* and/or modify it under the terms of either:
*
* a) the GNU General Public License as published by the Free
* Software Foundation; either version 1, or (at your option)
* any later version, or
*
* b) the "Artistic License" which comes with this module.
*
* 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. See either the GNU General Public License or the
* Artistic License for more details.
*
* You should have received a copy of the Artistic License
* with this module, in the file ARTISTIC. If not, I'll be
* glad to provide one.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA
*
* Modified by David McNab (david@rebirthing.co.nz) to allow nesting of
* templates (ie, passing a child Template object as a value argument
* to a .setParam() invocation on a parent Template object).
*
*/
package HTML.Tmpl.Element;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import HTML.*;
public class Conditional extends Element
{
private boolean control_val = false;
private Vector [] data;
public Conditional(String type, String name)
throws IllegalArgumentException
{
if(type.equalsIgnoreCase("if"))
this.type="if";
else if(type.equalsIgnoreCase("unless"))
this.type="unless";
else
throw new IllegalArgumentException(
"Unrecognised type: " + type);
this.name = name;
this.data = new Vector[2];
this.data[0] = new Vector();
}
public void addBranch() throws IndexOutOfBoundsException
{
if(data[1] != null)
throw new IndexOutOfBoundsException("Already have two branches");
if(data[0] == null)
data[0] = new Vector();
else if(data[1] == null)
data[1] = new Vector();
}
public void add(String text)
{
if(data[1] != null)
data[1].addElement(text);
else
data[0].addElement(text);
}
public void add(Element node)
{
if(data[1] != null)
data[1].addElement(node);
else
data[0].addElement(node);
}
public void setControlValue(Object control_val)
throws IllegalArgumentException
{
this.control_val = process_var(control_val);
}
public String parse(Hashtable params)
{
if(!params.containsKey(this.name))
this.control_val = false;
else
setControlValue(params.get(this.name));
StringBuffer output = new StringBuffer();
Enumeration de;
if(type.equals("if") && control_val ||
type.equals("unless") && !control_val)
de = data[0].elements();
else if(data[1] != null)
de = data[1].elements();
else
return "";
while(de.hasMoreElements()) {
Object e = de.nextElement();
String eType = e.getClass().getName();
if(eType.endsWith(".String"))
output.append((String)e);
else if (eType.endsWith(".Template"))
output.append(((Template)e).output());
else
output.append(((Element)e).parse(params));
}
return output.toString();
}
public String typeOfParam(String param)
throws NoSuchElementException
{
for(int i=0; i<data.length; i++)
{
if(data[i] == null)
continue;
for(Enumeration e = data[i].elements();
e.hasMoreElements();)
{
Object o = e.nextElement();
if(o.getClass().getName().endsWith(".String"))
continue;
if(((Element)o).Name().equals(param))
return ((Element)o).Type();
}
}
throw new NoSuchElementException(param);
}
private boolean process_var(Object control_val)
throws IllegalArgumentException
{
String control_class = "";
if(control_val == null)
return false;
control_class=control_val.getClass().getName();
if(control_class.indexOf(".") > 0)
control_class = control_class.substring(
control_class.lastIndexOf(".")+1);
if(control_class.equals("String")) {
return !(((String)control_val).equals("") ||
((String)control_val).equals("0"));
} else if(control_class.equals("Vector")) {
return !((Vector)control_val).isEmpty();
} else if(control_class.equals("Boolean")) {
return ((Boolean)control_val).booleanValue();
} else if(control_class.equals("Integer")) {
return (((Integer)control_val).intValue() != 0);
} else {
throw new IllegalArgumentException("Unrecognised type");
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment