Notice: Use of undefined constant ‘file - assumed '‘file' in /home/jpalio/vhosts/jpaliowikien.torn.com.pl/LocalSettings.php on line 154

Notice: Use of undefined constant bi’ - assumed 'bi’' in /home/jpalio/vhosts/jpaliowikien.torn.com.pl/LocalSettings.php on line 154
JPALIO:Home - Jpaliowiki EN

JPALIO:Home

From Jpaliowiki EN

Jump to: navigation, search

Contents

Introduction

The jPALIO (JAVA based Portal All In One) is a tool for the management of a company's internal processes, devised to operate both in the Intranet and the Internet. The jPALIO as an universal databus, can also be used in the personalized distributed multivendor database-based internet portals with extreme ease of updating information vital for operations of big organizations, companies or corporations. With its significant number of implemented communication connectors (SQL, TCP/IP, XML, LDAP, SMTP, SNMP, JAVA components, WebServices) the system can be easily integrated with other systems and solutions.

The jPALIO is a modular system based entirely on the technologies and products such as: JAVA, Tomcat, Apache and any SQL database with JDBC or ODBC interface (ORACLE, DB2, Sybase, SQLServer, PostgreSQL, HypersonicSQL, Access, etc.). The jPALIO's structure enables easy introduction of new elements and their remote control.

Designing the jPALIO, significant focus was put on proper security strategy, so SSL protocol is used to ensure security of transferred data. Additionally, user authentication may incorporate tokens or chip cards with Public Key Infrastructure.

System features

jPALIO offers the following features:

  • content management as a separate module (Newser)
  • protection against attempts to modify the content of the browser's address bar (it is not possible to change the values of variables sent in the address bar by using checksums)
  • no need to use cookies (cookies are a potential threat), which allows a system built based on jPALIO to work with all browsers
  • the ability to build cluster configurations with load-balancing
  • the ability to build a hierarchical and distributed structure with automatic propagation of new version of the application code to subordinate servers (propagation is restricted to new versions of individual objects, without the need for sending the whole code every time) and with automatic propagation of new versions of jPALIO application servers themselves.
  • roles based access (where roles are built from privileges), the roles are assigned to users in the context of regions/organizational units (the ability to have different roles assigned depending on a region/organizational unit).
  • the client's interface is limited to a web browser (no need to install anything at client PCs, easiness of operations using mobile computers, standardized user interface, independence of the operating system, no need to maintain applications on hundreds of client PCs)
  • easy creation of a user-friendly and fully standardized user interface, full usage of the tips mechanism (selection of data from a list, dialog boxes, etc.) and the data input control mechanism (automatically built forms with data input control logic)
  • user passwords are stored in a database in the undisclosed, encrypted form
  • the ability to activate gzip compression for transferred data, which is especially important in case of low bandwidth links (e.g. dial-up)
  • the ability to use the SSL protocol in communication between jPALIO servers and between jPALIO and a client (a web browser)
  • database connections pooling management, ensuring a high level of efficiency and reliability of data exchange and with automatic restoration of broken connections
  • the ability to authenticate users using tokens and chip cards

jPALIO functional diagram

Image:jPALIO.png

jPALIO architecture

Image:jPALIO-architecture.png

Session control

Session control can be implemented in 2 ways:

  • by storing session information in operating memory
  • by writing session information to the database (an option to implement session sharing by several jPALIO installations

Configuration files

Configuration files describe instances or their parameters. There is a separate configuration file for each instance. Locations of configuration files for all instances are saved in the config.xml file located in the webapps/palio/WEB-INF sub folder of the Tomcat container server's root folder. An example of the config.xml file's contents

<?xml version="1.0" encoding="UTF-8"?>
<palio>
  <config>
    <locale language="pl" timezone="Europe/Warsaw" charset="utf-8"/>
    <!-- Optional port for jDesigner – default 5465 -->
    <designer port="5465"/>
    <instances dir="instances"/>
    <!-- Specification of jPALIO logs folder and the pattern of log file names -->
    <logs dir="/var/log/jpalio" pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c - %m%n" level="DEBUG"/>
    <!-- UProxy server settings -->
    <proxy host="myproxy.com" port="8080"/>
  </config>
</palio>

The dir attribute of the instances tag defines a folder, where configuration files of all instances are located. The access path to this folder defines its location in respect to the folder, where the config.xml file is located. Lack of the instances tag will force the server to search for the instance definition in the sub folder webapps/palio/WEB-INF/instances of the Tomcat container server's root folder, by default. A configuration file for a specific instance should have the name instance_name.xml (jPALIO retrieves the instance name from the file name, disregarding its extension) and contain a definition of a single instance. An example of the instance configuration file

<instance>
  <admin user="administrator login" password="administrator password"/>
  <locale language="pl" timezone="Europe/Warsaw"/>
  <preload all="true" code="true" media="true"/>
  <shared/>
  <cache all="true" media="true" source="false"/>
  <URL runSecure="{ -1 (unSecure), 0 (neutral), 1 (secure) }" runHost="10.2.1.1" mediaSecure="-1" mediaHost="10.2.1.2"/>
  <session timeout="0" cookies="false" staticIP="false"/>
  <secure sid="1234567" hash="MD5"/>
  <page statistic="false" default="1"/>
  <date presentation="dd-MM-yyyy"/>
  <currency thousand=" " decimal="," scale="2"/>

  <connector name="palio" url="jdbc:oracle:thin:@serwer:port:sid" refresh="0" traceRead="true" traceWrite="true" traceExecute="true">
    <user>login</user>
    <password>****</password>
    <dedicatedRefresh>5</dedicatedRefresh>
  </connector>

  <connector name="palio" url="torn.netobjects@serwer:port:jpalio" refresh="0" traceRead="true" traceWrite="true" traceExecute="true">
    <user>login</user>
    <password>****</password>
    <timeout>0</timeout>
    <resetCounter>2000</resetCounter>
  </connector>

  <connector name="data" class="GenericSQLConnector" url="jdbc:oracle:thin:@host:port:sid" refresh="0" traceRead="true" traceWrite="true" traceExecute="true">
    <user>login</user>
    <password>****</password>
    <driver>oracle.jdbc.driver.OracleDriver</driver>
    <initSQL>select sysdate from dual</initSQL>
    <refreshSQL>select sysdate from dual</refreshSQL>
    <reconnectExceptions>17002 17009 1012 28 17410</reconnectExceptions>
  </connector>

  <connector name="informix" class="GenericSQLConnector" url="jdbc:informix-sqli://host:port[/dbname]:INFORMIXSERVER=server_name;user=login;password=****" refresh="0" traceRead="true" traceWrite="true" traceExecute="true">
    <driver>com.informix.jdbc.IfxDriver</driver>
    <reconnectExceptions>201</reconnectExceptions>
  </connector>

  <connector name="remote" url="remote@serwer:port:jpalio" refresh="0" traceRead="true">
    <user>login</user>
    <password>****</password>
    <timeout>0</timeout>
    <resetCounter>2000</resetCounter>
  </connector>

  <connector name="sybase" class="GenericSQLConnector" url="jdbc:sybase:Tds:host:port" refresh="0" traceRead="true" traceWrite="true" traceExecute="true">
    <user>login</user>
    <password>****</password>
    <driver>com.sybase.jdbc.SybDriver</driver>
    <initSQL>use gtc</initSQL>
    <refreshSQL>select sysdate from dual</refreshSQL>
    <reconnectExceptions></reconnectExceptions>
  </connector>

  <connector name="tcp" url="tcp:@host:port" refresh="0" traceWrite="true">
    <charset>iso-8859-2</charset>
  </connector>

  <connector name="ftp" url="ftp://ftp.serwer.pl:21">
    <user>login</user>
    <password>****</password>
  </connector>

  <connector name="ldap" url="ldap://localhost:389/dc=xxx">
    <principal>cn=Manager,dc=xxx</principal>
    <credentials>secret</credentials>
  </connector>

  <listener name="palio">
    <class>palio.listeners.GenericPalioListener</class>
    <port>port</port>
    <user>login</user>
    <password>****</password>
  </listener>

  <listener name="remote">
    <class>palio.listeners.RemoteListener</class>
    <port>port</port>
    <user>login</user>
    <password>****</password>
    <modules>user palio logic mth sql</modules>
  </listener>

  <listener name="metadata">
    <class>palio.listeners.MetaDataListener</class>
    <port>port</port>
  </listener>

  <!-- Optional port for jDesigner - default 5465 -->
  <designer port="5465"/>

  <module name="Ezop">
    <client_conn>st</client_conn>
    <client_table>clients</client_table>
    <client_sequence>clients_s</client_sequence>
  </module>

  <module name="AdServer">
    <refresh_rate>10</refresh_rate>
  </module>

  <module name="Mapper"/>

  <module name="Mail">
    <smtp_server>IP serwera SMTP</smtp_server>
    <pop3_server>IP serwera POP3</pop3_server>
    <charset>ISO-8859-2</charset>
  </module>

  <module name="Scheduler"/>
</instance>

The admin tag defines the administrator's login and password that enable the management of users, who have access to that specific instance's application code. The page tag specifies the portal's home page identifier for a specific instance. The secure tag defines and initializes the checksum calculation algorithm for URL addresses. With connector tags you can define connectors for various types of systems (e.g. databases), including definition of user login and password with user and password tags, respectively. The connector named palio must be defined in the configuration file. With listener tags you can define listeners to listen on various types of ports, including specification of a port number with the port tag and user login and password with user and password tags, respectively. The module tag is used to attach jPALIO modules (sets of functions) that are not available as standard, by providing a module's name as a value of the name attribute and the module's parameters by means of tags embedded in the module tag.

Listeners

Listeners are used to receive calls from a client and to pass them on for execution to the application code. An example of such a listener is the Web server (for calls sent over the HTTP protocol). Listeners can also provide certain services to specific instances. This applies e.g. to the SNMP listener, which collects information on the network status (by first querying the devices) and writes it to a specific instance's table for future analysis.

Connectors

Connectors are used to connect jPALIO with various types of systems.

Instance types

There are three types of instances in jPALIO distinguished by different levels of code's security. Instance type can be set in instance configuration XML file, e.g.

<instance type="master"> (case in-sensitive)

There are three allowed types:

MASTER 
Default bacause of backward compatibility (warnings are logged in case of type's definition lack in configuration). No security restrictions. Full access to all features, packages or libraries.
STANDARD 
This will be default instance type in future releases. Restricted access to critical Java classes allowing to stop server or access environment parameters of VM, etc., Java security management or container's classes. No access also to other instances beyond your own.
RESTRICTED 
Restricted access level, suitable for untrusted users not allowing them to threat jPALIO server as whole Dostępna funkcjonalność jest bardzo ograniczona. Access only to one instance and classes from few packages: palio.modules, palio.api, java.lang (except of few criticals), java.util and java.io (for general stream handling, not access to system files).

All restrictions mentioned above accords to jPalio Classic/Super Palio as well as Java/Groovy classes or scripts.

Components

You can distinguish the following components in jPALIO

pages
objects
privileges
roles
regions
media
tasks

Pages are elements called from the user interface (a web browser) - they portal is composed of them. Each of the pages contains a link to an object that forms its content. When a page is called the system checks if the user has adequate access rights to access it (in case of pages protected with privileges) and if the verification is successful the application control is passed on to the object associated with the page.

Objects are elements, where the application code is saved. Objects form the contents of pages. Each object can call any number of other objects and also - recurrently - itself. The source code that is the contents of a specific object is compiled and cached in the system on the first launch of this object.

Privileges are elements that define access rights to pages. Using privileges you can also restrict access to various parts of the portal.

Roles are groups of privileges. Using roles you can restrict access to various parts of the portal. Depending on the assigned roles users have the guaranteed access only to selected parts of the portal.

Regions are areas, where users' access rights to various parts of the portal are valid. A user can have different roles in each of the regions.

Media are multimedia and binary files (images, animations, movies, sounds, documents, etc.) placed and presented on the pages.

Tasks are definitions of operations performed by jPALIO periodically and automatically. Tasks can be divided into groups. Each group is associated with a separate thread that is dedicated to it. It is especially useful when certain tasks take long time to execute and block execution of other tasks.

Objects, pages and media are placed in a hierarchical types structure that reflects functional modules of the portal.

Syntax of the jPALIO language

Basic features of the created language

  • the server-side executed scripting language
  • distinguishing between small and capital letters
  • no need to define variables
  • variables are treated as arrays indexed from 0
  • arrays can store values of various types at the same time
  • expression values and results returned by functions are added to the HTML code

Data types

Dependencies between data types available in the system are hierarchical in accordance with the diagram

Image:DataTypes.png

List of data types

String - a data type that corresponds to the java.lang.String type; String-type variables are strings of characters placed in double quotation marks (for simple texts, i.e. texts that consist of a single word, usage of quotation marks is not obligatory); in order to place a double quotation mark or a backslash in the string of characters one has to precede it with a backslash

"text text text"
abcdefghijklmnopqrstuvwxyz
""
"description \"quotation\" description"

Long - a data type that corresponds to the java.lang.Long type; Long-type variables are integral numbers with or without a mark

879
-52322
0

Boolean - a data type that corresponds to the java.lang.Boolean type; Boolean-type variables can take logical values of true or false

true
false

BigDecimal - a data type that corresponds to the java.lang.BigDecimal type; BigDecimal-type variables are floating point numbers with or without a mark

-0.75982
11.034
3.14159265358979

Date - a data type that corresponds to the java.util.Date type; Date-type variables are dates, which in application code can be written down in any of the three formats d-M-y, d-M-y H:m, d-M-y H:m:s, where d is day in a month, M is month, y is year, H is hour, m are minutes, s are seconds; the current date can be retrieved with the SYSDATE keyword (letter size is irrelevant)

14-04-966
1-1-2005 15:45
sysdate

LinkedList - a data type that corresponds to the java.util.LinkedList type; LinkedList-type variables are lists of Object[]-type elements; these variables cannot be written directly in the application code but are used to suitably control the application code; LinkedList-type values are typically the results of SQL queries of the SELECT type, which can be used as parameters when calling the for function and instruction

HashMap - a data type that corresponds to the java.util.HashMap type; HashMap-type variables are sets of element pairs of the Object type, where one of them is the key and the other one is the value; these variables cannot be written directly in the application code, HashMap-type values can be used as function call parameters

TreeMap - a data type that corresponds to the java.util.TreeMap type; TreeMap-type variables are sets of element pairs of the Object type, where one of them is the key and the other one is the value; these variables cannot be written directly in the application code, TreeMap-type values can be used as function call parameters

PalioCode - jPALIO code placed in the application code as a string of jPALIO instructions in curly brackets; PalioCode-type variables cannot be defined in the application code - jPALIO code can only be used directly as function call parameters for functions that expect arguments of the PalioCode type

{ $=(var, 7) $var }

Object[] – Object[]-type variables are value arrays of any type; in the application code an array is placed in square brackets as a string of values separated by comas

[19, false, -0.142857, "XYZ"]
[]
["A", [4, 5, 6], [7, 8], sysdate]

byte[] – byte[]-type variables are strings of bytes; these variables cannot be placed directly in the application code; byte[]-type values are typically the contents of binary files placed on the server using upload forms

It is possible to dynamically change data types through casting - preceding calls to a variable's value with a type name in brackets or through conversion - calling an appropriate function.

Variables

Variables are available during a single call of a page but can be passed on by page call parameters in the URL address. All page calls with passing on parameters relate to passing on parameters of the String type. In order to receive parameters of a particular type one has to perform the type conversion using special functions.

Assigning a value to a variable

$=(variable_name, value)

Call to the variable's value

$variable_name

Assigning a value array to a variable

$=(variable_name, [value1, value, value3, ...])

A call to a value array saved in a variable

$variable_name[]

A call to the second element of such array (array elements are indexed from 0)

$variable_name[1]

All variables are treated as arrays and a call to the variable's value is synonymous with a call to the first element of the array (element of the index 0). So, a call

$variable_name

is equivalent to

$variable_name[0]

A change of the variable's value through casting

(type_name)$variable_name

A variable that does not exist or has no value assigned to it has a null value defined by the null constant of the Object-type. A variable can be assigned the null value as well

$=(variable_name, null)

In order to assign null values to all array elements one can use the null constant type casting

$=(variable_name, (Object[])null)

Each variable in the program's application code is treated as an Object-type variable. That's why passing on a variable's value as a function call parameter requires type casting or conversion (as long as that function expects an argument type other than Object). This requirements also applies to passing on the null value.

In order to place the $ character in the application code you have to enter

$$

Starting from version 6.2.10 of jPALIO special characters can be entered using the format

$\SPECIAL_CHARACTER

so, the dollar sign can be entered as

$\$

Comments

There are 2 types of comments. A comment that starts with the string of characters $// and ends at the end of a line of text

$// comment

A comment that is placed between the string of characters $/* and the string of characters $*/ and which can cover any number of text lines

$/*
comment
$*/

Operators

There are many different operators defined in the jPALIO system

  • arithmetic operators
+  add operator (dyadic)
–  subtract operator (dyadic)
*  multiple operator (dyadic)
/  divide operator (dyadic)
%  division remainder operator (dyadic)
++ increment operator (unary)
–– decrement operator (unary)
  • logical operators
&& logical AND (dyadic)
|| logical OR (dyadic)
!  logical NOT (unary)
== logical Equal To (dyadic)
!= logical Not Equal To (dyadic)
<> logical Not Equal To (dyadic)
<  logical Less Than (dyadic)
<= logical Less Than or Equal To (dyadic)
>  logical Greater Than (dyadic)
>= logical Greater Than or Equal To (dyadic)
  • bit operators
&  bitwise AND (dyadic)
|  bitwise OR (dyadic)
^  bitwise XOR (dyadic)
~  bitwise NOT (unary)
  • other
=  assignment operator (dyadic)
+  character strings concatenation operator (dyadic)
?  conditional expression operator (ternary)

Methods of usage of operators

$operator(arguments)

Apart from its dyadic version the character strings concatenation operator also has the unary version, where the argument is a character string array and the result of operation is concatenation of all characters from this array.

$+([string1, string2, string3, ... ])

Apart from their dyadic versions logical AND and OR operators also have their unary versions, where the argument is a logical expressions array and the result of operation is the logical product and logical sum of all expressions from the array, respectively.

Apart from its dyadic version the divide operator also has its ternary version, where the third argument defines required precision of the operation (number of digits after the point).

Operators are short notations of calls to particular functions and during compiling they are replaced by calls to specific functions

+  add function
–  subtract function
*  multiply function
/  divide function
%  remainder function
++ increment function
–– decrement function
&& and function
|| or function
!  not function
== equals function
!= notEquals function
<> notEquals function
<  lesser function
<= lesserOrEquals function
>  bigger function
>= biggerOrEquals function
&  bitwiseAnd function
|  bitwiseOr function
^  bitwiseXor function
~  bitwiseNot function
=  setParam function
?  condition function

So, for example, a call

$+(2, 7)

is equivalent to

$add(2, 7)

Examples

$// Set variable z to value 5
$=(z, 5)
$// Increase z variable's value by 1
$++(z)
$// Collect variable's value z and place it in HTML code
$z
$// Calculate expression ((24 + 76) * 8.99) and place in HTML code
$*($+(24, 76), 8.99)
$// Set variable x to value 7
$=(x, 7)
$// Set variable y to value of variable x divided by 14 
$// with precision up to 1 place after the point
$=(y, $/((Long)$x, 14, 1))
$// Assign character string "def" to variable t
$=(t, "def")
$// Concatenation of character strings "abc" and "def" and placing the result in HTML code
$+("abc", "def")
$// Concatenation of character string "abc" and character strong saved in variable t and
$// writing the result again to variable t
$=(t, $+("abc", (String)$t))
$// Assign variable s with character string that is the result of concatenation
$// of character strings "abc", "def" and "ghi"
$=(s, $+(["abc", "def", "ghi"]))
$// Set variable b to value true
$=(b, true)
$// Calculate logical expression (~b) and place it in HTML code
$!((Boolean)$b)
$// Calculate logical expression (b || (true && ~b)) and place it in HTML code
$||((Boolean)$b, $&&(true, $!((Boolean)$b))) 
$// Set variable i to value 3
$=(i, 3)
$// Place letter P in HTML code if variable i has even value
$// or letter N if variable i has odd value
$?($==($%((Long)$i, 2), 0), "P", "N")
$// Set variable today to current date
$=(today, sysdate)
$// Set variable s to the number of seconds that passed since the beginning of 2005 until now
$=(s, $-((Date)$today, 01-01-2005 00:00:00))
$// Place in HTML code the number of seconds that passed since the beginning of 2005 until now
$toLong($/((Long)$s, 86400))
$// Set variable tab2D to the value array [[1,2,3], ["A","B"]]
$=(tab2D, [[1, 2, 3], ["A", "B"]])
$// Set variable tab1D to the second of arrays of array tab2D
$=(tab1D, (Object[])$tab2D[1])
$// Place in HTML code the first element of array tab1D
$tab1D[0]

Control instructions

3 types of control instruction have been defined

if – execution of an operation if a particular condition is met
for – execution of an operation a number of times in a loop
try – execution of an operation with exception handling

If instruction

The if instruction can be used in two ways

$if(condition, { 
  codeOnTrue
})

where

condition – Boolean type condition
codeOnTrue – a set of instructions executed, when condition is true

or

$if(condition, { 
  codeOnTrue
}, {
  codeOnFalse
})

where

condition – Boolean type condition
codeOnTrue – a set of instructions executed, when condition is true
codeOnFalse – a set of instructions executed, when condition is false

Examples

$// Set variable condition to value true
$=(condition, true)
$if((Boolean)$condition, {
  $// Place header in HTML code if variable condition has value true
  <h3>Header's content</h3>
})
$// Set variable x to value 5
$=(x, 5)
$if($==((Long)$x, 7), {
  $// Set variable y to value 0 if variable x has value 7
  $=(y, 0)
}, {
  $// Set variable y to value 3 if variable x has value other than 7
  $=(y, 3)
})
$// Place value of variable y in HTML code
$y

For instruction

The for instruction has 4 structures

$for(loopCount, {
  loopCode
})

where

loopCount – number of iterations
loopCode – a set of instruction executed in each of the loopCount iterations of the loop

or

$for(conditionParamName, { 
  loopCode 
})

where

conditionParamName – variable's name
loopCode – a set of instructions executed in a loop until the conditionParamName variable 

has value true

or

$for(paramName, loopTable, {
  loopCode
})

where

paramName – variable's name
loopTable – Object[]-type array
loopCode – a set of instructions executed for each element of the loopTable array; at each loop iteration a single element of the loopTable array will be assigned to the paramName variable

or

$for(paramName, loopList, {
  loopCode
})

where

paramName – variable's name
loopList – LinkedList-type list
loopCode – a set of instructions executed for each element from the loopList list; at each loop iteration a single row of the loopList list will be assigned to the paramName variable; a single row of the loopList list is the Object[]-type array

Examples

$// Set variable Cnt to value 1
$=(Cnt, 1)
$// Execute the instruction set 7 times
$for(7, {
  $// Place value of variable Cnt in HTML code
  $Cnt
  $// Increase Cnt variable's value by 1
  $++(Cnt)
})
$// Set variable Ctr to value 1
$=(Ctr, 1)
$// Set variable loop to value true
$=(loop, true)
$// Execute a set of instruction if variable loop is true
$for(loop, {
  $// Place value of variable Ctr in HTML code
  $Ctr
  $// Increase Ctr variable's value by 1
  $++(Ctr)
  $// Set variable loop to value false if variable Ctr takes value bigger than 4
  $if($>((Long)$Ctr, 4), { $=(loop, false) })
})
$// Assign value array ["html","xml","txt"] to variable extensions
$=(extensions, ["html","xml","txt"])
$// Execute a set of instructions for each of the elements from the extensions array
$for(i, $extensions[], {
  $// Place value of current element of table extensions in HTML code
  $i
})
$// Set variable users to the result of execution of SQL query,
$// that collects the list of rows from table p_users
$=(users, $sql.read("select id, login from p_users order by login"))
$// Execute a set of instructions for each row of list users
$for(i, (LinkedList)$users, {
  $// Place values of elements of the current row of list users in HTML code
  $// (the first of elements is id, and the second is login)
  $i[0] $i[1]
})

Try instruction

The try instruction has 2 structures

$try({
  tryCode
}, {
  catchCode
})

where

tryCode – a set of instruction, which when attempted to execute can trigger an exception
catchCode – a set of instructions that handle an exception

or

$try({
  tryCode
}, {
  catchCode
}, {
  finallyCode
})

where

tryCode – a set of instruction, which when attempted to execute can trigger an exception
catchCode – a set of instructions that handle an exception
finallyCode – a set of instructions executed at the end, regardless of whether in the try block there was an exception and regardless of whether it was handled

Examples

$try({
  $// Divide by zero instruction causes an exception
  $// and transfer of control to exception handling block
  $/(7, 0)
}, {
  $// Place information about attempt to divide by zero in HTML code
  Attempt to divide by zero!
})  
$try({
  $// Attempt to open file for writing
  $=(WRITER, $pipe.openWriter("/tmp/text.txt", "FILE", "ISO-8859-2"))
  $// Attempt to write to file
  $pipe.write((java.io.Writer)$WRITER, "TEXT")
}, {
  $// Display error message
  $error.getMessage()
}, {
  $// Attempt to close file
  $try({ $pipe.closeWriter((java.io.Writer)$WRITER) }, {})
})

jPALIO instruction sets

Instruction sets (SuperPALIO language) have been introduced in order to speed up and facilitate creation of instruction call sequences. An instruction set looks like this

${
  a string of SuperPALIO instructions
}

where each instruction within a string of instructions (except for the last one) must end with a semicolon. Any number of white characters can be placed between all instructions and operators.

Inside an instruction set (written in SuperPALIO) one can also put jPALIO instructions. The structure for this purpose looks like this

$(
  jPALIO instruction string
);

Formats of expressions in the instruction string

  • assigning the expression's value to a variable
variable_name = expression;
  • inputting the expression's value into a specific position of an array
variable_name [index] = expression;
  • placing the expression's value in HTML code
expression;

Components of expressions

  • values of constants
null
false
true
-19
0.001
"text"
  • values of variables
(type_name)variable_name
variable_name[] or (Object[])variable_name
(type_name)variable_name[index]
  • values of functions
(type_name)module_name.function_name(arguments)
(type_name)function_name(arguments)
  • expression arrays
[expression1, expression2, ... ]
[]
  • arithmetic operators
expression1 + expression2
expression1 - expression2
expression1 * expression2
expression1 / expression2
  • relational operators
expression1 || expression2
expression1 && expression2
! expression
  • logical operators
expression1 == expression2
expression1 != expression2
expression1 <> expression2
expression1 < expression2
expression1 <= expression2
expression1 > expression2
expression1 >= expression2
  • concatenation operator
expression1 + expression2
  • conditional expression operator
condition ? expression1 : expression2
  • parenthesis to determine the sequence of operations
(expression)

In case of logical operations all component types are automatically converted into Boolean. Any errors are then returned dynamically - not at compilation time.

Argument types of add and subtract operators are matched one by one according to particular conditions. If one of the matches works, the subsequent ones are not checked. Matching conditions

  • if an operation involves exactly two components and there is no negation operator with the first component, then the complier will convert the expression into add or subtract function; users have to match component types and argument types of those functions themselves
  • if the operation involves more than two components or there is a negation operator with the first component and all arguments are of the Long type, the returned value will of the Long type; jPALIO's internal function is used
  • if all arguments are of the Long or BigDecimal type, the returned value will be of the BigDecimal type; jPALIO's internal function is used
  • if all components are added then arguments can be of any type; all arguments are cast to the String type and concatenated using the add function
  • the no match error is returned

Argument types of multiply and divide operators are matched one by one according to particular conditions. If one of the matches works, the subsequent ones are not checked. Matching conditions

  • if an operation involves exactly two components, then the complier will convert the expression into multiple or divide function; users have to match component types and argument types of those functions themselves
  • if all components are multiplied and are of the Long type, the returned value is also of the Long type; jPALIO's internal functions is used
  • if all arguments are of the Long or BigDecimal type, the returned value is also of the BigDecimal type; jPALIO's internal function is used
  • the no match error is returned

In case of the array read operator, the index role can be played by any expression - there is automatic conversion of the index type to the Long type. Left-side expression is automatically converted into the Object[] type.

The term component used above means an expression with higher priority level.

Examples

${
  $($/* Assign expression value(5 + 1) to variable a $*/);
  a = 5 + 1;
  $($/* Place value of variable a in HTML code $*/);
  a;
  $($/* Place the string of characters <br> in HTML code $*/);
  "<br>";
  $($/* Assign expression value(19 - 6 * 2) to variable b $*/);
  b = 19 – (Long)a * 2;
  $($/* Place the record b - 4 = 3 that ends with the <br> tag in HTML code $*/);
  "b – 4 = " + ((Long)b – 4) + "<br>"
}
$// Place value of variable b in HTML code
$// if it is called from outside of the instruction set
$b
${
  $($/* Assign value array [1, 1, 2, 3, 5]) to variable t $*/);
  t = [1, 1, 2, 3, 5];
  $($/* Assign the number of elements in the array t to variable i $*/);
  i = tableLen(t[]);
  $($/* Add to the table t an element that is the sum of two last elements from this table $*/);
  addParam("t", (Long)t[(Long)i – 1] + (Long)t[(Long)i – 2]);
  $($/* Place the array of all values from the table t in HTML code $*/);
  t[];
}
${
  $($/* Assign value 0 to variable sum $*/);
  sum = 0;
  $($/* Calculate the sum of absolute values of numbers from the array [4, -7, 2] $*/);
  for("i", [4, –7, 2], {
    if((Long)i < 0, {
      sum = (Long)sum – (Long)i;
    }, {
      sum = (Long)sum + (Long)i; 
    });
  });
  $($/* Place the record |4| + |–7| + |2| = 13 in HTML code $*/);
  "|4| + |–7| + |2| = " + sum;
}

JAVA instruction sets

jPALIO platform also enables creation of instruction sets in the JAVA language. An instruction set will look like this

$[
  a set of instruction in the JAVA language
]

Example

$[
  // Reference to the current object
  Current current = Instance.getCurrent();

  // Write to the page's source
  current.getWriter().println("<h3>Hello, World!</h3>");

  // Set jPALIO parameter
  current.setParam("_TestParam", Long.valueOf(200));

  // Retrieve external jPALIO parameter
  Long _TestParam = (Long)current.getParam("_TestParam")[0];
  current.getWriter().println("_TestParam = " + _TestParam + "<br>");

  // Loop
  for (int i = 0; i < 10; i++) 
  {
    current.getWriter().println(i +"<br>");
  }

  // Class definition
  class SpecialFunction
  {
    public double sinh(double x)
    {
      return ((java.lang.Math.exp(x) - java.lang.Math.exp(-x))/2.0);
    }
  }

  SpecialFunction f = new SpecialFunction();
  current.getWriter().println("sinh(2.5) = " + f.sinh(2.5) + "<br>");
]

$// Call outside of the instruction set to the parameter value set inside this instruction set
_TestParam = $_TestParam

From JAVA instruction sets You can call jPALIO objects:

palio.Groovy.object(ID_OBIEKTU)
palio.Groovy.object(ID_OBIEKTU, new Object[] {PARAMETR1, PARAMETR2, PARAMETR3, ...})
palio.Groovy.object(KOD_OBIEKTU)
palio.Groovy.object(KOD_OBIEKTU, new Object[] {PARAMETR1, PARAMETR2, PARAMETR3, ...})

Objects

Objects contain application control code. Once an object is created it can be used multiple times. Invoking an object from inside of another object or from inside of the same object (recurrently) will look like this

$*object_identifier

or

$*object_code

in case of no parameter objects, and

$*object_identifier(parameter1, parameter2, ... )

lub

$*object_code(parameter1, parameter2, ... )

for objects invoked with parameters, where object_identifier is a unique number assigned automatically to each object when it is created, and object_code is a unique string of characters assigned to each object by users. The object code's first character must be a letter or the underscore character, subsequent characters can be digits or a point, after the point there must be a letter or the underscore character. The same rule applies to creating of page codes, media and elements of hierarchical type structure.

A call within an object to the value of any parameter of its invoking will look like this

$parameter_no

or (in case of parameters that are value arrays)

$parameter_no[]

whereas, parameters are numbered from 0, so $0 means the value of the first parameter ($0[] if the first parameter is an array), $1 - the value of the second parameter ($1[] if the second parameter is an array), etc.

Object call parameters exist only while this object is being executed and are not visible outside of this object.

Variables set before invoking the object are visible inside this object and can be modified by it.

Variables set inside the object remain visible in the application code also after invoking this object.

For example, let an object with the identifier 1 have the following contents

Call to object 1<br>
$=(z1, 11)
Set value of variable z1 in object 1 to $z1<br>
$*2("PAR112", "PAR212")
<br>Return to object 1<br>
Variable z1 in object 1 has value $z1<br>
Variable z2 in object 1 has value $z2<br>
Variable z3 in object 1 has value $z3<br>

and an object with the identifier 2 have the following content

<br>Call to object 2<br>
$try({ $=(p1, $+("has value ", (String)$0)) }, { $=(p1, "does not exist") })
$try({ $=(p2, $+("has value ", (String)$1)) }, { $=(p2, "does not exist") })
$try({ $=(p3, $+("has value ", (String)$2)) }, { $=(p3, "does not exist") })
The first object 2 call parameter $p1<br>
The second object 2 call parameter $p2<br>
The third object 2 call parameter $p3<br>
Variable z1 in object 2 has value $z1<br>
$=(z1, 21)
$=(z2, 22)
Change of value of variable z1 in object 2 to $z1<br>
Set value of variable z2 in object 2 to $z2<br>
$*3("PAR123")
<br>Return to object 2<br>
Variable z1 in object 2 has value $z1<br>
Variable z2 in object 2 has value $z2<br>
Variable z3 in object 2 has value $z3<br>

and an object with the identifier 3 have the following content

<br>Call to object 3<br>
$try({ $=(p1, $+("has value ", (String)$0)) }, { $=(p1, "does not exist") })
$try({ $=(p2, $+("has value ", (String)$1)) }, { $=(p2, "does not exist") })
$try({ $=(p3, $+("has value ", (String)$2)) }, { $=(p3, "does not exist") })
The first object 3 call parameter $p1<br>
The second object 3 call parameter $p2<br>
The third object 3 call parameter $p3<br>
Variable z1 in object 3 has value $z1<br>
Variable z2 in object 3 has value $z2<br>
$=(z1, 31)
$=(z2, 32)
$=(z3, 33)
Change of value of variable z1 in object 3 to $z1<br>
Change of value of variable z2 in object 3 to $z2<br>
Set value of variable z3 in object 3 to $z3<br>

Invoking the object with the identifier 1 from the above example will generate the following record in HTML code

Call to object 1
Set value of variable z1 in object 1 to 11

Call to object 2
The first object 2 call parameter has value PAR112
The second object 2 call parameter has value PAR212
The third object 2 call parameter does not exist
Variable z1 in object 2 has value 11
Change of value of variable z1 in object 2 to 21
Set value of variable z2 in object 2 to 22

Call to object 3
The first object 3 call parameter has value PAR123
The second object 3 call parameter does not exist
The third object 3 call parameter does not exist
Variable z1 in object 3 has value 21
Variable z2 in object 3 has value 22
Change of value of variable z1 in object 3 to 31
Change of value of variable z2 in object 3 to 32
Set value of variable z3 in object 3 to 33

Return to object 2
Variable z1 in object 2 has value 31
Variable z2 in object 2 has value 32
Variable z3 in object 2 has value 33
Return to object 1
Variable z1 in object 1 has value 31
Variable z2 in object 1 has value 32
Variable z3 in object 1 has value 33

With version 5.0.0 of jPALIO the instruction for returning the value by an object was introduced. The return instruction causes an immediate exit from code / object with the return of a value. Everything that is located after the return instruction will not be executed

$return("VALUE")

The returned value can be retrieved

$@=(RESULT, (String)$*OBJECT_IDENTIFIER_OR_CODE)

It is also possible to exit the code without returning a value

$return()

If the exit instruction is executed inside a loop, iteration is interrupted and the program exits from the object. This behaviour applies to the majority of the embedded code in the object (loops, conditional instructions, etc.). The only exception are all methods of the $palio.execute...() type. Usage of the exit instruction inside this method interrupts execution of this code only (not the whole object). Because of this all of those methods now return a value (usually null, if execution of the code was not interrupted). The method $palio.executeToBuffer returns exit (any value returned inside the code is lost). A method that invokes the code in another thread does not return a value (exit is logged, any returned value is lost).

In version 5.0.0 of jPALIO we have introduced an instruction that imports JAVA types and packages. Import of a specific type for quicker future use

$#import(palio.pelements.PObject)

Import of a whole package (when mapping exact readings are checked first and the packages are checked later)

$#import(palio.pelements.*)

Local variables

With version 5.0.0 of jPALIO we have introduced local variables. Names of local variables are preceded with @ character. Local variables can be used without a threat of being overwritten by another object or by a recurring call of the same object

$@=(text, "She has got a cat")
Text: $@text

Local variables have statically stored types based on the first assignment. So, one can re-assign values but only of the same type - the stored type is provided for each usage of the variable (casting is not required)

$@=(value, 2)
2+2 = $+($@value, $@value)

In order for a more detailed type to be stored, one should cast with the first assignment

$=(ID, 7)
$@=(ID, (Long)$ID)
$@ID

A special instruction allows to quickly assign object call parameters to local variables together with type storage

$#params(Long id, String action, Object[] parameters)

which is equivalent to

$@=(id, (Long)$0)
$@=(action, (String)$1)
$@=(parameters, $2[])

Methods can be invoked for the benefit of local variables

$@=(text, "She has got a cat")
Text: $@text <br/>
Length: $@text.length() <br/>
Has she got a cat? $@text.contains("cat") <br/>

All errors related to invoking of methods are trapped at compiling time because local variable types are known.

Local variables can also be used in SuperPALIO code

${
  @text = "She has got a cat";
  "Text: "; $@text; "<br/>";
  "Length of text: "; @text.length(); "<br/>";
  @value = 2; 
  "2+2 = "; ($@value + $@value);
}

Starting with version 6.2.10 of jPALIO the @ character became part of the local variable's name. As the result (ensuring compatibility with previous versions) the records

$@=(variable, value)
$@=(@variable, value)
$=(@variable, value)

became equivalent. However, it is recommended to use the following format

$=(@variable, value)

Invoking $getParam("variable") means calling a global variable, and invoking $getParam("@variable") means calling a local variable.

Modules

Modules are sets of functions invoked from the application code. Each module must be a palio.modules.Module class derivative and must be located in the palio.modules package. Functionality of jPALIO modules is described in the following table

MODULE FUNCTIONALITY
Admin a set of functions to manage an instance and a set of information functions
Ads* a set of functions to operate an ads server
Bar a set of functions to generate barcodes
Beans* a set of functions to access class objects written in compliance with the JavaBeans specification
BugBase a set of functions to handle the error database
Cache a set of functions to buffer frequently used data in the system
Cert a set of functions to handle certificates
Chart a set of functions to draw charts
CMS* a set of functions to create CMS
Crypto a set of cryptographic functions
Disk a set of functions to access disk files
Editor* a set of functions to integrate the TinyMCE editor with jPALIO
Error a set of functions to handle exceptions
Ezop* a set of functions used to build internet shops
Forum* a set of functions to create discussion forums
FTP a set of functions to communicate with an FTP server
Global a set of functions to handle global variables
Hetman a set of functions that support creation and implementation of processes (workflow)
History a set of functions to record the history of changes to the contents of database tables
HTML a set of functions that facilitate work with HTML code
Imager a set of functions to perform operations on images
IText a set of functions to generate PDF files
Lang a set of functions that support building of multi-language portals
Ldap a set of functions to communicate with LDAP servers
Log a set of functions to create log records
Logic a set of basic logical operators
Mail* a set of functions to send messages using the electronic mail
Mapper a set of functions to create maps
Media a set of functions to handle multimedia objects
Mth a set of mathematical functions
Net a set of functions to perform network operations
Newser a set of functions to handle news
Newsletter* a set of functions to distribute e-mail messages to subscribers
Page a set of functions to handle pages, build internet addresses and redirections, to perform operations related to the HTTP header
Palio a set of basic functions of the jPALIO system
Pipe a set of functions to perform operations on streams
Proc a set of functions to create and handle business processes
Reflect a set of functions that support programming in the JAVA language
Remote a set of functions to remotely invoke functions
Report* a set of functions that support creation of reports
Scheduler* a set of functions to schedule periodic tasks performed automatically by jPALIO
SearchUtils a set of functions for advanced text searching
SNMP a set of functions that support network management
Sql a set of functions to communicate with databases
Std a set of standard functions that facilitate building of sites
Text a set of functions to perform operations on characters strings
Time a set of functions that support execution of operations related to time and date
UrlModule* a set of functions to generate URLs for PALIO
User a set of functions that enable management of users, roles and sessions
Util a set of utility functions
VirtualTable a specialized applet that builds a virtual table to use by all users for common writing and drawing
XLS a set of functions to generate XLS files
Xml a set of functions to process files in XML format

For modules marked with * a record in the instance's configuration file is required.

Functions

Call to a function from a specific module

$module_name.function_name(arguments)

Letter size in the module's name is irrelevant.

In case of Logic, Mth, Page, Palio, Std, Text and Util modules it is not required to precede the function's name with the module's name - the record is streamlined into

$function_name(arguments)

The full documentation of all functions is available at the address

http://docs.torn.com.pl/jPalio/modules/

Integration with Groovy

With version 6.0.0. of jPALIO we introduced the ability to create application code using the groovy language.

In a groovy-written object that is associated with a page, the access to HTTP parameters is ensured by the params map.

In a groovy-written object that is called from the other object, the access to call arguments is ensured by the args array.

The groovy language offers the ability to declare classes. In this case the object contains a full class declaration

package PACKAGE_NAME;

class CLASS_NAME
{
  ...
}

An object, in which the above declaration is written, must have the code PACKAGE_NAME.CLASS_NAME. You can use groovy-written classes in groovy code only. Each class must be defined in a separate jPALIO object.

// Class definition within the object coded toys.balls.Ball
package toys.balls

class Ball 
{
  public Ball(color, size) 
  {
    this.color = color
    this.size = size
  }

  public printBallData () 
  {
    return "${color} ball of size ${size}"
  }

  def color, size
}

A call to the jPALIO object from a groovy object will look like this

import palio.Groovy

Groovy.object(OBJECT_IDENTIFIER)
Groovy.object(OBJECT_IDENTIFIER, (Object[])[PARAMETER1, PARAMETER2, PARAMETER3, ...])
Groovy.object(OBJECT_CODE)
Groovy.object(OBJECT_CODE, (Object[])[PARAMETER1, PARAMETER2, PARAMETER3, ...])

A call to the groovy object from a jPALIO object will look like this

$*OBJECT_IDENTIFIER
$*OBJECT_IDENTIFIER(PARAMETER1, PARAMETER2, PARAMETER3, ...)
$*OBJECT_CODE
$*OBJECT_CODE(PARAMETER1, PARAMETER2, PARAMETER3, ...)

A call in groovy from jPALIO modules to a function will look like this

import palio.Groovy
Groovy.module("MODULE_NAME").FUNCTION_NAME()
Groovy.module("MODULE_NAME").FUNCTION_NAME(ARGUMENT1, ARGUMENT2, ARGUMENT3, ...)

or

import palio.Groovy
MODULE_NAME = Groovy.module("MODULE_NAME")

MODULE_NAME.FUNCTION_NAME()
MODULE_NAME.FUNCTION_NAME(ARGUMENT1, ARGUMENT2, ARGUMENT3, ...)

The following function is used to invoke functions from jPALIO modules in groovy (functions that take arguments of the PalioCode type)

PalioCode palio.Groovy.asPalioCode(Closure closure)

Example

import palio.Groovy
Groovy.module("sql").transaction(palio.Groovy.asPalioCode({
  
  code in the groovy language
  
}))

Just as jPALIO objects the groovy objects can also return values

return("VALUE")

Examples

Using basic functions

<html>
<head>
  <title>jPALIO</title>
  $// Place coding declaration in HTML file source
  $html.contentMeta()
</head>

<body>
  $// Assign value to variable VAR
  $=(VAR, 1234567)
  $// List value of variable VAR
  Zmienna <b>VAR</b> ma wartość <b>$VAR</b><br>
  $// List result of the expression (VAR % 7)
  The division remainder of variable <b>VAR</b> by <b>7</b> is <b>$%((Long)$VAR, 7)</b><br>
  $// Assign result of the expression (VAR - 1234456) to variable VAR
  $=(VAR, $–((Long)$VAR, 1234456))
  $// List value of variable VAR
  After subtracting <b>1234456</b> from the value of variable <b>VAR</b> it has the value <b>$VAR</b><br>
  $// List result of the expression (VAR / (-2.5))
  The result of dividing the variable <b>VAR</b> by <b>-2.5</b> with precision up to 1 place after the point is <b>$/((Long)$VAR, -2.5, 1)</b><br><br>

  $// Assign current date and time on server to variable NOW
  $=(NOW, sysdate)
  $// List date in format day.month.year
  Date <b>$toString((Date)$NOW, "dd.MM.yyyy")</b><br>
  $// WList time in format hour:minutes:seconds
  Time <b>$toString((Date)$NOW, "HH:mm:ss")</b><br>
  $// List client's IP address
  Client's IP address <b>$net.getClientIP()</b><br><br>

  $// Assign value array to a variable TABLE
  $=(TABLE, ["j", "P", "A", "L", "I", "O"])
  Elements of the table <b>TABLE</b>:
  $// Set counter CTR to start value 0
  $=(CTR, 0)
  $// Set the number of elements of table TABLE to variable TL
  $=(TL, $tableLen($TABLE[]))
  $// Loop through all elements of table TABLE
  $for(i, $TABLE[], {
    $// Check if the analyzed element of table TABLE is not the last element,
    $// if yes - list the value of this element and the point, if not - list only the value of this element
    $if($<((Long)$CTR, $–((Long)$TL, 1)), { <b>$i</b>, }, { <b>$i</b> })
    $// Increase CRT counter's value by 1
    $++(CTR)
  })
  <br><br>

  $// Concatenation and processing of character strings
  The result of concatenation of character strings <b>m</b>, <b>~SS~SS~</b> and <b>ppI</b>, where small letters were replaced by capital letters and the character <b>~</b> with letter <b>i</b> is <b>$replace($toUpper($+(["m", "~SS~SS~", "ppI"])), "~", "i")</b><br><br>

  $// List the character $
  Character <b>$$</b><br><br>

  $// Create a link to the home page
  <a href="$pageURL($defaultPageID())">home page</a>
</body>
</html> 

Upload of SWF files (PostgreSQL)

$/*
  In order for this example to work properly it is necessary to create in the PostgreSQL database
  the following table and sequence
  
  create table flash
  (
    id numeric(12) not null constraint fla_pk primary key,
    width numeric(3) not null,
    height numeric(3) not null,
    file_name varchar(250) not null,
    file_size numeric(12) not null,
    file_mime_type varchar(100) not null,
    file_content bytea,
    created timestamp not null
  );
  
  create sequence flash_s start 1;
$*/

$// Check if the form was sent, if yes - process data from the form
$ifNotNull($flash_add, {
  $// Check if the file was sent,
  $// if yes - process data from the form,
  $// if no - report error
  $if($&&([$isNotNull($flash_content[1]), $isNotNull($flash_content[2]), $isNotNull($flash_content[3])]), {
    $// Check if the sent file is in SWF format,
    $// if yes - try to save data from the form to database,
    $// if no - report error
    $if($==($toLower($toString($flash_content[3])), "application/x-shockwave-flash"), {
      $// Attempt to save data from the form to database with exception handling
      $// and report error if unsuccessful
      $try({
        $// Start of transaction
        $sql.transaction({
          $// Retrieve next value from the sequence that generates file identifiers
          $=(flash_id, $sql.getSequence("flash_s"))
          $// Save file to database
          $sql.write("insert into flash (id, width, height, file_name, file_size, file_mime_type, file_content, created) values (?, ?, ?, ?, ?, ?, ?, now())",
          [$flash_id, $flash_width, $flash_height, $flash_content[1], $flash_content[2], $flash_content[3], (byte[])$flash_content])
        })
        $// Store message on the success of save-to-database operation
        $=(_Info, "The file was saved in the database")
        $// Delete values of variables that store data from the form
        $=(flash_width, null)
        $=(flash_height, null)
      }, {
        $// Store message on the failure of save-to-database operation
        $=(_Error, "Attempt to save the file to database failed")
      })
    }, {
      $// Store message on the reason of failure of save-to-database operation
      $=(_Error, "Improper file format")
    })
  }, {
    $// Store message on the reason of failure of save-to-database operation
    $=(_Error, "No file")
  })
})

$// Display message on the failure of save-to-database operation
$ifNotNull($_Error, { <center><b style="color:red">$_Error</b></center> })

$// Display message on the success of save-to-database operation
$ifNotNull($_Info, { <center><b>$_Info</b></center> })

$// Create file upload form
$html.createUploadForm("flash_form","flash_form", $pageURL($currentPage()), "field", "button", {
  <table cellspacing=1 cellpadding=1 border=0 align=center>
  <tr><td colspan=2 align=right><b>Add file</b></td></tr>
  <tr>
    <td>width</td>
    $// Create text field to input width
    <td>$html.textField("flash_width", (String)$flash_width, 3, false, "WIDTH", "/^[1-9]\d*$/", "size=40") px</td>
  </tr>
  <tr>
    <td>height</td>
    $// Create text field to input height
    <td>$html.textField("flash_height", (String)$flash_height, 3, false, "WYSOKOŚĆ", "/^[1-9]\d*$/", "size=40") px</td>
  </tr>
  <tr>
    <td>file</td>
    $// Create text field to input file
    <td><input type="file" name="flash_content" size="40"></td>
  </tr>
  $// Create button to send form
  <tr><td colspan=2 align=right>$html.submitButton("flash_add", "Add")</td></tr>
  </table>
}, {
  $// Form validation code
  if (form.flash_width.value=="") error+="\n- the WIDTH field cannot be empty";
  if (form.flash_height.value=="") error+="\n- the HEIGHT field cannot be empty";
  if (form.flash_content.value=="") error+="\n- the FILE field cannot be empty";
})
Personal tools