chg: replaced ant with gradle

This commit is contained in:
Tobi Schäfer 2020-03-16 16:53:52 +01:00
parent ced560f0c7
commit 7eebeee1d0
615 changed files with 87626 additions and 638 deletions

View file

@ -0,0 +1 @@
Jala is a <a href="http://helma.org">Helma</a>-based library and utility project initially developed to ease the work at <a href="http://orf.at">ORF.at</a>'s software development department.

View file

@ -0,0 +1,175 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Fields and methods of the jala.AsyncRequest class.
*/
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
/**
* Creates a new AsyncRequest instance.
* @class This class is used to create requests of type "INTERNAL"
* (like cron-jobs) that are processed in a separate thread and
* therefor asynchronous.
* @param {Object} obj Object in whose context the method should be called
* @param {String} funcName Name of the function to call
* @param {Array} args Array containing the arguments that should be passed
* to the function (optional). This option is <em>deprecated</em>, instead
* pass the arguments directly to the {@link #run} method.
* @constructor
* @returns A new instance of AsyncRequest
* @type AsyncRequest
* @deprecated Use the {@link http://helma.zumbrunn.net/reference/core/app.html#invokeAsync
* app.invokeAsync} method instead (built-in into Helma as
* of version 1.6)
*/
jala.AsyncRequest = function(obj, funcName, args) {
app.logger.warn("Use of jala.AsyncRequest is deprecated in this version.");
app.logger.warn("This module will probably be removed in a " +
"future version of Jala.");
/**
* Contains a reference to the thread started by this AsyncRequest
* @type java.lang.Thread
* @private
*/
var thread;
/**
* Contains the timeout defined for this AsyncRequest (in milliseconds)
* @type Number
* @private
*/
var timeout;
/**
* Contains the number of milliseconds to wait before starting
* the asynchronous request.
* @type Number
* @private
*/
var delay;
/**
* Run method necessary to implement java.lang.Runnable.
* @private
*/
var runner = function() {
// evaluator that will handle the request
var ev = app.__app__.getEvaluator();
if (delay != null) {
java.lang.Thread.sleep(delay);
}
try {
if (args === undefined || args === null || args.constructor != Array) {
args = [];
}
if (timeout != null) {
ev.invokeInternal(obj, funcName, args, timeout);
} else {
ev.invokeInternal(obj, funcName, args);
}
} catch (e) {
// ignore it, but log it
app.log("[Runner] Caught Exception: " + e);
} finally {
// release the ev in any case
app.__app__.releaseEvaluator(ev);
// remove reference to underlying thread
thread = null;
}
return;
};
/**
* Sets the timeout of this asynchronous request.
* @param {Number} seconds Thread-timeout.
*/
this.setTimeout = function(seconds) {
timeout = seconds * 1000;
return;
};
/**
* Defines the delay to wait before evaluating this asynchronous request.
* @param {Number} millis Milliseconds to wait
*/
this.setDelay = function(millis) {
delay = millis;
return;
};
/**
* Starts this asynchronous request. Any arguments passed to
* this method will be passed to the method executed by
* this AsyncRequest instance.
*/
this.run = function() {
if (arguments.length > 0) {
// convert arguments object into array
args = Array.prototype.slice.call(arguments, 0, arguments.length);
}
thread = (new java.lang.Thread(new java.lang.Runnable({"run": runner})));
thread.start();
return;
};
/**
* Starts this asynchronous request.
* @deprecated Use {@link #run} instead
*/
this.evaluate = function() {
this.run.apply(this, arguments);
return;
};
/**
* Returns true if the underlying thread is alive
* @returns True if the underlying thread is alive,
* false otherwise.
* @type Boolean
*/
this.isAlive = function() {
return thread != null && thread.isAlive();
}
/** @ignore */
this.toString = function() {
return "[jala.AsyncRequest]";
};
/**
* Main constructor body
*/
if (!obj || !funcName)
throw "jala.AsyncRequest: insufficient arguments.";
return this;
}

View file

@ -0,0 +1,429 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Fields and methods of the jala.BitTorrent class.
*/
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
/**
* Module dependencies
*/
app.addRepository("modules/core/String.js");
app.addRepository("modules/helma/File.js");
/**
* Constructs a new BitTorrent file.
* @class This class provides methods to create a BitTorrent
* metadata file from any desired file.
* @param {String} trackerUrl The URL string of the tracker.
* @param {String} filePath The path to the original file.
* @returns A new BitTorrent file.
* @constructor
*/
jala.BitTorrent = function(filePath, trackerUrl) {
var self = this;
self.arguments = arguments;
// FIXME: Add support for multitracker mode as specified in
// http://www.bittornado.com/docs/multitracker-spec.txt
var torrent, sourceFile, torrentFile;
var pieceLength = 256;
var updateTorrent = function() {
if (torrent.info) {
return torrent;
}
var file = new java.io.File(filePath);
if (!file.exists()) {
throw Error("File " + file + " does not exist!");
}
var md5 = java.security.MessageDigest.getInstance("MD5");
var sha1 = java.security.MessageDigest.getInstance("SHA-1");
var fis = new java.io.FileInputStream(file);
var bis = new java.io.BufferedInputStream(fis);
var cache = new java.io.ByteArrayOutputStream();
var pieces = [];
var length = pieceLength * 1024;
var buffer = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, length);
while (bis.read(buffer, 0, buffer.length) > -1) {
app.debug("Updating SHA-1 hash with " + buffer.length + " bytes");
sha1.reset();
sha1["update(byte[])"](buffer);
cache["write(byte[])"](buffer);
pieces.push(new java.lang.String(sha1.digest()));
}
bis.close();
fis.close();
torrent.info = {
//md5sum: new java.lang.String(md5.digest(cache.toByteArray())),
length: cache.size(),
name: file.getName(),
"piece length": length,
pieces: pieces.join("")
};
return torrent;
};
/**
* Get all available property names.
* @returns The list of property names.
* @type Array
*/
this.keys = function() {
var keys = [];
for (var i in torrent) {
keys.push(i);
}
keys.sort();
return keys;
};
/**
* Get a torrent property.
* @param {String} name The name of the property.
* @returns The value of the property.
*/
this.get = function(name) {
return torrent[name];
};
/**
* Set a torrent property.
* @param {String} name The name of the property.
* @param {Object} value The property's value.
*/
this.set = function(name, value) {
if (typeof torrent[name] == "undefined") {
throw Error("Cannot set torrent property " + name);
}
torrent[name] = value;
delete torrent.info;
return;
};
/**
* Get the creation date of the torrent.
* @returns The torrent's creation date.
* @type Date
*/
this.getCreationDate = function() {
return new Date(torrent["creation date"] * 1000);
};
/**
* Set the creation date of the torrent.
* @param {Date} date The desired creation date.
*/
this.setCreationDate = function(date) {
this.set("creation date", Math.round((date || new Date()).getTime() / 1000));
return;
};
/**
* Get the piece length of the torrent.
* @returns The torrent's piece length.
* @type Number
*/
this.getPieceLength = function() {
return pieceLength;
};
/**
* Set the piece length of the torrent.
* @param {Number} length The desired piece length.
*/
this.setPieceLength = function(length) {
pieceLength = length;
delete torrent.info;
return;
};
/**
* Returns the underlying torrent file.
* @returns The torrent file.
* @type helma.File
*/
this.getTorrentFile = function() {
return torrentFile;
};
/**
* Returns the underlying source file.
* @returns The source file.
* @type helma.File
*/
this.getSourceFile = function() {
return sourceFile;
};
/**
* Saves the torrent as file.
* @param {String} filename An optional name for the torrent file.
* If no name is given it will be composed from name of source
* file as defined in the torrent plus the ending ".torrent".
*/
this.save = function(filename) {
updateTorrent();
if (!filename) {
filename = torrent.info.name + ".torrent";
}
torrentFile = new helma.File(sourceFile.getParent(), filename);
torrentFile.remove();
torrentFile.open();
torrentFile.write(jala.BitTorrent.bencode(torrent));
torrentFile.close();
return;
};
/**
* Get a string representation of the torrent.
* @returns The torrent as string.
* @type String
*/
this.toString = function() {
return "[jala.BitTorrent " + filePath + "]";
};
if (String(filePath).endsWith(".torrent")) {
torrentFile = new helma.File(filePath);
torrent = jala.BitTorrent.bdecode(torrentFile.readAll());
sourceFile = new helma.File(torrent.info.name);
} else {
torrent = {
announce: trackerUrl || null,
"announce-list": null,
"creation date": null,
comment: null,
"created by": null,
};
this.setCreationDate();
sourceFile = new helma.File(filePath);
}
return this;
};
/**
* The bencode method. Turns an arbitrary JavaScript
* object structure into a corresponding encoded
* string.
* @param {Object} obj The target JavaScript object.
* @returns The encoded string.
* @type String
*/
jala.BitTorrent.bencode = function(obj) {
var bencode = arguments.callee;
var str = obj.toString();
res.push();
switch (obj.constructor) {
case Array:
res.write("l");
for (var i in obj) {
if (obj[i])
res.write(bencode(obj[i]));
}
res.write("e");
break;
case Number:
res.write("i" + str + "e");
break;
case Object:
res.write("d");
var keys = [];
for (var i in obj) {
keys.push(i);
}
keys.sort();
var key;
for (var i in keys) {
key = keys[i];
if (obj[key]) {
res.write(bencode(key));
res.write(bencode(obj[key]));
}
}
res.write("e");
break;
default:
res.write(str.length + ":" + str);
}
return res.pop();
};
/**
* The bdecode method. Turns an encoded string into
* a corresponding JavaScript object structure.
* FIXME: Handle with caution...
* @param {String} code The encoded string.
* @returns The decoded JavaScript structure.
* @type Object
*/
jala.BitTorrent.bdecode = function(code) {
var DICTIONARY = "d";
var LIST = "l";
var INTEGER = "i";
var STRING = "s";
var END = "e";
var stack = [];
var overflowCounter = 0;
var position = -1, current;
function getResult() {
update();
var result;
switch (current) {
case DICTIONARY:
result = bdecodeDictionary();
break;
case LIST:
result = bdecodeList();
break;
case INTEGER:
result = bdecodeInteger();
break;
case END:
case null:
//res.debug("*** end detected in getResult()");
result = null;
break;
default:
result = bdecodeString();
}
return result;
}
function update() {
position += 1;
current = code.charAt(position);
/* res.debug("stack: " + stack);
res.debug("position: " + position);
res.debug("current: " + current);
res.debug("remains: " + code.substr(position)); */
return;
}
function overflow() {
if (overflowCounter++ > 100)
throw Error("Error parsing bdecoded string");
return false;
}
function bdecodeDictionary() {
stack.push(DICTIONARY);
var dictionary = {}, key, value;
while (current && !overflow()) {
key = getResult();
if (key === null)
break;
value = getResult();
if (key && value)
dictionary[key] = value;
else
break;
}
stack.pop();
return dictionary;
}
function bdecodeList() {
stack.push(LIST);
var list = [], value;
while (current && !overflow()) {
var value = getResult();
if (value)
list.push(value);
else
break;
}
stack.pop();
return list;
}
function bdecodeInteger() {
var integer = "";
stack.push(integer);
while (current && !overflow()) {
update();
if (current == "e")
break;
integer += current;
}
if (isNaN(integer))
throw("Error in bdecoded integer: " + integer + " is not a number");
//res.debug("integer = " + integer);
stack.pop();
return parseInt(integer);
}
function bdecodeString() {
var length = current, string = "";
stack.push(string);
update();
while (current && current != ":" && !overflow()) {
length += current;
update();
}
if (isNaN(length))
throw("Error in bdecoded string: invalid length " + length);
//res.debug("length = " + length);
length = parseInt(length);
if (length > code.length - position)
throw Error("Error parsing bdecoded string");
for (var i=0; i<length; i+=1) {
update();
string += current;
}
//res.debug("string = " + string);
if (string == "creation date")
void(null);
stack.pop();
return string;
}
return getResult();
};

View file

@ -0,0 +1,119 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Fields and methods of the jala.Captcha class.
*/
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
/**
* Construct a new captcha.
* @returns A new captcha.
* @class Wrapper class for the
* {@link http://jcaptcha.sourceforge.net/ JCaptcha library}.
* A captcha (an acronym for "completely automated public
* Turing test to tell computers and humans apart") is a
* type of challenge-response test used in computing to
* determine whether or not the user is human.
* @constructor
*/
jala.Captcha = function() {
/**
* Jala dependencies
*/
app.addRepository(getProperty("jala.dir", "modules/jala") +
"/lib/jcaptcha-all-1.0-RC3.jar");
var gimpy;
try {
var ref = Packages.com.octo.captcha.engine.image.gimpy;
gimpy = ref.DefaultGimpyEngine();
} catch(e) {
throw("Cannot instantiate object due to missing java class: " +
arguments.callee.toString());
}
var captcha = gimpy.getNextCaptcha();
/**
* Get a new captcha object.
* @returns A new captcha object.
* @type com.octo.captcha.Captcha
*/
this.getCaptcha = function getCaptcha() {
return captcha;
};
/**
* Render a new captcha image.
*/
this.renderImage = function renderImage() {
var image = captcha.getImageChallenge();
var stream = new java.io.ByteArrayOutputStream();
var ref = Packages.com.sun.image.codec.jpeg.JPEGCodec;
var encoder = ref.createJPEGEncoder(stream);
encoder.encode(image);
res.contentType = "image/jpeg";
res.writeBinary(stream.toByteArray());
return;
};
/**
* Validate a user's input with the prompted captcha.
* @param {String} input The user's input.
* @returns True if the user's input matches the captcha.
* @type Boolean
*/
this.validate = function validate(input) {
return !input || captcha.validateResponse(input);
};
return this;
};
/**
* Get a string representation of the captcha class.
* @returns A string representation of the capthca class.
* @type String
* @ignore
*/
jala.Captcha.toString = function toString() {
return "[jala.Captcha http://jcaptcha.sourceforge.net]";
};
/**
* Get a string representation of the captcha object.
* @returns A string representation of the captcha object.
* @type String
*/
jala.Captcha.prototype.toString = function toString() {
return "[jala.Captcha Object]";
};

File diff suppressed because it is too large Load diff

545
modules/jala/code/Date.js Normal file
View file

@ -0,0 +1,545 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Fields and methods of the jala.Date class.
*/
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
/**
* HelmaLib dependencies
*/
app.addRepository("modules/core/Date.js");
app.addRepository("modules/helma/Html.js");
/**
* Constructs a new Renderings object.
* @class This class provides various convenience
* methods for rendering purposes.
* @constructor
*/
jala.Date = function() {
return this;
};
/**
* Renders a timestamp as set of DropDown boxes, following the
* format passed as argument. Every &lt;select&gt;
* item is prefixed with a string so that it can be retrieved
* easily from the values of a submitted POST request.
* @param {String} prefix The prefix to use for all dropdown boxes, eg. "postdate"
* @param {Date} date A Date object to use as preselection (optional)
* @param {Object} fmt Array containing one parameter object for every single
* select box that should be rendered, with the following properties set:
* <ul>
* <li>pattern - The date format pattern that should be rendered. Valid
* patterns are: "dd", "MM", "yyyy", "HH", "ss".</li>
* <li>firstOption - The string to use as first option, eg.: "choose a day"</li>
* </ul>
*/
jala.Date.prototype.renderEditor = function(prefix, date, fmt) {
/**
* rendering method
* @private
*/
var render = function(param, date) {
switch (param.pattern) {
case "dd":
param.offset = 1;
param.max = 31;
param.selected = (date ? date.getDate() : null);
break;
case "MM":
param.offset = 1;
param.max = 12;
param.selected = (date ? date.getMonth() +1 : null);
break;
case "yyyy":
param.offset = 2002;
param.max = 20;
param.selected = (date ? date.getFullYear() : null);
break;
case "HH":
param.offset = 0;
param.max = 24;
param.selected = (date ? date.getHours() : null);
break;
case "mm":
param.offset = 0;
param.max = 60;
param.selected = (date ? date.getMinutes() : null);
break;
case "ss":
param.offset = 0;
param.max = 60;
param.selected = (date ? date.getSeconds() : null);
break;
}
var key = prefix + ":" + param.pattern;
if (req.data[key])
param.selected = req.data[key];
var options = [];
var opt;
for (var i=0;i<param.max;i++) {
opt = (param.offset + i).format("00");
options[i] = [opt, opt];
}
var html = new helma.Html();
html.dropDown({name: key}, options, param.selected, param.firstOption);
}
if (!fmt)
var fmt = [{pattern: "dd", firstOption: "day"},
{pattern: "MM", firstOption: "month"},
{pattern: "yyyy", firstOption: "year"},
{pattern: "HH", firstOption: "hour"},
{pattern: "mm", firstOption: "minute"}];
for (var i in fmt) {
render(fmt[i], date);
}
return;
};
/**
* Returns a timestamp as set of dropdown-boxes
* @see #renderEditor
* @type String
*/
jala.Date.prototype.renderEditorAsString = function(prefix, date, pattern) {
res.push();
this.renderEditor(prefix, date, pattern);
return res.pop();
};
/**
* Creates a new instance of jala.Data.Calendar
* @class This class represents a calendar based based on a grouped
* collection of HopObjects. It provides several methods for rendering
* the calendar plus defining locale and timezone settings.
* @param {HopObject} collection A grouped HopObject collection to work on
* @returns A newly created jala.Date.Calendar instance
* @constructor
*/
jala.Date.Calendar = function(collection) {
var renderer = null;
var locale = java.util.Locale.getDefault();
var timezone = java.util.TimeZone.getDefault();
var hrefFormat = "yyyyMMdd";
var accessNameFormat = "yyyyMMdd";
/**
* Returns the collection this calendar object works on
* @returns The HopObject collection of this calendar
* @type HopObject
*/
this.getCollection = function() {
return collection;
};
/**
* Sets the renderer to use.
* @param {Object} r The renderer to use
* @see #getRenderer
*/
this.setRenderer = function(r) {
renderer = r;
return;
};
/**
* Returns the renderer used by this calendar.
* @returns The calendar renderer
* @type Object
* @see #setRenderer
*/
this.getRenderer = function() {
if (!renderer) {
renderer = new jala.Date.Calendar.Renderer(this);
}
return renderer;
};
/**
* Sets the locale to use within this calendar object
* @param {java.util.Locale} loc The locale to use
* @see #getLocale
*/
this.setLocale = function(loc) {
locale = loc;
return;
};
/**
* Returns the locale used within this calendar instance. By default
* the locale used by this calendar is the default locale of the
* Java Virtual Machine running Helma.
* @returns The locale of this calendar
* @type java.util.Locale
* @see #setLocale
*/
this.getLocale = function() {
return locale;
};
/**
* Sets the locale to use within this calendar object
* @param {java.util.Locale} loc The locale to use
* @see #getTimeZone
*/
this.setTimeZone = function(tz) {
timezone = tz;
return;
};
/**
* Returns the locale used within this calendar instance. By default
* the timezone used by this calendar is the default timezone
* of the Java Virtual Machine running Helma.
* @returns The locale of this calendar
* @type java.util.Locale
* @see #setTimeZone
*/
this.getTimeZone = function() {
return timezone;
};
/**
* Sets the format of the hrefs to render by this calendar
* to the format pattern passed as argument.
* @param {String} fmt The date format pattern to use for
* rendering the href
* @see #getHrefFormat
*/
this.setHrefFormat = function(fmt) {
hrefFormat = fmt;
return;
};
/**
* Returns the date formatting pattern used to render hrefs. The default
* format is "yyyyMMdd".
* @returns The date formatting pattern
* @type String
* @see #setHrefFormat
*/
this.getHrefFormat = function() {
return hrefFormat;
};
/**
* Sets the format of the group name to use when trying to access
* child objects of the collection this calendar is operating on.
* @param {String} fmt The date format pattern to use for
* accessing child objects
* @see #getAccessNameFormat
*/
this.setAccessNameFormat = function(fmt) {
accessNameFormat = fmt;
return;
};
/**
* Returns the format of the access name used by this calendar to access
* child group objects of the collection this calendar is operating on.
* The default format is "yyyyMMdd".
* @returns The date formatting pattern used to access child objects
* @type String
* @see #setAccessNameFormat
*/
this.getAccessNameFormat = function() {
return accessNameFormat;
};
return this;
};
/** @ignore */
jala.Date.Calendar.prototype.toString = function() {
return "[Jala Calendar]";
};
/**
* Renders the calendar using either a custom renderer defined
* using {@link #setRenderer} or the default one.
* @see #setRenderer
* @see jala.Date.Calendar.Renderer
*/
jala.Date.Calendar.prototype.render = function(today) {
var renderer = this.getRenderer();
var collection = this.getCollection();
var hrefFormat = this.getHrefFormat();
var accessNameFormat = this.getAccessNameFormat();
var locale = this.getLocale();
var timezone = this.getTimeZone();
var size = collection.size();
if (size == null)
return;
/**
* private method that creates a date object set
* to the last date of the previous month or the
* first date of the next month (if available)
*/
var prevNextMonth = function(which, dayIndex) {
var obj;
if (which == "prev") {
if (size <= dayIndex || !(obj = collection.get(dayIndex +1)))
return;
} else if (which == "next") {
if (dayIndex == 0 || !(obj = collection.get(dayIndex - 1)))
return;
} else {
return;
}
return new Date(obj.groupname.substring(0, 4),
obj.groupname.substring(4, 6) -1,
obj.groupname.substring(6));
};
// create the calendar object used for date calculations
var cal = java.util.Calendar.getInstance(timezone, locale);
var firstDayOfWeek = cal.getFirstDayOfWeek();
var symbols = new java.text.DateFormatSymbols(locale);
res.push();
// render the header-row
res.push();
var weekdays = symbols.getShortWeekdays();
for (var i=0;i<7;i++) {
renderer.renderDayHeader(weekdays[(i+firstDayOfWeek-1)%7+1]);
}
renderer.renderRow(res.pop());
cal.set(java.util.Calendar.DATE, 1);
// check whether there's a day in path
// if so, use it to determine the month to render
if (today) {
cal.set(java.util.Calendar.YEAR, today.getFullYear());
cal.set(java.util.Calendar.MONTH, today.getMonth());
}
// nr. of empty days in rendered calendar before the first day of month appears
var pre = (7-firstDayOfWeek+cal.get(java.util.Calendar.DAY_OF_WEEK)) % 7;
var days = cal.getActualMaximum(java.util.Calendar.DATE);
var weeks = Math.ceil((pre + days) / 7);
var daycnt = 1;
var date = new Date(cal.get(java.util.Calendar.YEAR), cal.get(java.util.Calendar.MONTH), 1);
// remember the index of the first and last days within this month.
// this is needed to optimize previous and next month links.
var lastDayIndex = Number.MAX_VALUE;
var firstDayIndex = -1;
var dayObj, idx, selected;
for (var i=0;i<weeks;i++) {
res.push();
for (var j=0;j<7;j++) {
if ((i == 0 && j < pre) || daycnt > days) {
renderer.renderDay(null);
} else {
date.setDate(daycnt);
if ((dayObj = collection.get(date.format(accessNameFormat))) != null) {
idx = collection.contains(dayObj);
if (idx > -1) {
if (idx > firstDayIndex) {
firstDayIndex = idx;
}
if (idx < lastDayIndex) {
lastDayIndex = idx;
}
}
}
selected = (today != null) ? date.equals(today) : false;
renderer.renderDay(date, dayObj != null, selected);
daycnt++;
}
}
renderer.renderRow(res.pop());
}
var prevMonth = prevNextMonth("prev", firstDayIndex) || null;
var nextMonth = prevNextMonth("next", lastDayIndex) || null;
renderer.renderCalendar(date, res.pop(), prevMonth, nextMonth);
return;
};
/**
* Returns a rendered calendar
* @see #renderCalendar
* @type String
*/
jala.Date.Calendar.prototype.getCalendar = function(today) {
res.push();
this.render(today);
return res.pop();
};
/**
* Returns a new instance of the default calendar renderer.
* @class A default renderer to use in conjunction with jala.Date.Calendar
* @param {jala.Date.Calendar} calendar The calendar utilizing this renderer
* @returns A newly created instance of jala.Date.Calendar.Renderer
* @constructor
*/
jala.Date.Calendar.Renderer = function(calendar) {
/**
* An instance of helma.Html used for rendering the calendar
* @type helma.Html
*/
this.html = new helma.Html();
/**
* The calendar utilizing this renderer instance
* @type jala.Date.Calendar
*/
this.calendar = calendar;
return this;
};
/** @ignore */
jala.Date.Calendar.Renderer.prototype.toString = function() {
return "[Jala Calendar Default Renderer]";
};
/**
* Renders a single cell in the calendar day header row directly to response.
* @param {String} text The text to display in the header field.
*/
jala.Date.Calendar.Renderer.prototype.renderDayHeader = function(text) {
this.html.element("th", text);
return;
};
/**
* Renders a single calendar row directly to response.
* @param {String} row The body of the calendar row.
*/
jala.Date.Calendar.Renderer.prototype.renderRow = function(row) {
this.html.element("tr", row);
return;
};
/**
* Renders a single day within the calendar directly to response.
* @param {Date} date A date instance representing the day within the calendar.
* @param {Boolean} isExisting True if there is a child object in the calendar's
* collection to which the date cell should link to
* @param {Boolean} isSelected True if this calendar day should be rendered
* as selected day.
*/
jala.Date.Calendar.Renderer.prototype.renderDay = function(date, isExisting, isSelected) {
var attr = {"class": "jala-calendar-day day"};
if (isSelected === true) {
attr["class"] += " jala-calendar-selected selected";
}
this.html.openTag("td", attr);
if (date != null) {
var text = date.getDate();
if (isExisting === true) {
attr = {"href": this.calendar.getCollection().href() +
date.format(this.calendar.getHrefFormat())};
this.html.link(attr, text);
} else {
res.write(text);
}
}
this.html.closeTag("td");
return;
};
/**
* Renders a link to the previous or next month's calendar directly to response.
* @param {Date} date A date object set to the previous or next available
* month. This can be null in case there is no previous or next month.
*/
jala.Date.Calendar.Renderer.prototype.renderPrevNextLink = function(date) {
if (date != null) {
var attr = {"href": this.calendar.getCollection().href() +
date.format(this.calendar.getHrefFormat())};
this.html.link(attr, date.format("MMMM", this.calendar.getLocale()));
}
return;
};
/**
* Renders the calendar directly to response.
* @param {Date} date A date object representing this calendar's month and year.
* Please mind that the day will be set to the <em>last</em> date in this
* month.
* @param {String} body The rendered calendar weeks including the day header
* (basically the whole kernel of the table).
* @param {Date} prevMonth A date object set to the last available date of
* the previous month. This can be used to render a navigation link to
* the previous month.
* @param {Date} nextMonth A date object set to the first available date
* of the next month. This can be used to render a navigation link to
* the next month.
*/
jala.Date.Calendar.Renderer.prototype.renderCalendar = function(date, body, prevMonth, nextMonth) {
var locale = this.calendar.getLocale();
this.html.openTag("table", {"class": "jala-calendar calendar"});
this.html.openTag("thead");
this.html.openTag("tr");
this.html.openTag("th", {"colspan": 7});
res.write(date.format("MMMM", locale));
res.write(' ');
res.write(date.format("yyyy", locale));
this.html.closeTag("th");
this.html.closeTag("tr");
this.html.closeTag("thead");
this.html.element("tbody", body);
this.html.openTag("tfoot");
this.html.openTag("tr");
this.html.openTag("td", {"class": "jala-calendar-left left", "colspan": 3});
this.renderPrevNextLink(prevMonth);
this.html.closeTag("td");
this.html.openTag("td");
this.html.closeTag("td");
this.html.openTag("td", {"class": "jala-calendar-right right", "colspan": 3});
this.renderPrevNextLink(nextMonth);
this.html.closeTag("td");
this.html.closeTag("tr");
this.html.closeTag("tfoot");
this.html.closeTag("table");
return;
};
/**
* Default date class instance.
* @type jala.Date
* @final
*/
jala.date = new jala.Date();

View file

@ -0,0 +1,312 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Fields and methods of the jala.DnsClient class.
*/
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
/**
* Jala dependencies
*/
app.addRepository(getProperty("jala.dir", "modules/jala") +
"/lib/javadns.jar");
/**
* Constructs a new DnsClient object.
* @class This is a wrapper around the Dns Client by wonderly.org
* providing methods for querying Dns servers. For more information
* about the Java DNS client visit
* <a href="https://javadns.dev.java.net/">https://javadns.dev.java.net/</a>.
* Please mind that the nameserver specified must accept queries on port
* 53 TCP (the Java DNS client used doesn't support UDP nameserver queries),
* and that reverse lookups are not supported.
* @param {String} nameServer IP-Address or FQDN of nameserver to query
* @constructor
*/
jala.DnsClient = function(nameServer) {
/**
* Contains the IP Adress/FQDN of the name server to query.
* @type String
*/
this.nameServer = nameServer;
if (!this.nameServer) {
throw "jala.DnsClient: missing nameserver argument";
} else {
// test if required javadns library is available
try {
var clazz = java.lang.Class.forName("org.wonderly.net.dns.Query",
false, app.getClassLoader())
} catch (e) {
throw "jala.DnsClient requires JavaDNS.jar"
+ " in lib/ext or application directory "
+ "[https://javadns.dev.java.net/]";
}
}
return this;
};
/** @ignore */
jala.DnsClient.PKG = Packages.org.wonderly.net.dns;
/**
* The "A" record/query type.
* @type Number
* @final
*/
jala.DnsClient.TYPE_A = jala.DnsClient.PKG.Question.TYPE_A;
/**
* The "CNAME" record/query type.
* @type Number
* @final
*/
jala.DnsClient.TYPE_CNAME = jala.DnsClient.PKG.Question.TYPE_CNAME;
/**
* The "MX" record/query type.
* @type Number
* @final
*/
jala.DnsClient.TYPE_MX = jala.DnsClient.PKG.Question.TYPE_MX;
/**
* The "NS" record/query type.
* @type Number
* @final
*/
jala.DnsClient.TYPE_NS = jala.DnsClient.PKG.Question.TYPE_NS;
/**
* The "PTR" record/query type.
* @type Number
* @final
*/
jala.DnsClient.TYPE_PTR = jala.DnsClient.PKG.Question.TYPE_PTR;
/**
* The "SOA" record/query type.
* @type Number
* @final
*/
jala.DnsClient.TYPE_SOA = jala.DnsClient.PKG.Question.TYPE_SOA;
/**
* The "TXT" record/query type.
* @type Number
* @final
*/
jala.DnsClient.TYPE_TXT = jala.DnsClient.PKG.Question.TYPE_TXT;
/**
* The "WKS" record/query type.
* @type Number
* @final
*/
jala.DnsClient.TYPE_WKS = jala.DnsClient.PKG.Question.TYPE_WKS;
/**
* Queries the nameserver for a specific domain
* and the given type of record.
* @param {String} dName The domain name to query for
* @param {Number} queryType The type of records to retrieve
* @returns The records retrieved from the nameserver
* @type org.wonderly.net.dns.RR
*/
jala.DnsClient.prototype.query = function(dName, queryType) {
if (dName == null) {
throw new Error("no domain-name to query for");
}
if (queryType == null) {
queryType = jala.DnsClient.TYPE_A;
}
// construct the question for querying the nameserver
var question = new jala.DnsClient.PKG.Question(dName,
queryType,
jala.DnsClient.PKG.Question.CLASS_IN);
// construct the query
var query = new jala.DnsClient.PKG.Query(question);
// run the query
query.runQuery(this.nameServer);
// wrap the records received in instances of jala.DnsClient.Record
var answers = query.getAnswers();
var arr = [];
for (var i=0;i<answers.length;i++) {
arr[i] = new jala.DnsClient.Record(answers[i]);
}
return arr;
};
/**
* Convenience method to query for the MX-records
* of the domain passed as argument.
* @param {String} dName The domain name to query for
* @returns The records retrieved from the nameserver
* @type org.wonderly.net.dns.RR
*/
jala.DnsClient.prototype.queryMailHost = function (dName) {
return this.query(dName, this.TYPE_MX);
};
/** @ignore */
jala.DnsClient.toString = function() {
return "[jala.DnsClient]";
};
/** @ignore */
jala.DnsClient.prototype.toString = function() {
return "[jala.DnsClient (" + this.nameServer + ")]";
};
/**
* Constructs a new instance of jala.DnsClient.Record.
* @class Instances of this class wrap record data as received
* from the nameserver.
* @param {org.wonderly.net.dns.RR} data The data as received from
* the nameserver
* @returns A newly constructed Record instance
* @constructor
*/
jala.DnsClient.Record = function(data) {
/**
* The type of the nameserver record represented by this Answer instance.
* @type Number
* @see #TYPE_A
* @see #TYPE_CNAME
* @see #TYPE_HINFO
* @see #TYPE_MX
* @see #TYPE_NS
* @see #TYPE_PTR
* @see #TYPE_SOA
* @see #TYPE_TXT
* @see #TYPE_WKS
*/
this.type = data.getType();
/**
* The name of the host. This will only be set for records
* of type A, AAAA and NS.
* @type String
* @see #TYPE_A
* @see #TYPE_AAAA
* @see #TYPE_NS
*/
this.host = null;
/**
* The IP address of the host. This will only be set for records
* of type A and AAAA
* @type String
* @see #TYPE_A
* @see #TYPE_AAAA
*/
this.ipAddress = null;
/**
* The CNAME of this record. This will only be set for records
* of type CNAME
* @type String
* @see #TYPE_CNAME
*/
this.cname = null;
/**
* The name of the mail exchanging server. This is only set for
* records of type MX
* @type String
* @see #TYPE_MX
*/
this.mx = null;
/**
* The email address responsible for a name server. This property
* will only be set for records of type SOA
* @type String
* @see #TYPE_SOA
*/
this.email = null;
/**
* Descriptive text as received from the nameserver. This is only
* set for records of type TXT
* @type String
* @see #TYPE_TXT
*/
this.text = null;
/**
* Returns the wrapped nameserver record data
* @returns The wrapped data
* @type org.wonderly.net.dns.RR
*/
this.getData = function() {
return data;
};
/**
* Main constructor body
*/
switch (data.getClass()) {
case jala.DnsClient.PKG.ARR:
case jala.DnsClient.PKG.AAAARR:
this.host = data.getHost();
this.ipAddress = data.getIPAddress();
break;
case jala.DnsClient.PKG.NSRR:
this.host = data.getHost();
break;
case jala.DnsClient.PKG.CNAMERR:
this.cname = data.getCName();
break;
case jala.DnsClient.PKG.MXRR:
this.mx = data.getExchanger();
break;
case jala.DnsClient.PKG.SOARR:
this.host = data.getNSHost();
this.email = data.getResponsibleEmail();
break;
case jala.DnsClient.PKG.TXTRR:
this.text = data.getText();
break;
default:
break;
}
return this;
};
/** @ignore */
jala.DnsClient.Record.prototype.toString = function() {
return "[jala.DnsClient.Record]";
};

2524
modules/jala/code/Form.js Normal file

File diff suppressed because it is too large Load diff

130
modules/jala/code/Global.js Normal file
View file

@ -0,0 +1,130 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Fields and methods of the Global prototype.
*/
/**
* Returns true if the value passed as argument is either a string literal,
* an instance of String or of java.lang.String.
* @param {Object} val The value to test
* @returns True if the value is a string, false otherwise
* @type Boolean
*/
function isString(val) {
return typeof(val) == "string" ||
val instanceof java.lang.String ||
val instanceof String;
};
/**
* Returns true if the value passed as argument is either a boolean
* literal or an instance of Boolean.
* @param {Object} val The value to test
* @returns True if the value is a boolean, false otherwise
* @type Boolean
*/
function isBoolean(val) {
return typeof(val) == "boolean" ||
val instanceof Boolean;
};
/**
* Returns true if the value passed as argument is either a number,
* an instance of Number or of java.lang.Number.
* @param {Object} val The value to test
* @returns True if the value is a number, false otherwise
* @type Boolean
*/
function isNumber(val) {
return typeof(val) == "number" ||
val instanceof java.lang.Number ||
val instanceof Number;
};
/**
* Returns true if the value passed as argument is null.
* @param {Object} val The value to test
* @returns True if the value is null, false otherwise
* @type Boolean
*/
function isNull(val) {
return val === null;
};
/**
* Returns true if the value passed as argument is undefined.
* @param {Object} val The value to test
* @returns True if the value is undefined, false otherwise
* @type Boolean
*/
function isUndefined(val) {
return val === undefined;
};
/**
* Returns true if the value passed as argument is an array.
* @param {Object} val The value to test
* @returns True if the value is an array, false otherwise
* @type Boolean
*/
function isArray(val) {
return val instanceof Array;
};
/**
* Returns true if the value passed as argument is either a Javascript date
* or an instance of java.util.Date.
* @param {Object} val The value to test
* @returns True if the value is a date, false otherwise
* @type Boolean
*/
function isDate(val) {
return val instanceof Date ||
val instanceof java.util.Date;
};
/**
* Returns true if the value passed as argument is either a Javascript
* object or an instance of java.lang.Object.
* @param {Object} val The value to test
* @returns True if the value is an object, false otherwise
* @type Boolean
*/
function isObject(val) {
return val instanceof Object ||
val instanceof java.lang.Object;
};
/**
* Returns true if the value passed as argument is a function.
* @param {Object} val The value to test
* @returns True if the argument is a function, false otherwise
* @type Boolean
*/
function isFunction(val) {
return val instanceof Function;
};

View file

@ -0,0 +1,253 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Fields and methods of the jala.History class.
*/
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
/**
* Constructs a new History object.
* @class This class is an implementation of a Browser-like history
* stack suitable to use in any Helma application. The difference
* to a Browser's history is that this implementation ignores
* POST requests and checks if Urls in the stack are still valid to
* prevent eg. redirections to a HopObject's url that has been deleted.
* Plus it is capable to create new "intermediate" history-stacks
* and this way maintain a "history of histories" which is needed for
* eg. editing sessions in a popup window that should use their own
* request history without interfering with the history of the
* main window.
* @constructor
*/
jala.History = function() {
var MAX = 40;
/**
* Stack constructor
* @private
*/
var Stack = function(id) {
this.items = [];
this.id = id;
return this;
};
/**
* Returns the current url including query string
* @private
*/
var getUrl = function() {
var query;
var url = path.href(req.action);
try {
if (query = req.getServletRequest().getQueryString())
url += "?" + query;
} catch (e) {
// ignore
}
return url;
}
/**
* Checks if a request is valid for being added
* to the history stack. This method returns false
* for all POST-requests or requests whose action name
* contains a dot (to prevent requests for external stylesheets
* or the like from being recorded).
* @private
* @type Boolean
*/
var isValid = function() {
// FIXME: we should check for mimetype of response instead
// of assuming that requests containing a dot aren't worth
// being put into history stack ...
if (req.isPost() || (req.action && req.action.contains(".")))
return false;
return true;
};
/**
* returns a single Stack instance
* @private
*/
var getStack = function() {
if (history.length < 1)
history.push(new Stack(getUrl()));
return history[history.length -1];
};
/**
* Variable containing the history-stacks
* @private
*/
var history = [];
/**
* Initializes a new history stack, adds
* it to the array of stacks (which makes it
* the default one to use for further requests)
* and records the current request Url.
*/
this.add = function() {
if (!isValid())
return;
var url = getUrl();
if (getStack().id != url) {
history.push(new Stack(url));
this.push();
}
return;
};
/**
* Removes the current history stack
*/
this.remove = function() {
history.pop();
return;
};
/**
* Records a request Url in the currently active
* history stack.
*/
this.push = function() {
if (isValid()) {
var obj = path[path.length-1];
var url = getUrl();
var stack = getStack();
if (stack.items.length < 1 || stack.items[stack.items.length -1].url != url) {
if (stack.items.length >= MAX)
stack.items.shift();
stack.items.push({
url: url,
path: path.href().substring(root.href().length).replace(/\+/g, " ")
});
}
}
return;
};
/**
* Clears the currently active history stack
*/
this.clear = function() {
getStack().items.length = 0;
return;
};
/**
* Redirects the client back to the first valid
* request in history. Please mind that searching for
* a valid Url starts at <em>history.length - 2</em>.
* @param {Number} offset The index position in the stack to start
* searching at
*/
this.redirect = function(offset) {
res.redirect(this.pop(offset));
return;
};
/**
* Retrieves the first valid request Url in history
* stack starting with a given offset. The default offset is 1.
* Any valid Url found is removed from the stack, therefor
* this method <em>alters the contents of the history stack</em>.
* @param {Number} offset The index position in history stack to start
* searching at
* @return The Url of the request
* @type String
*/
this.pop = function(offset) {
/**
* checks if a referrer is stil valid
* @private
*/
var isValidPath = function(p) {
var arr = p.split("/");
var obj = root;
for (var i=0;i<arr.length -1;i++) {
if (!(obj = obj.get(unescape(arr[i]))) || obj.__node__.getState() == 3)
return false;
}
return true;
};
var obj;
var cut = offset != null ? offset : 1;
var stack = getStack();
if (stack.items.length > 0) {
while (cut-- > 0) {
obj = stack.items.pop();
}
}
while (stack.items.length > 0) {
obj = stack.items.pop();
// check if url is valid
if (isValidPath(obj.path)) {
return obj.url;
}
}
return path.href();
};
/**
* Retrieves the request Url at the given position
* in the current history stack. If no offset is given
* the last Url in the stack is returned. This method
* <em>does not alter the stack contents</em>!
* @param {Number} offset The index position in history stack to start
* searching at
* @return The Url of the request
* @type String
*/
this.peek = function(offset) {
var stack = getStack();
return stack.items[stack.items.length - (offset != null ? offset : 1)];
};
/**
* Returns the contents of all history stacks
* as string
* @return The history stacks as string
* @type String
*/
this.dump = function() {
return history.toSource();
};
/** @ignore */
this.toString = function() {
return "[History " + getStack().toSource() + "]";
};
return this;
}

View file

@ -0,0 +1,177 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Additional fields and methods of the HopObject class.
*/
/**
* HelmaLib dependencies
*/
app.addRepository("modules/core/String.js");
app.addRepository("modules/helma/File.js");
/**
* Constructs a name from an object which
* is unique in the underlying HopObject collection.
* @param {Object} obj The object representing or containing
* the alias name. Possible object types include:
* <ul>
* <li>File</li>
* <li>helma.File</li>
* <li>java.io.File</li>
* <li>String</li>
* <li>java.lang.String</li>
* <li>Packages.helma.util.MimePart</li>
* </ul>
* @param {Number} maxLength The maximum length of the alias
* @returns The resulting alias
* @type String
*/
HopObject.prototype.getAccessName = function(obj, maxLength) {
/**
* Private method checking if the key passed as argument is already
* existing in this object
* @param {String} key The key string to test
* @returns True in case the key is already in use, false otherwise
* @type Boolean
*/
var isReserved = function(obj, key) {
return key === "." ||
key === ".." ||
obj[key] != null ||
obj[key + "_action"] != null ||
obj.get(key) != null
};
// prepare name depending on argument
var name;
var clazz = obj.constructor || obj.getClass();
switch (clazz) {
case File:
case helma.File:
case java.io.File:
case Packages.helma.util.MimePart:
// first fix bloody ie/win file paths containing backslashes
name = obj.getName().split(/[\\\/]/).pop();
if (name.contains("."))
name = name.substring(0, name.lastIndexOf("."));
break;
case String:
case java.lang.String:
name = obj;
break;
default:
name = obj.toString();
}
// remove all (back)slashes
var accessName = name.replace(/[\\\/]/g, "");
// remove all plus signs
accessName = accessName.replace("+","");
if (accessName.length > maxLength) {
accessName = accessName.substring(0, maxLength);
}
var result = accessName;
if (isReserved(this, result)) {
var len = result.length;
var counter = 1;
var overflow;
while (isReserved(this, result)) {
result = accessName + "-" + counter.toString();
if ((overflow = result.length - maxLength) > 0) {
result = accessName.substring(0, accessName.length - overflow) +
"-" + counter.toString();
if (result.length > maxLength) {
throw "Unable to create accessname due to limit restriction";
}
}
counter += 1;
}
}
return result;
};
/**
* Returns true if the internal state of this HopObject is TRANSIENT.
* @returns True if this HopObject is marked as <em>transient</em>, false otherwise.
* @type Boolean
*/
HopObject.prototype.isTransient = function() {
return this.__node__.getState() === Packages.helma.objectmodel.INodeState.TRANSIENT;
};
/**
* Returns true if the internal state of this HopObject is VIRTUAL.
* @returns True if this HopObject is marked as <em>virtual</em>, false otherwise.
* @type Boolean
*/
HopObject.prototype.isVirtual = function() {
return this.__node__.getState() === Packages.helma.objectmodel.INodeState.VIRTUAL;
};
/**
* Returns true if the internal state of this HopObject is INVALID.
* @returns True if this HopObject is marked as <em>invalid</em>, false otherwise.
* @type Boolean
*/
HopObject.prototype.isInvalid = function() {
return this.__node__.getState() === Packages.helma.objectmodel.INodeState.INVALID;
};
/**
* Returns true if the internal state of this HopObject is CLEAN.
* @returns True if this HopObject is marked as <em>clean</em>, false otherwise.
* @type Boolean
*/
HopObject.prototype.isClean = function() {
return this.__node__.getState() === Packages.helma.objectmodel.INodeState.CLEAN;
};
/**
* Returns true if the internal state of this HopObject is NEW.
* @returns True if this HopObject is marked as <em>new</em>, false otherwise.
* @type Boolean
*/
HopObject.prototype.isNew = function() {
return this.__node__.getState() === Packages.helma.objectmodel.INodeState.NEW;
};
/**
* Returns true if the internal state of this HopObject is MODIFIED.
* @returns True if this HopObject is marked as <em>modified</em>, false otherwise.
* @type Boolean
*/
HopObject.prototype.isModified = function() {
return this.__node__.getState() === Packages.helma.objectmodel.INodeState.MODIFIED;
};
/**
* Returns true if the internal state of this HopObject is DELETED.
* @returns True if this HopObject is marked as <em>deleted</em>, false otherwise.
* @type Boolean
*/
HopObject.prototype.isDeleted = function() {
return this.__node__.getState() === Packages.helma.objectmodel.INodeState.DELETED;
};

View file

@ -0,0 +1,156 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Fields and methods of the jala.HtmlDocument class.
*/
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
/**
* Jala dependencies
*/
(function() {
var jalaDir = getProperty("jala.dir", "modules/jala");
app.addRepository(jalaDir + "/lib/dom4j-1.6.1.jar");
app.addRepository(jalaDir + "/lib/jaxen-1.1-beta-8.jar");
})();
/**
* Construct a new HTML document.
* @class This class provides easy access to the elements of
* an arbitrary HTML document. By using TagSoup, Dom4J and Jaxen
* even invalid HTML can be parsed, turned into an object tree
* and easily be processed with XPath expressions.
* @param {String} source The HTML source code.
* @returns A new HTML document.
* @constructor
*/
jala.HtmlDocument = function(source) {
var REQUIREMENTS = {
"dom4j-1.6.1": "http://www.dom4j.org",
"jaxen-1.1-beta-8": "http://www.jaxen.org"
};
var reader = new java.io.StringReader(source);
var dom4j = Packages.org.dom4j;
var tagsoup = "org.ccil.cowan.tagsoup.Parser";
try {
var saxReader = new dom4j.io.SAXReader(tagsoup);
var document = saxReader.read(reader);
document.normalize();
} catch(e) {
res.push();
res.write("\njala.HtmlDocument requires the following Java ");
res.write("packages in ext/lib or application directory:\n");
for (var i in REQUIREMENTS) {
res.write(i);
res.write(".jar");
res.write(" [");
res.write(REQUIREMENTS[i]);
res.write("]\n");
}
throw (e + res.pop());
}
/**
* Get all document nodes from an XPath expression.
* @param {String} xpathExpr An XPath expression.
* @returns A list of HTML elements.
* @type org.dom4j.tree.DefaultElement
*/
this.scrape = function(xpathExpr) {
return document.selectNodes(xpathExpr);
};
/**
* Get all link elements of the HTML document.
* @returns A list of link elements.
* @type Array
*/
this.getLinks = function() {
var result = [];
var list = this.scrape("//html:a");
for (var i=0; i<list.size(); i+=1) {
var element = list.get(i);
var text = element.getText();
var href = element.attribute("href");
if (text && href) {
result.push({
text: text,
url: href.getText()
});
}
}
return result;
};
/**
* Retrieves all elements by name from the document.
* The returned object structure is compatible for usage
* in {@link jala.XmlWriter}.
* @param {String} elementName The name of the desired element
* @returns The list of available elements in the document
* @type Array
*/
this.getAll = function(elementName) {
var result = [], object;
var list = this.scrape("//html:" + elementName);
var i, n, element, text, attributes, attr, size;
for (i=0; i<list.size(); i+=1) {
element = list.get(i);
object = {
name: element.getName(),
value: element.getText() || null
};
attributes = element.attributes();
if ((size = attributes.size()) > 0) {
object.attributes = new Array;
for (n=0; n<size; n+=1) {
attr = attributes.get(n);
object.attributes.push({
name: attr.getName(),
value: attr.getData() || null
});
}
}
result.push(object);
}
return result;
};
/**
* Get a string representation of the HTML document.
* @returns A string representation of the HTML document.
* @type String
*/
this.toString = function() {
return "[jala.HtmlDocument " + source.length + " Bytes]";
};
return this;
};

403
modules/jala/code/I18n.js Normal file
View file

@ -0,0 +1,403 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Methods and macros for internationalization
* of Helma applications.
*/
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
/**
* Constructs a new instance of jala.I18n
* @class This class provides various functions and macros for
* internationalization of Helma applications.
* @constructor
* @type jala.I18n
*/
jala.I18n = function() {
/**
* The default object containing the messages.
* @ignore
*/
var messages = global.messages;
/**
* The default method for retrieving the locale.
* @ignore
*/
var localeGetter = function() {
return java.util.Locale.getDefault();
};
/**
* Overwrite the default object containing
* the messages (ie. a vanilla EcmaScript object).
* @param {Object} msgObject The object containing the messages
*/
this.setMessages = function(msgObject) {
messages = msgObject;
};
/**
* Get the message object.
* @returns The object containing the messages
* @type Object
*/
this.getMessages = function() {
return messages;
};
/**
* Set the method for retrieving the locale.
* @param {Function} func The getter method
*/
this.setLocaleGetter = function(func) {
if (func && func.constructor == Function) {
localeGetter = func;
} else {
throw Error("Getter method to retrieve locale must be a function");
}
return;
};
/**
* Get the method for retrieving the locale.
* @returns The getter method
* @type Function
*/
this.getLocaleGetter = function() {
return localeGetter;
};
return this;
};
/**
* The default handler containing the messages.
* @ignore
*/
jala.I18n.HANDLER = global;
/** @ignore */
jala.I18n.prototype.toString = function() {
return "[Jala i18n]";
};
/**
* Set (overwrite) the default handler containing
* the messages (ie. a vanilla EcmaScript object).
* @param {Object} handler The handler containing the message object
* @deprecated Use {@link #setMessages} instead
*/
jala.I18n.prototype.setHandler = function(handler) {
this.setMessages(handler.messages);
return;
};
/**
* Returns the locale for the given id, which is expected to follow
* the form <code>language[_COUNTRY][_variant]</code>, where <code>language</code>
* is a valid ISO Language Code (eg. "de"), <code>COUNTRY</code> a valid ISO
* Country Code (eg. "AT"), and variant an identifier for the variant to use.
* @returns The locale for the given id
* @type java.util.Locale
*/
jala.I18n.prototype.getLocale = function(localeId) {
if (localeId) {
if (localeId.indexOf("_") > -1) {
var arr = localeId.split("_");
if (arr.length == 3) {
return new java.util.Locale(arr[0], arr[1], arr[2]);
} else {
return new java.util.Locale(arr[0], arr[1]);
}
} else {
return new java.util.Locale(localeId);
}
}
return java.util.Locale.getDefault();
}
/**
* Tries to "translate" the given message key into a localized
* message.
* @param {String} key The message to translate (required)
* @param {String} plural The plural form of the message to translate
* @param {Number} amount A number to determine whether to use the
* singular or plural form of the message
* @returns The localized message or the appropriate key if no
* localized message was found
* @type String
*/
jala.I18n.prototype.translate = function(singularKey, pluralKey, amount) {
var translation = null;
if (singularKey) {
// use the getter method for retrieving the locale
var locale = this.getLocaleGetter()();
var catalog, key;
if ((catalog = jala.i18n.getCatalog(locale))) {
if (arguments.length == 3 && amount != 1) { // is plural
key = pluralKey;
} else {
key = singularKey;
}
if (!(translation = catalog[key])) {
translation = key;
app.logger.debug("jala.i18n.translate(): Can't find message '" +
key + "' for locale '" + locale + "'");
}
} else {
app.logger.debug("jala.i18n.translate(): Can't find message catalog for locale '" + locale + "'");
if (!pluralKey || amount == 1) {
translation = singularKey;
} else {
translation = pluralKey;
}
}
}
return translation;
};
/**
* Helper method to get the message catalog
* corresponding to the actual locale.
* @params {java.util.Locale} locale
* @returns The message catalog.
*/
jala.I18n.prototype.getCatalog = function(locale) {
if (!jala.I18n.catalogs) {
jala.I18n.catalogs = {};
}
var catalog = jala.I18n.catalogs[locale];
if (catalog) return catalog;
var messages = this.getMessages();
if (locale && messages) {
catalog = messages[locale.toLanguageTag()];
jala.I18n.catalogs[locale] = catalog;
}
return catalog;
};
/**
* Converts the message passed as argument into an instance
* of java.text.MessageFormat, and formats it using the
* replacement values passed.
* @param {String} message The message to format
* @param {Array} values An optional array containing replacement values
* @returns The formatted message or, if the formatting fails, the
* message passed as argument.
* @type String
* @see http://java.sun.com/j2se/1.5.0/docs/api/java/text/MessageFormat.html
*/
jala.I18n.prototype.formatMessage = function(message, values) {
if (message) {
var args = null;
if (values != null && values.length > 0) {
args = java.lang.reflect.Array.newInstance(java.lang.Object, values.length);
var arg;
for (var i=0;i<values.length;i++) {
if ((arg = values[i]) != null) {
// MessageFormat can't deal with javascript date objects
// so we need to convert them into java.util.Date instances
if (arg instanceof Date) {
args[i] = new java.util.Date(arg.getTime());
} else {
args[i] = arg;
}
}
}
}
// use the getter method for retrieving the locale
var locale = this.getLocaleGetter()();
// format the message
try {
var msgFormat = new java.text.MessageFormat(message, locale);
return msgFormat.format(args);
} catch (e) {
app.logger.warn("jala.i18n.formatMessage(): Unable to format message '"
+ message + "', reason: " + e, e.javaException);
}
}
return null;
};
/**
* Returns a localized message for the message key passed as
* argument. If no localization is found, the message key
* is returned. Any additional arguments passed to this function
* will be used as replacement values during message rendering.
* To reference these values the message can contain placeholders
* following "{number}" notation, where <code>number</code> must
* match the number of the additional argument (starting with zero).
* @param {String} key The message to localize
* @returns The translated message
* @type String
* @see #translate
* @see #formatMessage
*/
jala.I18n.prototype.gettext = function(key /** [value 0][, value 1][, ...] */) {
return this.formatMessage(this.translate(key),
Array.prototype.splice.call(arguments, 1));
};
/**
* Returns a localized message for the message key passed as
* argument. In contrast to gettext() this method
* can handle plural forms based on the amount passed as argument.
* If no localization is found, the appropriate message key is
* returned. Any additional arguments passed to this function
* will be used as replacement values during message rendering.
* To reference these values the message can contain placeholders
* following "{number}" notation, where <code>number</code> must
* match the number of the additional argument (starting with zero).
* @param {String} singularKey The singular message to localize
* @param {String} pluralKey The plural form of the message to localize
* @param {Number} amount The amount which is used to determine
* whether the singular or plural form of the message should be returned.
* @returns The translated message
* @type String
* @see #translate
* @see #formatMessage
*/
jala.I18n.prototype.ngettext = function(singularKey, pluralKey, amount /** [value 0][, value 1][, ...] */) {
return this.formatMessage(this.translate(singularKey, pluralKey, amount || 0),
Array.prototype.splice.call(arguments, 2));
};
/**
* A simple proxy method which is used to mark a message string
* for the i18n parser as to be translated.
* @param {String} key The message that should be seen by the
* i18n parser as to be translated.
* @returns The message in unmodified form
* @type String
*/
jala.I18n.prototype.markgettext = function(key) {
return key;
};
/**
* Returns a translated message. The following macro attributes
* are accepted:
* <ul>
* <li>text: The message to translate (required)</li>
* <li>plural: The plural form of the message</li>
* <li>values: A list of replacement values. Use a comma to separate more
* than one value. Each value is either interpreted as a global property
* (if it doesn't containg a dot) or as a property name of the given macro
* handler object (eg. "user.name"). If the value of the property is a
* HopObject or an Array this macro uses the size() resp. length of the
* object, otherwise the string representation of the object will be used.</li>
* </ul>
* @returns The translated message
* @type String
* @see #gettext
* @see #ngettext
*/
jala.I18n.prototype.message_macro = function(param) {
if (param.text) {
var args = [param.text];
if (param.plural) {
args[args.length] = param.plural;
}
if (param.values != null) {
var arr = param.values.split(/\s*,\s*/g);
// convert replacement values: if the value name doesn't contain
// a dot, look for a global property with that name, otherwise
// for a property of the specified macro handler object.
var propName, dotIdx, handlerName, handler;
for (var i=0;i<arr.length;i++) {
if ((propName = arr[i]) != null) {
var value = null;
if ((dotIdx = propName.indexOf(".")) > 0) {
var handlerName = propName.substring(0, dotIdx);
if (handlerName == "request") {
handler = req.data;
} else if (handlerName == "response") {
handler = res.data;
} else if (!(handler = res.handlers[handlerName])) {
continue;
}
propName = propName.substring(dotIdx + 1);
// primitive security: don't allow access to internal properties
// and a property named "password"
if (propName.charAt(0) != "_" && propName.toLowerCase() != "password") {
value = handler[propName];
}
} else {
value = global[propName];
}
if (value != null) {
// if its a HopObject collection or Array, use its size/length
// as value
if (value instanceof HopObject) {
value = value.size();
} else if (value instanceof Array) {
value = value.length;
}
}
args[args.length] = value;
}
}
}
if (param.plural) {
return this.ngettext.apply(this, args);
} else {
return this.gettext.apply(this, args);
}
}
return;
};
/**
* Default i18n class instance.
* @type jala.I18n
* @final
*/
jala.i18n = new jala.I18n();
/**
* For convenience reasons the public methods and macros are
* put into global scope too
*/
var gettext = function() {
return jala.i18n.gettext.apply(jala.i18n, arguments);
};
var ngettext = function() {
return jala.i18n.ngettext.apply(jala.i18n, arguments);
};
var markgettext = function() {
return jala.i18n.markgettext.apply(jala.i18n, arguments);
};
var message_macro = function() {
return jala.i18n.message_macro.apply(jala.i18n, arguments);
};

View file

@ -0,0 +1,362 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Fields and methods of the jala.ImageFilter class.
*/
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
/**
* Constructs a new ImageFilter object
* @class This class provides several image manipulating
* methods. Most of this filter library is based on filters created
* by Janne Kipinä for JAlbum. For more information have a look
* at http://www.ratol.fi/~jakipina/java/
* @param {Object} img Either
<ul>
<li>an instance of helma.image.ImageWrapper</li>
<li>the path to the image file as String</li>
<li>an instance of helma.File representing the image file</li>
<li>an instance of java.io.File representing the image file</li>
</ul>
* @constructor
*/
jala.ImageFilter = function(img) {
/**
* The buffered image to work on
* @type java.awt.image.BufferedImage
* @private
*/
var bi;
/**
* Perfoms a gaussian operation (unsharp masking or blurring)
* on the image using the kernelFactory passed as argument
* @param {Number} radius The radius
* @param {Number} amount The amount
* @param {Function} kernelFactory Factory method to call for building the kernel
* @private
*/
var gaussianOp = function(radius, amount, kernelFactory) {
var DEFAULT_RADIUS = 2;
var MINIMUM_RADIUS = 1;
var MAXIMUM_RADIUS = 10;
var DEFAULT_AMOUNT = 15;
var MINIMUM_AMOUNT = 1;
var MAXIMUM_AMOUNT = 100;
// correct arguments if necessary
if (isNaN(radius = Math.min(Math.max(radius, MINIMUM_RADIUS), MAXIMUM_RADIUS)))
radius = DEFAULT_RADIUS;
if (isNaN(amount = Math.min(Math.max(amount, MINIMUM_AMOUNT), MAXIMUM_AMOUNT)))
amount = DEFAULT_AMOUNT;
if ((bi.getWidth() < bi.getHeight()) && (radius > bi.getWidth())) {
radius = bi.getWidth();
} else if ((bi.getHeight() < bi.getWidth()) && (radius > bi.getHeight())) {
radius = bi.getHeight();
}
var size = (radius * 2) + 1;
var deviation = amount / 20;
var elements = kernelFactory(size, deviation);
var large = jala.ImageFilter.getEnlargedImageWithMirroring(bi, radius);
var resultImg = new java.awt.image.BufferedImage(large.getWidth(), large.getHeight(), large.getType());
var kernel = new java.awt.image.Kernel(size, size, elements);
var cop = new java.awt.image.ConvolveOp(kernel, java.awt.image.ConvolveOp.EDGE_NO_OP, null);
cop.filter(large, resultImg);
// replace the wrapped buffered image with the modified one
bi = resultImg.getSubimage(radius, radius, bi.getWidth(), bi.getHeight());
return;
};
/**
* Sharpens the image using a plain sharpening kernel.
* @param {Number} amount The amount of sharpening to apply
*/
this.sharpen = function(amount) {
var DEFAULT = 20;
var MINIMUM = 1;
var MAXIMUM = 100;
// correct argument if necessary
if (isNaN(Math.min(Math.max(amount, MINIMUM), MAXIMUM)))
amount = DEFAULT;
var sharpened = new java.awt.image.BufferedImage(bi.getWidth(), bi.getHeight(), bi.getType());
var kernel = new java.awt.image.Kernel(3, 3, jala.ImageFilter.getSharpeningKernel(amount));
var cop = new java.awt.image.ConvolveOp(kernel, java.awt.image.ConvolveOp.EDGE_NO_OP, null);
cop.filter(bi, sharpened);
bi = sharpened;
return;
};
/**
* Performs an unsharp mask operation on the image
* @param {Number} radius The radius
* @param {Number} amount The amount
*/
this.unsharpMask = function(radius, amount) {
gaussianOp(radius, amount, jala.ImageFilter.getUnsharpMaskKernel);
return;
};
/**
* Performs a gaussian blur operation on the image
* @param {Number} radius The radius
* @param {Number} amount The amount
*/
this.gaussianBlur = function(radius, amount) {
gaussianOp(radius, amount, jala.ImageFilter.getGaussianBlurKernel);
return;
};
/**
* Returns the image that has been worked on
* @return An instance of helma.image.ImageWrapper
* @type helma.image.ImageWrapper
*/
this.getImage = function() {
var generator = Packages.helma.image.ImageGenerator.getInstance();
return new Packages.helma.image.ImageWrapper(bi,
bi.getWidth(),
bi.getHeight(),
generator);
};
/**
* Returns the wrapped image as byte array, to use eg. in conjunction
* with res.writeBinary()
* @returns The wrapped image as byte array
* @type byte[]
*/
this.getBytes = function() {
var outStream = new java.io.ByteArrayOutputStream();
Packages.javax.imageio.ImageIO.write(bi, "jpeg", outStream);
var bytes = outStream.toByteArray();
outStream.close();
return bytes;
};
/**
* constructor body
* @ignore
*/
if (arguments.length == 0 || img == null) {
throw "jala.ImageFilter: insufficient arguments";
} else if (img instanceof Packages.helma.image.ImageWrapper) {
bi = img.getBufferedImage();
} else {
if (typeof(img) == "string") {
var inStream = new java.io.FileInputStream(new java.io.File(img));
} else {
var inStream = new java.io.FileInputStream(img);
}
var decoder = Packages.com.sun.image.codec.jpeg.JPEGCodec.createJPEGDecoder(inStream);
bi = decoder.decodeAsBufferedImage();
}
return this;
};
/** @ignore */
jala.ImageFilter.prototype.toString = function() {
return "[jala.ImageFilter]";
};
/**
* Transforms an image into a bigger one while mirroring the edges
* This method is used to apply the filtering up to the edges
* of an image (otherwise the image would keep an unmodified
* border).
* @param {java.awt.image.BufferedImage} bi The buffered image to transform
* @param {Number} size The size of the border area
* @returns The transformed image
* @type java.awt.image.BufferedImage
* @private
*/
jala.ImageFilter.getEnlargedImageWithMirroring = function(bi, size) {
var doFlip = function(bi, sx, sy, dist) {
var out = new java.awt.image.BufferedImage(bi.getWidth(), bi.getHeight(), bi.getType());
var transform = java.awt.geom.AffineTransform.getScaleInstance(sx, sy);
(sx < sy) ? transform.translate(-dist, 0) : transform.translate(0, -dist);
var atop = new java.awt.image.AffineTransformOp(transform,
java.awt.image.AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
out = atop["filter(java.awt.image.BufferedImage,java.awt.image.BufferedImage)"](bi, null);
return out;
}
var doHorizontalFlip = function(bi) {
return doFlip(bi, -1, 1, bi.getWidth());
}
var doVerticalFlip = function(bi) {
return doFlip(bi, 1, -1, bi.getHeight());
}
var width = bi.getWidth() + 2 * size;
var height = bi.getHeight() + 2 * size;
var out = new java.awt.image.BufferedImage(width, height, bi.getType());
var g = out.createGraphics();
// due to method overloading exactly define the method to be called
var func = "drawImage(java.awt.Image,int,int,java.awt.image.ImageObserver)";
g[func](bi, size, size, null);
var part;
//top-left corner
part = bi.getSubimage(0, 0, size, size);
part = doHorizontalFlip(part);
part = doVerticalFlip(part);
g[func](part, 0, 0, null);
//top-right corner
part = bi.getSubimage(bi.getWidth()-size, 0, size, size);
part = doHorizontalFlip(part);
part = doVerticalFlip(part);
g[func](part, width-size, 0, null);
//bottom-left corner
part = bi.getSubimage(0, bi.getHeight()-size, size, size);
part = doHorizontalFlip(part);
part = doVerticalFlip(part);
g[func](part, 0, height-size, null);
//bottom-right corner
part = bi.getSubimage(bi.getWidth()-size, bi.getHeight()-size, size, size);
part = doHorizontalFlip(part);
part = doVerticalFlip(part);
g[func](part, width-size, height-size, null);
//left border
part = bi.getSubimage(0, 0, size, bi.getHeight());
part = doHorizontalFlip(part);
g[func](part, 0, size, null);
//right border
part = bi.getSubimage(bi.getWidth()-size, 0, size, bi.getHeight());
part = doHorizontalFlip(part);
g[func](part, width-size, size, null);
//top border
part = bi.getSubimage(0, 0, bi.getWidth(), size);
part = doVerticalFlip(part);
g[func](part, size, 0, null);
//bottom border
part = bi.getSubimage(0, bi.getHeight()-size, bi.getWidth(), size);
part = doVerticalFlip(part);
g[func](part, size, height-size, null);
return out;
};
/**
* Factory method for a gaussian blur kernel
* @returns The gaussian blur kernel
* @param {Number} size The size of the kernel
* @param {Number} deviation The deviation to use
* @returns The gaussian blur kernel
* @type float[]
* @private
*/
jala.ImageFilter.getGaussianBlurKernel = function(size, deviation) {
var nominator = 2 * deviation * deviation;
var kernel = java.lang.reflect.Array.newInstance(java.lang.Float.TYPE, size*size);
var center = (size - 1) / 2;
var limit = size - 1;
var xx, yy;
var sum = 0;
var value = 0;
for (var y=0; y<size; y++) {
for (var x=0; x<size; x++) {
if ((y <= center) && (x <= center)) {
if (x >= y) {
//calculate new value
xx = center - x;
yy = center - y;
value = Math.exp(-(xx*xx + yy*yy) / nominator);
kernel[(y*size)+x] = value;
sum += value;
} else {
//copy existing value
value = kernel[(x*size)+y];
kernel[(y*size)+x] = value;
sum += value;
}
} else {
xx = x;
yy = y;
if (yy > center)
yy = limit - yy;
if (xx > center)
xx = limit - xx;
value = kernel[(yy*size)+xx];
kernel[(y*size)+x] = value;
sum += value;
}
}
}
for (var i=0; i<kernel.length; i++) {
kernel[i] = kernel[i] / sum;
}
return kernel;
};
/**
* Factory method for an unsharp mask kernel
* @param {Number} size The size of the kernel
* @param {Number} deviation The deviation to use
* @returns The unsharp mask kernel
* @type float[]
* @private
*/
jala.ImageFilter.getUnsharpMaskKernel = function(size, deviation) {
var elements = jala.ImageFilter.getGaussianBlurKernel(size, deviation);
var center = ((size * size) - 1) / 2;
elements[center] = 0;
var sum = 0;
for (var i=0; i<elements.length; i++) {
sum += elements[i];
elements[i] = -elements[i];
}
elements[center] = sum + 1;
return elements;
};
/**
* Factory method for a sharpening kernel
* @param {Number} amount The amount of sharpening to use
* @return The sharpening kernel
* @type float[]
* @private
*/
jala.ImageFilter.getSharpeningKernel = function(amount) {
var kernel = java.lang.reflect.Array.newInstance(java.lang.Float.TYPE, 9);
var corner = 0;
var side = amount / -50;
var center = (side * -4.0) + (corner * -4.0) + 1.0;
kernel[0] = kernel[2] = kernel[6] = kernel[8] = corner;
kernel[1] = kernel[3] = kernel[5] = kernel[7] = side;
kernel[4] = center;
return kernel;
};

View file

@ -0,0 +1,765 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Fields and methods of the jala.IndexManager class.
*/
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
/**
* HelmaLib dependencies
*/
app.addRepository("modules/helma/Search.js");
app.addRepository("modules/helma/File.js");
/**
* Constructs a new IndexManager object.
* @class This class basically sits on top of a helma.Search.Index instance
* and provides methods for adding, removing and optimizing the underlying index.
* All methods generate jobs that are put into an internal queue which is
* processed asynchronously by a separate worker thread. This means all calls
* to add(), remove() and optimize() will return immediately, but the changes to
* the index will be done within a short delay. Please keep in mind to change the
* status of this IndexManager instance to REBUILDING before starting to rebuild
* the index, as this ensures that all add/remove/optimize jobs will stay in the
* queue and will only be processed after switching the status back to NORMAL.
* This ensures that objects that have been modified during a rebuilding process
* are re-indexed properly afterwards.
* @param {String} name The name of the index, which is the name of the directory
* the index already resides or will be created in.
* @param {helma.File} dir The base directory where this index's directory
* is already existing or will be created in. If not specified a RAM directory
* is used.
* @param {String} lang The language of the documents in this index. This leads
* to the proper Lucene analyzer being used for indexing documents.
* @constructor
* @see helma.Search.createIndex
*/
jala.IndexManager = function IndexManager(name, dir, lang) {
/**
* Private variable containing the worker thread
* @private
*/
var thread = null;
/**
* Private flag indicating that the worker thread should stop
* @type Boolean
* @private
*/
var interrupted = false;
/**
* Private variable containing the index managed by
* this IndexManager instance.
* @private
*/
var index = null;
/**
* Private variable containing a status indicator.
* @type Number
* @private
*/
var status = jala.IndexManager.NORMAL;
/**
* Synchronized linked list that functions as a queue for
* asynchronous processing of index manipulation jobs.
* @type java.util.LinkedList
* @private
* @see jala.IndexManager.Job
*/
var queue = java.util.Collections.synchronizedList(new java.util.LinkedList());
/**
* The name of the unique identifier field in the index. Defaults to "id".
* @type String
* @private
*/
var idFieldname = "id";
/**
* The index directory
* @type Packages.org.apache.lucene.store.Directory
* @private
*/
var indexDirectory = null;
/**
* The searcher utilized by {@link #search}
* @type jala.IndexManager.Searcher
* @private
*/
var searcher = null;
/**
* Returns the directory of the underlying index
* @returns The directory of the underlying index
* @type Packages.org.apache.lucene.store.Directory
*/
this.getDirectory = function() {
return indexDirectory;
};
/**
* Returns the underlying index.
* @returns The index this queue is working on.
* @type helma.Search.Index
*/
this.getIndex = function() {
return index;
};
/**
* Returns the status of this manager.
* @returns The status of this index manager.
* @type Number
* @see #NORMAL
* @see #REBUILDING
*/
this.getStatus = function() {
return status;
};
/**
* Modifies the status of this manager, which has implications
* on how index modifying jobs are handled. If the status
* is {@link #REBUILDING}, all jobs are queued until the status
* is set back to {@link #NORMAL}.
* @param {Number} s The new status of this manager.
* @see #NORMAL
* @see #REBUILDING
*/
this.setStatus = function(s) {
status = s;
return;
};
/**
* Returns the queue this index manager is using.
* @returns The queue.
* @type java.util.LinkedList
*/
this.getQueue = function() {
return queue;
};
/**
* Returns the name of the index manger, which
* is equal to the name of the underlying index
* @returns The name of the index manager
* @type String
*/
this.getName = function() {
return name;
};
/**
* Returns the name of the field containing the unique identifier
* of document objects in the index wrapped by this IndexManager.
* Defaults to "id".
* @returns The name of the id field in the index
* @type String
* @see #setIdFieldname
*/
this.getIdFieldname = function() {
return idFieldname;
};
/**
* Sets the name of the field containing the unique identifier
* of document objects in the index wrapped by this IndexManager.
* @see #getIdFieldname
*/
this.setIdFieldname = function(name) {
idFieldname = name;
return;
};
/**
* Returns true if the underlying index is currently optimized.
* @returns True in case the index is optimized, false otherwise.
* @type Boolean
*/
this.hasOptimizingJob = function() {
for (var i=0; i<queue.size(); i++) {
if (queue.get(i).type == jala.IndexManager.Job.OPTIMIZE) {
return true;
}
}
return false;
};
/**
* Returns true if the underlying index is currently rebuilding.
* @returns True in case the index is rebuilding, false otherwise.
* @type Boolean
*/
this.isRebuilding = function() {
return status == jala.IndexManager.REBUILDING;
};
/**
* Starts the IndexManager worker thread that processes the job queue
*/
this.start = function() {
if (!this.isRunning()) {
interrupted = false;
thread = app.invokeAsync(this, function() {
while (interrupted === false) {
if (this.getStatus() != jala.IndexManager.REBUILDING && !queue.isEmpty()) {
var job = queue.remove(0);
if (this.processJob(job) === false) {
// processing job failed, check if we should re-add
if (job.errors < jala.IndexManager.MAXTRIES) {
// increment error counter and put back into queue
job.errors += 1;
queue.add(job);
} else {
this.log("error", "error during queue flush: tried " +
jala.IndexManager.MAXTRIES + " times to handle " +
job.type + " job " + ", giving up.");
}
}
this.log("debug", "remaining jobs " + queue.size());
// if no more jobs are waiting, optimize the index and re-open
// the index searcher to make changes visible
if (queue.isEmpty()) {
var start = java.lang.System.currentTimeMillis();
try {
this.getIndex().optimize();
this.log("optimized index in " + jala.IndexManager.getRuntime(start) + " ms");
this.initSearcher();
} catch (e) {
this.log("error", "Unable to optimize index or re-open searcher, reason: " + e.toString());
}
}
} else {
// wait for 100ms before checking again
java.lang.Thread.sleep(100);
}
}
return true;
}, [], -1);
this.log("started successfully");
} else {
this.log("already running");
}
return;
};
/**
* Stops this IndexManager instance. This function waits for 10 seconds
* maximum for the worker thread to stop.
* @returns True if the worker thread stopped successfully, false otherwise
* @type Boolean
*/
this.stop = function() {
interrupted = true;
var result;
if ((result = this.isRunning()) === true) {
if ((result = thread.waitForResult(10000)) === true) {
thread = null;
this.log("stopped successfully");
} else {
result = false;
this.log("error", "unable to stop");
}
} else {
this.log("info", "already stopped");
}
return result;
};
/**
* Returns true if this IndexManager instance is running
* @returns True if this IndexManager instance is running, false otherwise.
* @type Boolean
*/
this.isRunning = function() {
if (thread != null) {
return thread.running;
}
return false;
};
/**
* Read only reference containing the running status of this IndexManager
* @type Boolean
*/
this.running; // for api documentation only, is overwritten by getter below
this.__defineGetter__("running", function() {
return this.isRunning()
});
/**
* Read only reference containing the number of pending jobs
* @type Number
*/
this.pending; // for api documentation only, is overwritten by getter below
this.__defineGetter__("pending", function() {
return queue.size()
});
/**
* Initializes the searcher
* @private
*/
this.initSearcher = function() {
searcher = new Packages.org.apache.lucene.search.IndexSearcher(indexDirectory);
return;
};
/**
* Returns the searcher of this index manager
* @returns The searcher of this index manager
* @type org.apache.lucene.search.IndexSearcher
* @private
*/
this.getSearcher = function() {
if (searcher === null) {
this.initSearcher();
}
return searcher;
};
/**
* Main constructor body. Initializes the underlying index.
*/
var search = new helma.Search();
var analyzer = helma.Search.getAnalyzer(lang);
if (dir != null) {
indexDirectory = search.getDirectory(new helma.File(dir, name));
this.log("created/mounted " + indexDirectory);
} else {
indexDirectory = search.getRAMDirectory();
this.log("created new RAM directory");
}
index = search.createIndex(indexDirectory, analyzer);
return this;
};
/**
* Constant defining the maximum number of tries to add/remove
* an object to/from the underlying index.
* @type Number
* @final
*/
jala.IndexManager.MAXTRIES = 10;
/**
* Constant defining normal mode of this index manager.
* @type Number
* @final
*/
jala.IndexManager.NORMAL = 1;
/**
* Constant defining rebuilding mode of this index manager.
* @type Number
* @final
*/
jala.IndexManager.REBUILDING = 2;
/**
* Returns the milliseconds elapsed between the current timestamp
* and the one passed as argument.
* @returns The elapsed time in millis.
* @type Number
* @private
*/
jala.IndexManager.getRuntime = function(millis) {
return java.lang.System.currentTimeMillis() - millis;
};
/** @ignore */
jala.IndexManager.prototype.toString = function() {
return "[" + this.constructor.name + " '" + this.getName() + "' (" +
this.pending + " objects queued)]";
};
/**
* Helper function that prefixes every log message with
* the name of the IndexManager.
* @param {String} level An optional logging level. Accepted values
* @param {String} msg The log message
* are "debug", "info", "warn" and "error".
*/
jala.IndexManager.prototype.log = function(/* msg, level */) {
var level = "info", message;
if (arguments.length == 2) {
level = arguments[0];
message = arguments[1];
} else {
message = arguments[0];
}
app.logger[level]("[" + this.constructor.name + " '" +
this.getName() + "'] " + message);
return;
};
/**
* Static helper method that returns the value of the "id"
* field of a document object.
* @param {helma.Search.Document} doc The document whose id
* should be returned.
* @private
*/
jala.IndexManager.prototype.getDocumentId = function(doc) {
try {
return doc.getField(this.getIdFieldname()).value;
} catch (e) {
// ignore
}
return null;
};
/**
* Queues the document object passed as argument for addition to the underlying
* index. This includes that all existing documents with the same identifier will
* be removed before the object passed as argument is added.
* @param {helma.Search.Document} doc The document object that should be
* added to the underlying index.
* @returns True if the job was added successfully to the internal queue,
* false otherwise.
* @type Boolean
* @see helma.Search.Document
*/
jala.IndexManager.prototype.add = function(doc) {
var id;
if (!doc) {
this.log("error", "missing document object to add");
return false;
} else if ((id = this.getDocumentId(doc)) == null) {
this.log("error", "document doesn't contain an Id field '" +
this.getIdFieldname() + "'");
return false;
}
// the job's callback function which actually adds the document to the index
var callback = function() {
var start = java.lang.System.currentTimeMillis();
this.getIndex().updateDocument(doc, this.getIdFieldname());
this.log("debug", "added document with Id " + id +
" to index in " + jala.IndexManager.getRuntime(start) + " ms");
return;
}
var job = new jala.IndexManager.Job(jala.IndexManager.Job.ADD, callback);
this.getQueue().add(job);
this.log("debug", "queued adding document " + id + " to index");
return true;
};
/**
* Queues the removal of all index documents whose identifier value ("id" by default)
* matches the number passed as argument.
* @param {Number} id The identifier value
* @returns True if the removal job was added successfully to the queue, false
* otherwise.
* @type Boolean
*/
jala.IndexManager.prototype.remove = function(id) {
if (id === null || isNaN(id)) {
this.log("error", "missing or invalid document id to remove");
return false;
}
// the job's callback function which actually removes all documents
// with the given id from the index
var callback = function() {
var start = java.lang.System.currentTimeMillis();
this.getIndex().removeDocument(this.getIdFieldname(), parseInt(id, 10));
this.log("debug", "removed document with Id " + id +
" from index in " + jala.IndexManager.getRuntime(start) + " ms");
};
var job = new jala.IndexManager.Job(jala.IndexManager.Job.REMOVE, callback);
this.getQueue().add(job);
this.log("debug", "queued removal of document with Id " + id);
return true;
};
/**
* Queues the optimization of the underlying index. Normally there is no need
* to call this method explicitly, as the index will be optimized after all
* queued jobs have been processed.
* @returns True if the optimizing job was added, false otherwise, which means
* that there is already an optimizing job waiting in the queue.
* @type Boolean
*/
jala.IndexManager.prototype.optimize = function() {
if (this.hasOptimizingJob()) {
return false;
}
var callback = function() {
var start = java.lang.System.currentTimeMillis();
this.getIndex().optimize();
this.log("optimized index in " + jala.IndexManager.getRuntime(start) + " ms");
// re-open index searcher, so that changes are seen
this.initSearcher();
return;
};
var job = new jala.IndexManager.Job(jala.IndexManager.Job.OPTIMIZE, callback);
this.getQueue().add(job);
this.log("debug", "queued index optimization");
return true;
};
/**
* Processes a single queued job
* @param {Object} job
* @private
*/
jala.IndexManager.prototype.processJob = function(job) {
this.log("debug", job.type + " job has been in queue for " +
jala.IndexManager.getRuntime(job.createtime.getTime()) +
" ms, processing now...");
try {
job.callback.call(this);
} catch (e) {
this.log("error", "Exception while processing job " + job.type + ": " + e);
return false;
}
return true;
};
/**
* Searches the underlying index using the searcher of this index manager
* @param {helma.Search.Query|org.apache.lucene.search.Query} query The query
* to execute. Can be either an instance of helma.Search.Query, or an instance
* of org.apache.lucene.search.Query
* @param {helma.Search.QueryFilter|org.apache.lucene.search.Filter} filter
* An optional query filter
* @param {Array} sortFields An optional array containing
* org.apache.lucene.search.SortField instances to use for sorting the result
* @returns A HitCollection containing the search results
* @type helma.Search.HitCollection
*/
jala.IndexManager.prototype.search = function(query, filter, sortFields) {
var pkg = Packages.org.apache.lucene;
if (query == null || (!(query instanceof helma.Search.Query) &&
!(query instanceof pkg.search.Query))) {
throw "jala.IndexManager search(): missing or invalid query";
} else if (query instanceof helma.Search.Query) {
// unwrap query
query = query.getQuery();
}
if (filter != null && filter instanceof helma.Search.QueryFilter) {
// unwrap filter
filter = filter.getFilter();
}
var searcher = this.getSearcher();
var analyzer = this.getIndex().getAnalyzer();
var hits;
if (sortFields != null && sortFields.length > 0) {
// convert the array with sortfields to a java array
var arr = java.lang.reflect.Array.newInstance(pkg.search.SortField, sortFields.length);
sortFields.forEach(function(sortField, idx) {
arr[idx] = sortField;
});
var sort = pkg.search.Sort(arr);
if (filter) {
hits = searcher.search(query, filter, sort);
} else {
hits = searcher.search(query, sort);
}
} else if (filter) {
hits = searcher.search(query, filter);
} else {
hits = searcher.search(query);
}
this.log("debug", "Query: " + query.toString());
return new helma.Search.HitCollection(hits);
};
/**
* Parses the query string passed as argument into a lucene Query instance
* @param {String} queryStr The query string to parse
* @param {Array} fields An array containing the names of the files to search in
* @param {Object} boostMap An optional object containing properties whose name denotes
* the name of the field to boost in the query, and the value the boost value.
* @returns The query
* @type org.apache.lucene.search.Query
*/
jala.IndexManager.prototype.parseQuery = function(queryStr, fields, boostMap) {
if (queryStr == null || typeof(queryStr) !== "string") {
throw "IndexManager.parseQuery(): missing or invalid query string";
}
if (fields == null || fields.constructor !== Array || fields.length < 1) {
throw "IndexManager.parseQuery(): missing fields argument";
}
var query = null;
var analyzer = this.getIndex().getAnalyzer();
var pkg = Packages.org.apache.lucene;
var map = null;
if (boostMap != null) {
// convert the javascript object into a HashMap
map = new java.util.HashMap();
for (var name in boostMap) {
map.put(name, new java.lang.Float(boostMap[name]));
}
}
var parser;
try {
if (fields.length > 1) {
parser = new pkg.queryParser.MultiFieldQueryParser(fields, analyzer, map);
} else {
parser = new pkg.queryParser.QueryParser(fields, analyzer);
}
query = parser.parse(queryStr);
} catch (e) {
// ignore, but write a message to debug log
app.logger.debug("Unable to construct search query '" + queryStr +
"', reason: " + e);
}
return query;
};
/**
* Parses the query passed as argument and returns a caching filter. If an array
* with more than one query strings is passed as argument, this method constructs
* a boolean query filter where all queries in the array must match.
* @param {String|Array} query Either a query string, or an array containing
* one or more query strings
* @param {org.apache.lucene.analysis.Analyzer} analyzer Optional analyzer
* to use when parsing the filter query
* @returns A caching query filter
* @type org.apache.lucene.search.CachingWrapperFilter
*/
jala.IndexManager.prototype.parseQueryFilter = function(query, analyzer) {
var filter = null;
if (query != null) {
var pkg = Packages.org.apache.lucene;
// use the index' analyzer if none has been specified
if (analyzer == null) {
analyzer = this.getIndex().getAnalyzer();
}
var parser = new pkg.queryParser.QueryParser("", analyzer);
var filterQuery;
try {
if (query.constructor === Array) {
if (query.length > 1) {
filterQuery = new pkg.search.BooleanQuery();
query.forEach(function(queryStr){
filterQuery.add(parser.parse(queryStr), pkg.search.BooleanClause.Occur.MUST);
}, this);
} else {
filterQuery = parser.parse(query[0]);
}
} else {
filterQuery = parser.parse(query);
}
filter = new pkg.search.CachingWrapperFilter(new pkg.search.QueryWrapperFilter(filterQuery));
} catch (e) {
app.logger.debug("Unable to parse query filter '" + query + "', reason: " + e);
}
}
return filter;
};
/*********************
***** J O B *****
*********************/
/**
* Creates a new Job instance.
* @class Instances of this class represent a single index
* manipulation job to be processed by the index manager.
* @param {Number} id The Id of the job
* @param {Number} type The type of job, which can be either
* jala.IndexManager.Job.ADD, jala.IndexManager.Job.REMOVE
* or jala.IndexManager.Job.OPTIMIZE.
* @param {Object} data The data needed to process the job.
* @returns A newly created Job instance.
* @constructor
* @see jala.IndexManager.Job
*/
jala.IndexManager.Job = function(type, callback) {
/**
* The type of the job
* @type Number
*/
this.type = type;
/**
* The data needed to process this job. For adding jobs this property
* must contain the {@link helma.Search.Document} instance to add to
* the index. For removal job this property must contain the unique identifier
* of the document that should be removed from the index. For optimizing
* jobs this property is null.
*/
this.callback = callback;
/**
* An internal error counter which is increased whenever processing
* the job failed.
* @type Number
* @see jala.IndexManager.MAXTRIES
*/
this.errors = 0;
/**
* The date and time at which this job was created.
* @type Date
*/
this.createtime = new Date();
return this;
};
/** @ignore */
jala.IndexManager.Job.prototype.toString = function() {
return "[Job (type: " + this.type + ")]";
};
/**
* Constant defining an add job
* @type Number
* @final
*/
jala.IndexManager.Job.ADD = "add";
/**
* Constant defining a removal job
* @type Number
* @final
*/
jala.IndexManager.Job.REMOVE = "remove";
/**
* Constant defining an optimizing job
* @type Number
* @final
*/
jala.IndexManager.Job.OPTIMIZE = "optimize";

File diff suppressed because it is too large Load diff

1521
modules/jala/code/Mp3.js Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,129 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Fields and methods of the jala.PodcastWriter class.
*/
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
/**
* Jala dependencies
*/
app.addRepository(getProperty("jala.dir", "modules/jala") +
"/code/Rss20Writer.js");
/**
* @class Class to create, modify and render standard-compliant
* RSS 2.0 feeds including support for Apple's Podcast specification.
* @constructor
* @extends jala.Rss20Writer
* @param {String} header Optional XML header.
*/
jala.PodcastWriter = function(header) {
jala.Rss20Writer.apply(this, arguments);
var CATEGORY = {
name: "itunes:category",
attributes: {
name: "text"
}
};
var OWNER = {
name: "itunes:owner",
value: [{
name: "itunes:name"
}, {
name: "itunes:email"
}]
};
this.addNamespace("itunes", "http://www.itunes.com/dtds/podcast-1.0.dtd");
this.extendChannel([{
name: "itunes:author"
}, {
name: "itunes:subtitle"
}, {
name: "itunes:summary"
}, {
name: "itunes:new-feed-url"
}, {
name: "itunes:image",
attributes: [{
name: "href"
}]
}, {
name: "itunes:link",
attributes: [{
name: "rel"
}, {
name: "type"
}, {
name: "href"
}]
}]);
this.getChannel().setValue(this.createElement(OWNER));
this.extendItem([{
name: "itunes:duration"
}, {
name: "itunes:subtitle"
}]);
/**
* Add an iTunes Podcast category.
* @param {String} name The category's name.
* @param {String} subName The (optional) sub-category's name.
* @param {jala.XmlWriter.XmlElement} parent Optional parent
* element to add the category to.
*/
this.addItunesCategory = function(name, subName, parent) {
if (!parent)
parent = this.getChannel();
var cat = this.createElement(CATEGORY);
cat.populate({attributes: {text: name}});
if (subName) {
var subCat = this.createElement(CATEGORY);
subCat.populate({attributes: {text: subName}});
cat.addValue(subCat);
}
parent.addValue(cat);
return;
};
return this;
};
/** A typical XML header as default.
@type String @final */
jala.PodcastWriter.XMLHEADER = '<?xml version="1.0" encoding="UTF-8"?>';

View file

@ -0,0 +1,307 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Fields and methods of the jala.RemoteContent class.
*/
// HelmaLib dependencies
app.addRepository("modules/core/String.js");
app.addRepository("modules/core/Object.js");
app.addRepository("modules/core/Date.js");
app.addRepository("modules/helma/Http.js");
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
/**
* Construct a new remote content handler.
* @class API to define, fetch and update content
* from a remote site.
* @param {String} url The URL string of the remote site.
* @param {Integer} method The method to retrieve the remote content.
* @param {File} storage The cache directory.
* @returns A new remote content handler.
* @extends helma.Http
* @constructor
*/
jala.RemoteContent = function(url, method, storage) {
if (typeof PropertyMgr == "undefined")
var PropertyMgr = {};
var NULLSTR = "";
var key = url.md5();
var fname = key + jala.RemoteContent.SUFFIX;
var cache;
method = (method != null ? method.toLowerCase() : null);
// depending on the method argument the instance
// becomes extent of the appropriate remote client
switch (method) {
case jala.RemoteContent.XMLRPC:
break;
default:
helma.Http.call(this);
break;
}
if (!storage) {
storage = jala.RemoteContent.CACHEDIR;
if (!storage.exists() || !storage.isDirectory())
storage.mkdir(storage.getAbsolutePath());
}
var getCache = function() {
switch (storage.constructor) {
case HopObject:
cache = storage;
break;
case PropertyMgr:
cache = storage.getAll();
break;
default:
var f = new File(storage, fname);
cache = f.exists() ? Xml.read(f) : new HopObject();
}
return cache;
};
var setCache = function() {
cache.url = url;
cache.method = method;
if (!cache.interval) {
cache.interval = Date.ONEHOUR;
}
cache.lastUpdate = new Date();
cache = cache.clone(new HopObject());
switch (storage.constructor) {
case HopObject:
for (var i in cache)
storage[i] = cache[i];
break;
case PropertyMgr:
storage.setAll(cache);
break;
default:
var f = new File(storage, fname);
Xml.write(cache, f);
}
return;
};
cache = getCache();
/**
* Set the interval the remote content's
* cache is bound to be updated.
* @param {Number} interval The interval value in milliseconds.
*/
this.setInterval = function(interval) {
cache.interval = parseInt(interval, 10);
return;
};
/**
* Get an arbitrary property of the remote content.
* @param {String} key The name of the property.
* @returns The value of the property.
*/
this.get = function(key) {
return cache[key];
}
/**
* Get all available property names.
* @returns The list of property names.
* @type Array
*/
this.getKeys = function() {
var keys = [];
for (var i in cache) {
keys.push(i);
}
return keys.sort();
};
/**
* Tests whether the remote content needs to be updated.
* @returns True if the remote content needs to be updated.
* @type Boolean
*/
this.needsUpdate = function() {
if (!cache.lastUpdate) {
return true;
} else {
var max = new Date() - cache.interval;
if (max - cache.lastUpdate > 0) {
return true;
}
}
return false;
};
/**
* Get the updated and cached remote content.
* @returns The content as retrieved from the remote site.
* @type String
*/
this.update = function() {
app.debug("[jala.RemoteContent] Retrieving " + url);
var result;
switch (method) {
case jala.RemoteContent.XMLRPC:
break;
default:
result = this.getUrl(url, cache.lastModified || cache.eTag);
if (result.code != 200 && cache.content) {
// preserve the content received before
result.content = cache.content;
}
result.interval = cache.interval;
cache = result;
}
setCache();
return cache.content;
};
/**
* Flushes (empties) the cached remote content.
*/
this.clear = function() {
switch (storage.constructor) {
case HopObject:
for (var i in storage)
delete storage[i];
break;
case PropertyMgr:
storage.reset();
break;
default:
var f = new File(storage, fname);
f.remove();
}
return;
};
/**
* Get a string representation of the remote content.
* @returns The remote content as string.
* @type String
*/
this.toString = function() {
return cache.content || NULLSTR;
};
/**
* Get the value of the remote content.
* @returns The remote content including response header data.
* @type Object
*/
this.valueOf = function() {
return cache;
};
return this;
};
/**
* A constant representing the HTTP retrieval method.
* @type int
* @final
*/
jala.RemoteContent.HTTP = 1;
/**
* A constant representing the XML-RPC retrieval method.
* @type int
* @final
*/
jala.RemoteContent.XMLRPC = 2;
/**
* The default name of the cache directory.
* @type String
* @final
*/
jala.RemoteContent.SUFFIX = ".cache";
/**
* The default cache directory.
* @type File
* @final
*/
jala.RemoteContent.CACHEDIR = new File(app.dir, jala.RemoteContent.SUFFIX);
/**
* Remove all remote content from a file-based cache.
* @param {File} cache An optional target directory.
*/
jala.RemoteContent.flush = function(cache) {
jala.RemoteContent.forEach(function(rc) {
rc.clear();
return;
});
return;
};
/**
* Apply a custom method on all remote content in a file-based cache.
* @param {Function} callback The callback method to be executed
* for each remote content file.
* @param {File} cache An optional target directory.
*/
jala.RemoteContent.forEach = function(callback, cache) {
if (!cache)
cache = jala.RemoteContent.CACHEDIR;
var f, rc;
var files = cache.list();
for (var i in files) {
f = new File(cache, files[i]);
if (!files[i].endsWith(jala.RemoteContent.SUFFIX))
continue;
rc = new jala.RemoteContent(Xml.read(f).url);
if (callback && callback.constructor == Function)
callback(rc);
}
return;
};
/**
* Apply a custom method on all remote content in a file-based cache.
* @param {Function} callback The callback method to be executed
* for each remote content file.
* @param {File} cache An optional target directory.
* @deprecated Use {@link #forEach} instead.
*/
jala.RemoteContent.exec = function() {
jala.RemoteContent.forEach.apply(this, arguments);
};

View file

@ -0,0 +1,334 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Fields and methods of the jala.Rss20Writer class.
*/
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
/**
* Jala dependencies
*/
app.addRepository(getProperty("jala.dir", "modules/jala") +
"/code/XmlWriter.js");
/**
* @class Class to create, modify and render standard-compliant
* RSS 2.0 feeds.
* @constructor
* @extends jala.XmlWriter
* @param {String} header Optional XML header.
*/
jala.Rss20Writer = function(header) {
// defines the prototype of this constructor
jala.XmlWriter.apply(this, arguments);
// this should do the same but alas, helma throws
// an error the very first time it is executed:
//arguments.callee.prototype = new jala.XmlWriterInterface();
var DATEFMT = "EEE, dd MMM yyyy HH:mm:ss Z";
var CATEGORY = {
name: "category",
amount: Infinity,
attributes: {
name: "domain",
}
};
var ITEM = {
name: "item",
amount: Infinity,
value: [{
name: "title",
required: true
}, {
name: "link",
}, {
name: "description",
}, {
name: "author",
}, {
name: "comments",
}, {
name: "enclosure",
attributes: [{
name: "url",
required: true
}, {
name: "length",
required: true
}, {
name: "type",
required: true
}]
}, {
name: "guid",
attributes: [{
name: "isPermaLink",
type: Boolean
}]
}, {
name: "pubDate",
type: Date,
format: DATEFMT
}, {
name: "source",
attributes: [{
name: "url",
required: true
}]
}]
};
var CHANNEL = {
name: "channel",
value: [{
name: "title",
required: true
}, {
name: "link",
required: true
}, {
name: "description",
required: true
}, {
name: "language",
}, {
name: "copyright",
}, {
name: "managingEditor",
}, {
name: "webMaster",
}, {
name: "pubDate",
type: Date,
format: DATEFMT
}, {
name: "lastBuildDate",
type: Date,
format: DATEFMT
}, {
name: "generator",
}, {
name: "docs",
}, {
name: "cloud",
attributes: [{
name: "domain",
}, {
name: "port",
type: Number,
format: "#"
}, {
name: "path",
}, {
name: "registerProcedure",
}, {
name: "protocol",
}]
}, {
name: "ttl",
type: Number,
format: "#"
}, {
name: "rating",
}, {
name: "skipHours",
}, {
name: "skipDays",
}]
};
var IMAGE = {
name: "image",
value: [{
name: "url",
required: true
}, {
name: "title",
required: true
}, {
name: "link",
required: true
}, {
name: "width",
type: Number,
format: "#"
}, {
name: "height",
type: Number,
format: "#"
}, {
name: "description",
}]
};
var TEXTINPUT = {
name: "textinput",
value: [{
name: "title",
required: true
}, {
name: "description",
required: true
}, {
name: "name",
required: true
}, {
name: "link",
required: true
}]
};
var ROOT = {
name: "rss",
attributes: [{
name: "version",
value: "2.0"
}]
};
var xmlroot = this.createElement(ROOT);
var channel = this.createElement(CHANNEL);
xmlroot.setValue(channel);
/**
* Get the writer's root element.
* @returns The writer's root element.
* @type jala.XmlWriter.XmlElement
*/
this.getRoot = function() {
return xmlroot;
};
/**
* Add child elements to the channel template.
* @param {Array} ext List of additional child elements.
*/
this.extendChannel = function(ext) {
this.extend(CHANNEL, ext);
channel = this.createElement(CHANNEL);
xmlroot.setValue(channel);
return;
};
/**
* Get the writer's channel element.
* @returns The writer's channel element.
* @type jala.XmlWriter.XmlElement
*/
this.getChannel = function() {
return channel;
};
/**
* Populate the channel element with data.
* @param {Object} data An XmlWriter-compliant object structure.
* @returns The populated channel element.
* @type jala.XmlWriter.XmlElement
*/
this.setChannel = function(data) {
return channel.populate(data);
};
/**
* Add child elements to the item template.
* @param {Array} ext List of additional child elements.
*/
this.extendItem = function(ext) {
this.extend(ITEM, ext);
return;
};
/**
* Get a new and innocent item element.
* @param {Object} data An XmlWriter-compliant object structure.
* @returns A new and innocent item element.
* @type jala.XmlWriter.XmlElement
*/
this.createItem = function(data) {
var item = this.createElement(ITEM);
item.populate(data);
return item;
};
/**
* Add an item element to the channel element.
* @param {jala.XmlWriter.XmlElement} item The item element to add.
*/
this.addItem = function(item) {
channel.addValue(item);
return;
};
/**
* Add a category element to an arbitrary element.
* @param {String} name The name of the category.
* @param {String} domain The domain of the category.
* @param {jala.XmlWriter.XmlElement} parent The optional parent element.
*/
this.addCategory = function(name, domain, parent) {
if (!parent)
parent = channel;
var cat = this.createElement(CATEGORY);
cat.populate({
value: name,
attributes: {domain: domain}
});
parent.addValue(cat);
return;
};
/**
* Populate the image element with data.
* @param {Object} data An XmlWriter-compliant object structure.
*/
this.setImage = function(data) {
var image = this.createElement(IMAGE);
image.populate(data);
channel.setValue(image);
return;
};
/**
* Populate the textInput element with data.
* @param {Object} data An XmlWriter-compliant object structure.
*/
this.setTextInput = function(data) {
var textInput = this.createElement(TEXTINPUT);
textInput.populate(data);
channel.setValue(textInput);
return;
};
return this;
};

View file

@ -0,0 +1,247 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Fields and methods of the jala.Utilities class.
*/
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
/**
* HelmaLib dependencies
*/
app.addRepository("modules/core/Number.js");
/**
* Construct a utility object.
* @class This class contains various convenience methods
* which do not fit in any other class.
* @returns A new utitilty object.
* @constructor
*/
jala.Utilities = function() {
return this;
};
/**
* Return a string representation of the utitility class.
* @returns [jala.Utilities]
* @type String
* @ignore FIXME: JSDoc bug
*/
jala.Utilities.toString = function() {
return "[jala.Utilities]";
};
/**
* Return a string representation of the utitility object.
* @returns [jala.Utilities Object]
* @type String
*/
jala.Utilities.prototype.toString = function() {
return "[jala.Utilities Object]";
};
/**
* Default utility class instance.
* @type jala.Utilities
* @final
*/
jala.util = new jala.Utilities();
/**
* Creates a random password with different levels of security.
* @param {Number} len The length of the password (default: 8)
* @param {Number} level The security level
* <ul>
* <li>0 - containing only vowels or consonants (default)</li>
* <li>1 - throws in a number at random position</li>
* <li>2 - throws in a number and a special character at random position</li>
* </ul>
* @returns The resulting password
* @type String
*/
jala.Utilities.prototype.createPassword = function(len, level) {
len = len || 8;
level = level || 0;
var LETTERSONLY = 0;
var WITHNUMBERS = 1;
var WITHSPECIALS = 2;
var vowels = ['a', 'e', 'i', 'o', 'u'];
var consonants = ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'];
var specials = ['.', '#', '!', '$', '%', '&', '?'];
var posNum = level > LETTERSONLY ? Math.floor(Math.random() * (len - 2)) : -1;
var posSpecial = level > WITHNUMBERS ? Math.floor(Math.random() * (len - 3)) : -2;
if (posNum == posSpecial) {
posSpecial += 1;
}
res.push();
// loop to create characters:
var i, rnd;
for (i=0; i<(len-level); i+=1) {
if(i % 2 == 0) {
// every 2nd one is a vowel
rnd = Math.floor(Math.random() * vowels.length);
res.write(vowels[rnd]);
} else {
// every 2nd one is a consonant
rnd = Math.floor(Math.random() * consonants.length);
res.write(consonants[rnd]);
}
if (i == posNum) {
// increased password security:
// throw in a number at random
rnd = Math.floor(Math.random() * specials.length);
res.write(String(rnd + 1));
}
if (i == posSpecial) {
// increased password security:
// throw in a number at random
rnd = Math.floor(Math.random() * specials.length);
res.write(specials[rnd]);
}
}
return res.pop();
};
/**
* Static field indicating a removed object property.
* @type Number
* @final
*/
jala.Utilities.VALUE_REMOVED = -1;
/**
* Static field indicating ad added object property.
* @type Number
* @final
*/
jala.Utilities.VALUE_ADDED = 1;
/**
* Static field indicating a modified object property.
* @type Number
* @final
*/
jala.Utilities.VALUE_MODIFIED = 2;
/**
* Returns an array containing the properties that are
* added, removed or modified in one object compared to another.
* @param {Object} obj1 The first of two objects which should be compared
* @param {Object} obj2 The second of two objects which should be compared
* @returns An Object containing all properties that are added, removed
* or modified in the second object compared to the first.
* Each property contains a status field with an integer value
* which can be checked against the static jala.Utility fields
* VALUE_ADDED, VALUE_MODIFIED and VALUE_REMOVED.
* @type Object
*/
jala.Utilities.prototype.diffObjects = function(obj1, obj2) {
var childDiff, value1, value2;
var diff = {};
var foundDiff = false;
for (var propName in obj1) {
if (obj2[propName] === undefined || obj2[propName] === "" || obj2[propName] === null) {
diff[propName] = {status: jala.Utilities.VALUE_REMOVED};
foundDiff = true;
}
}
for (var propName in obj2) {
value1 = obj1[propName];
value2 = obj2[propName];
if (value1 == null) {
diff[propName] = {status: jala.Utilities.VALUE_ADDED,
value: value2};
foundDiff = true;
} else {
switch (value2.constructor) {
case HopObject:
case Object:
if (childDiff = this.diffObjects(value1, value2)) {
diff[propName] = childDiff;
foundDiff = true;
}
break;
default:
if (value2 != null && value2 !== "") {
if (value1 === null || value1 === undefined || value1 === "") {
diff[propName] = {status: jala.Utilities.VALUE_ADDED,
value: value2};
foundDiff = true;
} else if (value1 != value2) {
diff[propName] = {status: jala.Utilities.VALUE_MODIFIED,
value: value2};
foundDiff = true;
}
}
break;
}
}
}
return foundDiff ? diff : null;
};
/**
* Patches an object with a "diff" object created by the
* {@link #diffObjects} method.
* Please mind that this method is recursive, it descends
* along the "diff" object structure.
* @param {Object} obj The Object the diff should be applied to
* @param {Object} diff A "diff" object created by the {@link #diffObjects} method
* @returns The patched Object with all differences applied
* @type Object
*/
jala.Utilities.prototype.patchObject = function(obj, diff) {
var propDiff, value1;
for (var propName in diff) {
propDiff = diff[propName];
value1 = obj[propName];
if (propDiff.status != null) {
switch (propDiff.status) {
case jala.Utilities.VALUE_REMOVED:
// app.debug("applyDiff(): removing property " + propName);
delete obj[propName];
break;
case jala.Utilities.VALUE_ADDED:
case jala.Utilities.VALUE_MODIFIED:
default:
// app.debug("applyDiff(): changing property " + propName + " to " + propDiff.value);
obj[propName] = propDiff.value;
break;
}
} else {
// app.debug("applyDiff(): descending to child object " + propName);
this.patchObject(value1, propDiff);
}
}
return obj;
};

View file

@ -0,0 +1,461 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Fields and methods of the jala.XmlRpcRequest class.
*/
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
/**
* A constructor for XmlRpc request objects
* @class Instances of this class provide the necessary functionality
* for issueing XmlRpc requests to a remote service.
* @param {String} url The url of the XmlRpc entry point
* @param {String} methodName The name of the method to call
* @returns A newly created jala.XmlRpcRequest instance
* @constructor
*/
jala.XmlRpcRequest = function(url, methodName) {
/** @ignore */
var proxy = null;
/** @ignore */
var timeout = {
"connect": 0,
"socket": 0
};
/** @ignore */
var debug = false;
/** @ignore */
var credentials = null;
// default input and output encoding
/** @ignore */
var inputEncoding = "UTF-8";
/** @ignore */
var outputEncoding = "UTF-8";
/**
* Returns the URL of this request
* @returns The URL of this request
* @type java.net.URL
*/
this.getUrl = function() {
return new java.net.URL(url);
};
/**
* Sets the proxy host and port. For Java runtimes < 1.5 this method
* sets the appropriate system properties (so this has an effect on
* all requests based on java.net.URL), for all others the proxy
* is only set for this request.
* @param {String} proxyString The proxy string in the form 'fqdn:port'
* (eg. my.proxy.com:3128)
*/
this.setProxy = function(proxyString) {
if (proxyString && proxyString.trim()) {
var idx = proxyString.indexOf(":");
if (idx > 0) {
var host = proxyString.substring(0, idx);
var port = proxyString.substring(idx+1);
if (host != null && port != null) {
if (java.lang.Class.forName("java.net.Proxy") != null) {
// construct a proxy instance
var socket = new java.net.InetSocketAddress(host, port);
proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, socket);
} else {
// the pre jdk1.5 way: set the system properties
var sys = java.lang.System.getProperties();
if (host) {
app.log("[Jala XmlRpc Client] WARNING: setting system http proxy to "
+ host + ":" + port);
sys.put("http.proxySet", "true");
sys.put("http.proxyHost", host);
sys.put("http.proxyPort", port);
}
}
}
}
}
return;
};
/**
* Returns the proxy object. This method will only return
* a value if using a java runtime > 1.5
* @returns The proxy to use for this request
* @type java.net.Proxy
* @see #setProxy
*/
this.getProxy = function() {
return proxy;
};
/**
* Sets the credentials for basic http authentication to
* use with this request.
* @param {String} username The username
* @param {String} password The password
*/
this.setCredentials = function(username, password) {
var str = new java.lang.String(username + ":" + password);
credentials = (new Packages.sun.misc.BASE64Encoder()).encode(str.getBytes());
return;
};
/**
* Returns the credentials of this request
* @returns The base46 encoded credentials of this request
* @type String
*/
this.getCredentials = function() {
return credentials;
};
/**
* Sets the connection timeout to the specified milliseconds.
* @param {Number} millis The timeout to use as connection timeout
*/
this.setTimeout = function(millis) {
timeout.connect = millis;
return;
};
/**
* Sets the socket timeout to the specified milliseconds.
* @param {Number} millis The timeout to use as socket timeout
*/
this.setReadTimeout = function(millis) {
timeout.socket = millis;
return;
};
/**
* Returns the connection timeout of this request
* @returns The connection timeout value in milliseconds
* @type Number
*/
this.getTimeout = function() {
return timeout.connect;
};
/**
* Returns the socket timeout of this request
* @returns The socket timeout value in milliseconds
* @type Number
*/
this.getReadTimeout = function() {
return timeout.socket;
};
/**
* Returns the name of the remote function to call
* @returns The name of the remote function
* @type String
*/
this.getMethodName = function() {
return methodName;
};
/**
* Sets both input and output encoding to the
* specified encoding string
* @param {String} enc The encoding to use for
* both input and output. This must be a valid
* java encoding string.
*/
this.setEncoding = function(enc) {
inputEncoding = enc;
outputEncoding = enc;
return;
};
/**
* Sets the input encoding to the specified encoding string
* @param {String} enc The encoding to use for input. This must be a valid
* java encoding string.
*/
this.setInputEncoding = function(enc) {
inputEncoding = enc;
return;
};
/**
* Sets the output encoding to the specified encoding string
* @param {String} enc The encoding to use for output. This must be a valid
* java encoding string.
*/
this.setOutputEncoding = function(enc) {
outputEncoding = enc;
return;
};
/**
* Returns the input encoding
* @returns The input encoding used by this request
* @type String
*/
this.getInputEncoding = function() {
return inputEncoding;
};
/**
* Returns the output encoding
* @returns The output encoding used by this request
* @type String
*/
this.getOutputEncoding = function() {
return outputEncoding;
};
/**
* Enables or disables the debug mode. If enabled the xml source
* of both request and response is included in the result properties
* 'requestXml' and 'responseXml'
* @param {Boolean} flag True or false.
*/
this.setDebug = function(flag) {
debug = flag;
return;
};
/**
* Returns true if debug is enabled for this request, false otherwise
* @returns True if debugging is enabled, false otherwise
* @type Boolean
*/
this.debug = function() {
return debug == true;
};
return this;
};
/** @ignore */
jala.XmlRpcRequest.prototype.toString = function() {
return "[Jala XmlRpc Request]";
};
/**
* Calling this method executes the remote method using
* the arguments specified.
* @returns The result of this XmlRpc request
* @type Object
*/
jala.XmlRpcRequest.prototype.execute = function(/** [arg1][, arg2][, ...] */) {
// if in debug mode, log the time the request took to event log
if (app.__app__.debug() == true) {
var start = new Date();
}
var tz = java.util.TimeZone.getDefault();
var reqProcessor = new Packages.org.apache.xmlrpc.XmlRpcClientRequestProcessor(tz);
var resProcessor = new Packages.org.apache.xmlrpc.XmlRpcClientResponseProcessor(tz);
// create the result object
var result = {
error: null,
result: null,
requestXml: null,
responseXml: null
};
// convert arguments into their appropriate java representations
var params = new java.util.Vector();
for (var i=0;i<arguments.length;i++) {
params.add(jala.XmlRpcRequest.convertArgument(arguments[i]));
}
var r = new Packages.org.apache.xmlrpc.XmlRpcRequest(this.getMethodName(), params);
var requestBytes = reqProcessor.encodeRequestBytes(r, this.getOutputEncoding());
if (this.debug() == true) {
result.requestXml = String(new java.lang.String(requestBytes));
}
// open the connection
var proxy = this.getProxy();
var url = this.getUrl();
var conn = proxy ? url.openConnection(proxy) : url.openConnection();
conn.setAllowUserInteraction(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("User-Agent", "Jala XmlRpc Client");
conn.setRequestProperty("Content-Type", "text/xml");
conn.setRequestProperty("Content-Length", requestBytes.length);
// set timeouts if defined and possible
if (parseFloat(java.lang.System.getProperty("java.specification.version"), 10) >= 1.5) {
conn.setConnectTimeout(this.getTimeout());
conn.setReadTimeout(this.getReadTimeout());
} else {
app.logger.debug("WARNING: timeouts can only be using a Java runtime >= 1.5");
}
// set authentication credentials if defined
if (this.getCredentials() != null) {
conn.setRequestProperty("Authorization", "Basic " + this.getCredentials());
}
try {
conn.setDoOutput(true);
var outStream = conn.getOutputStream();
outStream["write(byte[])"](requestBytes);
outStream.flush();
outStream.close();
if (conn.getContentLength() > 0) {
var inStream = conn.getInputStream();
if (this.debug() == true) {
inStream = new java.io.BufferedInputStream(conn.getInputStream());
var outStream = new java.io.ByteArrayOutputStream();
var buf = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 1024);
var bytes;
while ((bytes = inStream.read(buf)) > -1) {
outStream.write(buf, 0, bytes);
}
result.responseXml = outStream.toString(this.getInputEncoding());
inStream.close();
// change the inStream and don't set the input encoding of
// the response processor, since the conversion already happened above
inStream = new java.io.ByteArrayInputStream(outStream.toByteArray());
}
resProcessor.setInputEncoding(this.getInputEncoding());
var parsedResult = resProcessor.decodeResponse(inStream);
if (parsedResult instanceof java.lang.Exception) {
result.error = parsedResult;
} else {
result.result = jala.XmlRpcRequest.convertResult(parsedResult);
}
}
} catch (e) {
result.error = "[Jala XmlRpc Request] Error executing " + this.getMethodName()
+ " with arguments " + jala.XmlRpcRequest.argumentsToString(arguments)
+ ", the error is: " + e.toString();
}
if (app.__app__.debug() == true) {
app.logger.debug("[Jala XmlRpc Request] (" + ((new Date()) - start) + " ms): executed '"
+ this.getMethodName() + "' with arguments: "
+ jala.XmlRpcRequest.argumentsToString(arguments));
}
return result;
};
/**
* Helper method for converting a Javascript object into
* its appropriate Java object.
* @param {Object} obj The Javascript object to convert
* @returns The appropriate Java representation of the object
* @type java.lang.Object
*/
jala.XmlRpcRequest.convertArgument = function(obj) {
var result;
if (obj instanceof Array) {
// convert into Vector
result = new java.util.Vector(obj.length);
for (var i=0;i<obj.length;i++) {
result.add(i, jala.XmlRpcRequest.convertArgument(obj[i]));
}
} else if (obj instanceof Date) {
// convert into java.util.Date
result = new java.util.Date(obj.getTime());
} else if (typeof(obj) == "boolean" || obj instanceof Boolean) {
result = obj;
} else if (typeof(obj) == "string" || obj instanceof String) {
result = obj;
} else if (isNaN(obj) == false) {
// convert into Integer or Double
if (obj - obj.toFixed() > 0) {
result = new java.lang.Double(obj);
} else {
result = new java.lang.Integer(obj);
}
} else if (obj instanceof Object) {
// convert into Hashtable
result = new java.util.Hashtable();
for (var key in obj) {
if (obj[key] != null) {
result.put(key, jala.XmlRpcRequest.convertArgument(obj[key]));
}
}
} else {
result = obj;
}
return result;
};
/**
* Converts a Java object into its appropriate Javascript representation.
* @param {java.lang.Object} obj The Java object to convert
* @returns The appropriate Javascript representation of the Java object
* @type Object
*/
jala.XmlRpcRequest.convertResult = function(obj) {
var result;
if (obj instanceof java.util.Vector) {
// convert into Array
result = [];
var e = obj.elements();
while (e.hasMoreElements()) {
result.push(jala.XmlRpcRequest.convertResult(e.nextElement()));
}
} else if (obj instanceof java.util.Hashtable) {
// convert into Object
result = {};
var e = obj.keys();
var key;
while (e.hasMoreElements()) {
key = e.nextElement();
result[key] = jala.XmlRpcRequest.convertResult(obj.get(key));
}
} else if (obj instanceof java.lang.String) {
result = String(obj);
} else if (obj instanceof java.lang.Number) {
result = Number(obj);
} else if (obj instanceof java.lang.Boolean) {
result = Boolean(obj);
} else if (obj instanceof java.lang.Date) {
result = new Date(obj.getTime());
} else {
result = obj;
}
return result;
};
/**
* Helper method to format an arguments array into
* a string useable for debugging output.
* @param {Object} args An arguments array
* @returns The arguments array formatted as string
* @type String
*/
jala.XmlRpcRequest.argumentsToString = function(args) {
var arr = [];
for (var i=0;i<args.length;i++) {
if (typeof(args[i]) == "string") {
arr.push('"' + args[i] + '"');
} else {
arr.push(args[i]);
}
}
return arr.join(", ");
};

View file

@ -0,0 +1,366 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Fields and methods of the jala.XmlWriter class.
*/
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
/**
* Construct a new XML writer.
* @class This class defines a generic interface to write
* arbitrary and validating XML source code. This is done
* by first applying data objects onto template objects,
* both in a specified format. Then, the resulting object
* tree is transformed into XML. Moreover, template objects
* can be extended with other template objects to provide
* full flexibility in inheriting subclasses.
* @param {String} header An optional XML header.
* @returns A new XML writer.
* @constructor
*/
jala.XmlWriter = function(header) {
var self = this;
var XMLHEADER = header ||
'<?xml version="1.0" encoding="iso-8859-15"?>';
var LOCALE = java.util.Locale.ENGLISH;
/** @ignore FIXME: JSDoc bug */
var write = function(str) {
return res.write(str);
};
var writeln = function(str) {
res.write(str);
res.write("\n");
return;
};
var getString = function(data, format) {
if (data == null)
return;
switch (data.constructor) {
case String:
return encodeXml(data);
case Number:
case Date:
if (format && data.format)
return encodeXml(data.format(format, LOCALE));
else if (data.toUTCString)
return encodeXml(data.toUTCString());
else
return encodeXml(data.toString());
break;
case Object:
return null;
}
return encodeXml(data.toString());
};
/** @ignore */
var XmlElement = function(data) {
if (!data)
throw Error("Insufficient arguments to create XmlElement");
var children = {};
var properties = [
"name",
"attributes",
"type",
"required",
"format",
"readonly"
];
if (data.value) {
if (data.value.constructor == Object) {
this.value = [new XmlElement(data.value)];
} else if (data.value.constructor == Array) {
this.value = [];
for (var i in data.value) {
this.value[i] = new XmlElement(data.value[i]);
}
} else
throw Error("Cannot handle unknown type of template value");
}
for (var i in properties) {
var key = properties[i];
this[key] = data[key] || null;
}
if (this.attributes) {
this.attributes = self.clone(this.attributes);
if (this.attributes.constructor == Object)
this.attributes = [this.attributes];
} else {
this.attributes = [];
}
return this;
};
/** @ignore */
XmlElement.toString = function() {
return "[XmlElement constructor]";
};
/** @ignore */
XmlElement.prototype.setValue = function(element) {
if (element.constructor != this.constructor)
throw Error("Invalid type for XmlElement addition");
if (!this.value)
this.value = [];
else {
var pos = this.contains(element);
if (pos > -1)
this.value.splice(pos, 1);
}
this.addValue(element);
return this;
};
/** @ignore */
XmlElement.prototype.addValue = function(element) {
if (element.constructor != this.constructor)
throw Error("Invalid type for XmlElement addition");
if (!this.value)
this.value = [];
this.value.push(element);
return this;
};
/** @ignore */
XmlElement.prototype.contains = function(element) {
if (!this.value || !element)
return -1;
for (var i in this.value) {
if (this.value[i].name == element.name)
return i;
}
return -1;
};
/** @ignore */
XmlElement.prototype.populate = function(data) {
if (this.attributes) {
var value;
for (var i in this.attributes) {
var attr = this.attributes[i];
if (!attr.name)
throw Error("Cannot populate unnamed attribute entry");
if (data && data.attributes)
value = data.attributes[attr.name];
if (data && (data.value || data.attributes) && !value && attr.required) {
throw Error('Missing required ' + (attr.type || Object).name + ' attribute "' +
attr.name + '" in element &lt;' + this.name + '&gt; (' + value + ")");
}
if (value && attr.type && attr.type != value.constructor) {
throw Error('Type mismatch in attribute "' +
this.name + ":" + attr.name + '"');
}
if (value) {
app.debug("populating attribute " + attr.name +
" with " + value.constructor.name + ": " + value.toSource());
}
if (!attr.readonly) {
attr.value = getString(value, attr.format) || attr.value ;
}
}
}
if (data && data.value) // && data.value.constructor == Object)
data = data.value;
if (this.value && data) {
for (var i in this.value) {
var element = this.value[i];
element.populate(data[element.name]);
}
} else {
if (!data && this.required)
throw Error('Missing required element "' + this.name + '"');
if (data && this.type && this.type != data.constructor) {
throw Error('Type mismatch in element "' + this.name + '"');
}
if (data) {
app.debug("populating element &lt;" + this.name + "&gt; with " +
(this.type || Object).name + ": " + data.toSource());
}
if (!this.readonly)
this.value = getString(data, this.format) || this.value;
}
return;
};
/** @ignore */
XmlElement.prototype.write = function(path) {
if (!path)
path = "";
if (!this.value && !this.attributes)
return;
var attrBuffer = new java.lang.StringBuffer();
if (this.attributes) {
for (var a in this.attributes) {
var attr = this.attributes[a];
if (attr.value) {
attrBuffer.append(" " + attr.name + '="');
attrBuffer.append(attr.value);
attrBuffer.append('"');
}
}
}
var attrSize = attrBuffer.length();
if (!this.value && attrSize < 1)
return;
write("<" + this.name);
if (attrSize > 0) {
display = true;
write(attrBuffer.toString());
}
if (this.value) {
write(">");
if (this.value && this.value.constructor == Array) {
for (var i in this.value)
this.value[i].write(path+"/"+this.name);
} else
write(this.value);
write("</" + this.name + ">\n");
} else
write("/>\n");
return;
};
/** @ignore */
XmlElement.prototype.toString = function() {
return "[XmlElement: " + this.toSource() + "]";
};
/**
* Get a newly created XML element.
* @param {Object} data The XML data as object tree.
* @returns The resulting XML element.
* @type jala.XmlWriter.XmlElement
*/
this.createElement = function(data) {
return new XmlElement(data);
};
/**
* Get the root XML element of this writer.
* @returns The root XML element.
* @type jala.XmlWriter.XmlElement
*/
this.getRoot = function() {
return new XmlElement({});
};
/**
* Extend a template object.
* @param {Object} template The template object.
* @param {Object} ext The extension object.
* @returns The XML writer.
* @type jala.XmlWriter
*/
this.extend = function(template, ext) {
if (ext.constructor == Object)
ext = [ext];
if (ext.constructor == Array) {
for (var i in ext)
template.value.push(ext[i]);
}
return this;
};
/**
* Add a namespace to this writer.
* @param {String} name The name of the namespace.
* @param {String} url The URL string of the namespace.
* @returns The XML root element.
* @type jala.XmlWriter.XmlElement
*/
this.addNamespace = function(name, url) {
var ref = this.getRoot();
ref.attributes.push({
name: "xmlns:" + name,
value: url
});
return ref;
};
/**
* Write the XML to the response buffer.
*/
this.write = function() {
res.contentType = "text/xml";
writeln(XMLHEADER);
this.getRoot().write();
return;
};
/**
* Get the XML output as string.
* @returns The XML output.
* @type String
*/
this.toString = function() {
res.push();
this.write();
return res.pop();
};
/**
* Clone this XML writer.
* @param {Object} The clone templare.
* @returns The cloned XML writer.
* @type jala.XmlWriter
*/
this.clone = function(obj) {
if (!obj || typeof obj != "object")
return obj;
var copy = new obj.constructor;
for (var i in obj) {
if (obj[i].constructor == Object ||
obj[i].constructor == Array)
copy[i]= this.clone(obj[i]);
else
copy[i] = obj[i];
}
return copy;
};
return this;
};

74
modules/jala/code/all.js Normal file
View file

@ -0,0 +1,74 @@
//
// Jala Project [http://opensvn.csie.org/traccgi/jala]
//
// Copyright 2004 ORF Online und Teletext GmbH
//
// Licensed under the Apache License, Version 2.0 (the ``License'');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an ``AS IS'' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision$
// $LastChangedBy$
// $LastChangedDate$
// $HeadURL$
//
/**
* @fileoverview Wrapper for automatic inclusion of all Jala modules.
*/
// Define the global namespace for Jala modules
if (!global.jala) {
global.jala = {};
}
(function() {
var packages = [
"AsyncRequest",
"BitTorrent",
"Date",
"DnsClient",
"Captcha",
"Form",
"History",
"HtmlDocument",
"HopObject",
"I18n",
"ImageFilter",
"IndexManager",
"ListRenderer",
"Mp3",
"PodcastWriter",
"RemoteContent",
"Rss20Writer",
"Utilities",
"XmlRpcRequest",
"XmlWriter"
];
var jalaDir = getProperty("jala.dir", "modules/jala");
for (var i in packages) {
app.addRepository(jalaDir + "/code/" + packages[i] + ".js");
}
return;
})();
/**
* Get a string representation of the Jala library.
* @returns [Jala JavaScript Application Library]
* @type String
*/
jala.toString = function() {
return "[Jala JavaScript Application Library]";
};