Merge remote-tracking branch 'manage/master' into subtree

this merges master branch of https://github.com/helma-org/apps-manage-mirror into helma
This commit is contained in:
Simon Oberhammer 2012-03-27 11:47:36 +02:00
commit ca2b08a5df
58 changed files with 2678 additions and 0 deletions

View file

@ -0,0 +1,67 @@
/**
* renders AppManager
*/
function main_action() {
if (checkAddress() == false)
return;
if (checkAuth(this) == false)
return;
res.data.body = this.renderSkinAsString("main");
renderSkin("global");
}
/**
* prints session- and thread-stats for mrtg-tool
* doesn't check username or password, so that we don't have
* to write them cleartext in a mrtg-configfile but checks the
* remote address.
*/
function mrtg_action() {
if (checkAddress() == false)
return;
if (this.isActive() == false) {
res.write("0\n0\n0\n0\n");
return;
}
if (req.data.action == "sessions") {
res.write(this.sessions.size());
res.write("\n0\n0\n0\n");
} else if (req.data.action == "threads") {
res.write(this.countActiveEvaluators() + "\n");
res.write(this.countEvaluators() + "\n");
res.write("0\n0\n");
} else if (req.data.action == "cache") {
res.write(this.getCacheUsage() + "\n");
res.write(this.getProperty("cachesize", "1000") + "\n");
res.write("0\n0\n");
} else if (req.data.action == "requests") {
// res.write (
} else {
res.write("0\n0\n0\n0\n");
}
}
/**
* performs a redirect to the public site
* (workaround, we can't access application object from docapplication for some reason)
* @see application.url_macro
*/
function redirectpublic_action() {
if (checkAddress() == false) return;
if (checkAuth(this) == false) return;
res.redirect(this.url_macro());
}

View file

@ -0,0 +1,42 @@
/**
* construct an application object so that we can use
* skins for non-active applications too
* @arg name
*/
function constructor(name) {
this.name = name;
}
/**
* return true/false to determine if application is running
*/
function isActive() {
if (root.getApplication(this.name) == null)
return false;
else
return true;
}
/**
* Method used by Helma for URL composition.
*/
function href(action) {
var base = root.href() + this.name + "/";
return action ? base + action : base;
}
/**
* Method used by Helma for URL composition.
*/
function getParentElement() {
return root;
}
/**
* Method used by Helma request path resolution.
*/
function getChildElement(name) {
if (name == "api")
return this.getDoc();
return null;
}

View file

@ -0,0 +1,11 @@
<p><big>AppManager <% this.title %></big>
<% this.description prefix="<br/>" %>
<br/>
-&gt;
<a href="<% this.href action="api" %>/read">showAPI</a> |
<a href="<% this.href action="api" %>/render">renderAPI</a> |
<a href="<% this.url %>">public</a> |
<a href="<% root.href action="main" %>?app=<% this.title %>&action=flush">flush</a> |
<a href="<% root.href action="main" %>?app=<% this.title %>&action=restart">restart</a> |
<a href="<% root.href action="main" %>?app=<% this.title %>&action=stop">stop</a>
</p>

View file

@ -0,0 +1,210 @@
/**
* macro rendering a skin
* @param name name of skin
*/
function skin_macro(par) {
if (par && par.name) {
this.renderSkin(par.name);
}
}
/**
* macro-wrapper for href-function
* @param action name of action to call on this prototype, default main
*/
function href_macro(par) {
return this.href((par && par.action) ? par.action : "main");
}
/**
* Macro returning the URL of an application.
* using absoluteURI if set in app.properties, otherwise we go for the href calculated by
* the application (which is using baseURI if set)
*/
function url_macro() {
var str = this.getProperty("absoluteuri");
if (str != null && str != "") {
return str;
} else {
return this.getRootHref();
}
}
/**
* Macro returning the title of an application
*/
function title_macro() {
var title = this.name;
return(title);
}
/**
* Macro rendering a description of an application from a
* file called description.txt or doc.html located in the
* app's root. Limits description to 200 chars.
* @param Object Macro parameter object
*/
function description_macro(param) {
var str = "";
var appHome = this.getAppDir();
var f = new File(this.getAppDir().toString(), "description.txt");
if (!f.exists())
f = new File(this.getAppDir().toString(), "doc.html");
if (f.exists()) {
str = f.readAll();
if (str.length > 200)
str = str.substring(0, 200) + "...";
}
return(str);
}
/**
* Macro returning the server's uptime nicely formatted
*/
function uptime_macro() {
return formatAge((java.lang.System.currentTimeMillis() - this.starttime) / 1000);
}
/**
* Macro returning the number of active sessions.
* parameter used by global.formatCount
* @see global.formatCount
*/
function countSessions_macro(par) {
if (this.isActive() == true)
return this.sessions.size() + formatCount(this.sessions.size(), par);
else
return 0;
}
/**
* Macro returning the number of logged-in users or the list
* of logged-in users if http-parameter showusers is set to true.
* Makes use of this.countUsers_macro and this.listUsers_macro
* @see application.countUsers_macro
* @see application.listUsers_macro
*/
function users_macro(par) {
if (req.data.showusers == "true") {
this.listUsers_macro(par);
} else {
this.countUsers_macro(par);
}
}
/**
* Macro returning the number of logged-in users if application
* is active
* parameter used by global.formatCount
* @see global.formatCount
*/
function countUsers_macro(par) {
if (this.isActive() == true)
return this.activeUsers.size() + formatCount(this.activeUsers.size(), par);
else
return 0;
}
/**
* Macro rendering the list of logged-in users if application is active
* @param separator html-code written between elements
*/
function listUsers_macro(par) {
var separator = (par && par.separator) ? par.separator : ", ";
if (this.activeUsers.size() == 0)
return "";
var users = this.activeUsers.iterator();
while (users.hasNext()) {
res.write(users.next().__name__);
if (users.hasNext()) {
res.write(separator);
}
}
}
/**
* Macro returning the number of active evaluators (=threads)
*/
function countActiveEvaluators_macro() {
return this.countActiveEvaluators();
}
/**
* Macro returning the number of free evaluators (=threads)
*/
function countFreeEvaluators_macro() {
return this.countFreeEvaluators();
}
/**
* Macro returning the current number of objects in the cache
*/
function cacheusage_macro(param) {
return this.getCacheUsage();
}
/**
* Macro returning the number of objects allowed in the cache
*/
function cachesize_macro(param) {
return this.getProperty("cachesize", "1000");
}
/**
* Macro formatting the number of requests in the last 5 minutes
*/
function requestCount_macro(par) {
if (app.data.stat == null || app.data.stat[this.name] == null)
return "not available";
if (this.isActive()) {
var obj = app.data.stat[this.name];
return obj.requestCount + formatCount(obj.requestCount, par);
} else {
return 0 + formatCount(0, par);
}
}
/**
* Macro formatting the number of errors in the last 5 minutes
*/
function errorCount_macro(par) {
if (app.data.stat == null || app.data.stat[this.name] == null)
return "not available";
if (this.isActive()) {
var obj = app.data.stat[this.name];
return obj.errorCount + formatCount(obj.errorCount, par);
} else {
return 0 + formatCount(0, par);
}
}
/**
* Macro formatting app.properties
*/
function properties_macro(par) {
formatProperties(this.getProperties(), par);
}
function repositories_macro(param) {
var repos = this.getRepositories().iterator();
while (repos.hasNext())
res.writeln(repos.next().getName());
}

View file

@ -0,0 +1,62 @@
<% this.skin name="head" %>
<table width="100%" border="0" cellspacing="0" cellpadding="3">
<tr>
<td class="list_separator" colspan="3">application</td>
</tr>
</table>
<table border="0" cellspacing="0" cellpadding="3">
<tr>
<td class="list_property" align="left">active sessions</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.countSessions %></td>
</tr>
<tr>
<td class="list_property" align="left"><a href="<% this.href action="main" %>?showusers=true">logged-in users</a></td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.users %>&nbsp;</td>
</tr>
<tr>
<td class="list_property" align="left">active evaluators</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.countActiveEvaluators %></td>
</tr>
<tr>
<td class="list_property" align="left">free evaluators</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.countFreeEvaluators %></td>
</tr>
<tr>
<td class="list_property" align="left">requests / 5 min</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.requestCount %></td>
</tr>
<tr>
<td class="list_property" align="left">errors / 5 min</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.errorCount %></td>
</tr>
<tr>
<td class="list_property" align="left">cache usage</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.cacheusage %> objects of <% this.cachesize %></td>
</tr>
<tr>
<td class="list_property" align="left">uptime</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.uptime %></td>
</tr>
<tr>
<td class="list_property" align="left" valign="top">repositories</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.repositories %></td>
</tr>
</table>
<table width="100%" border="0" cellspacing="0" cellpadding="3">
<tr>
<td class="list_separator" colspan="3">app.properties</td>
</tr>
<% this.properties itemprefix='<tr><td class="list_property" valign="top">' separator='</td><td class="list_property" width="5">&nbsp;</td><td class="list_property" valign="top">' itemsuffix='</td></tr>' %>
</table>

View file

@ -0,0 +1,18 @@
<div class="list_apps">
<b><a href="<% this.href action="main" %>"><% this.title %></a></b><br />
<small><% this.countSessions singular=" Session" plural=" Sessions" %>,
<% this.requestCount singular=" Request" plural=" Requests" %>/5min</small>
<div align="right">
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td align="right" valign="top"><small style="font-size:9px;">
<a href="<% this.href action="api" %>/read">showAPI</a> |
<a href="<% this.href action="api" %>/render">renderAPI</a> |
<a href="<% this.url %>">public</a> |
<a href="<% root.href action="main" %>?app=<% this.title %>&action=flush">flush</a> |
<a href="<% root.href action="main" %>?app=<% this.title %>&action=restart">restart</a>
</small></td>
</tr>
</table>
</div>
</div>

View file

@ -0,0 +1,10 @@
<div class="list_apps">
<table border="0" cellspacing="0" cellpadding="0" align="right">
<tr>
<td align="right" valign="top"><small>
<a href="<% root.href action="main" %>?app=<% this.title %>&action=start">start</a>
</td>
</tr>
</table>
<b><% this.title %></b>
</div>

View file

@ -0,0 +1,59 @@
function read_action() {
this.readApplication();
res.redirect(this.href("main"));
}
function main_action() {
if (checkAddress() == false)
return;
if (checkAuth(this.getParentElement()) == false)
return;
this.renderSkin("frameset");
}
function prototypes_action() {
if (checkAddress() == false)
return;
if (checkAuth(this.getParentElement()) == false)
return;
res.data.body = this.renderSkinAsString("prototypes");
renderSkin("api");
}
function summary_action() {
if (checkAddress() == false)
return;
if (checkAuth(this.getParentElement()) == false)
return;
res.data.body = this.renderSkinAsString("summary");
renderSkin("api");
}
function functionindex_action() {
if (checkAddress() == false)
return;
if (checkAuth(this.getParentElement()) == false)
return;
res.data.body = this.renderSkinAsString("functionindex");
renderSkin("api");
}
function render_action() {
// set res.data.rendering, this will suppress the link back to the manage
// console in the apidocs actions
res.data.rendering = true;
if (checkAddress() == false)
return;
if (checkAuth(this.getParentElement()) == false)
return;
var ct = this.renderApi();
res.data.body = '<body>rendering API ...<br/>wrote ' + ct + ' files<br/><br/>';
res.data.body += '<a href="' + root.href("main") + '">back to manage console</a>';
res.data.title = "rendering helma api";
res.data.head = renderSkinAsString("head");
renderSkin("basic");
}

View file

@ -0,0 +1,31 @@
<html>
<head>
<title>helma api / <% this.name %></title>
<script language="javascript"><!--
function changePrototypeList (obj) {
if (obj.href.indexOf (".html")>-1)
var newhref = obj.href.substring (0, obj.href.length-9) + "list.html";
else
var newhref = obj.href.substring (0, obj.href.length-4) + "list";
functions.location.href = newhref;
}
//--></script>
</head>
<frameset cols="30%,70%">
<frameset rows="40%,60%">
<frame src="<% this.href action="prototypes" %>" name="prototypes">
<frame src="<% this.hrefRoot action="list" %>" name="functions">
</frameset>
<frame src="<% this.href action="summary" %>" name="main">
</frameset>
<noframes>
<h2>
Frame Alert</h2>
<p>
This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
</noframes>
</html>

View file

@ -0,0 +1,24 @@
<table width="90%" border="0" cellspacing="1" cellpadding="5">
<tr>
<td class="headline">
<big class="top">Application <% this.headline %></tt></b></big><br>
</td>
</tr>
</table>
<a class="navig" href="<% this.href action="summary"%>">SUMMARY</a> |
<a class="navig" href="<% this.href action="functionindex" %>">INDEX</a> |
<a class="navig" href="#A">A</a>|<a class="navig" href="#B">B</a>|<a class="navig" href="#C">C</a>|<a class="navig" href="#D">D</a>|<a class="navig" href="#E">E</a>|<a class="navig" href="#F">F</a>|<a class="navig" href="#G">G</a>|<a class="navig" href="#H">H</a>|<a class="navig" href="#I">I</a>|<a class="navig" href="#J">J</a>|<a class="navig" href="#K">K</a>|<a class="navig" href="#L">L</a>|<a class="navig" href="#M">M</a>|<a class="navig" href="#N">N</a>|<a class="navig" href="#O">O</a>|<a class="navig" href="#P">P</a>|<a class="navig" href="#Q">Q</a>|<a class="navig" href="#R">R</a>|<a class="navig" href="#S">S</a>|<a class="navig" href="#T">T</a>|<a class="navig" href="#U">U</a>|<a class="navig" href="#V">V</a>|<a class="navig" href="#W">W</a>|<a class="navig" href="#X">X</a>|<a class="navig" href="#Y">Y</a>|<a class="navig" href="#Z">Z</a>|
<table width="90%" border="0" cellspacing="1" cellpadding="5">
<% this.functions skin="asIndexItem"
separator="<tr><td class='mainbox'><img src='' width=0 height=0></td></tr>"
%>
</table>
<a class="navig" href="<% this.href action="summary"%>">SUMMARY</a> |
<a class="navig" href="<% this.href action="functionindex" %>">INDEX</a> |
<a class="navig" href="#A">A</a>|<a class="navig" href="#B">B</a>|<a class="navig" href="#C">C</a>|<a class="navig" href="#D">D</a>|<a class="navig" href="#E">E</a>|<a class="navig" href="#F">F</a>|<a class="navig" href="#G">G</a>|<a class="navig" href="#H">H</a>|<a class="navig" href="#I">I</a>|<a class="navig" href="#J">J</a>|<a class="navig" href="#K">K</a>|<a class="navig" href="#L">L</a>|<a class="navig" href="#M">M</a>|<a class="navig" href="#N">N</a>|<a class="navig" href="#O">O</a>|<a class="navig" href="#P">P</a>|<a class="navig" href="#Q">Q</a>|<a class="navig" href="#R">R</a>|<a class="navig" href="#S">S</a>|<a class="navig" href="#T">T</a>|<a class="navig" href="#U">U</a>|<a class="navig" href="#V">V</a>|<a class="navig" href="#W">W</a>|<a class="navig" href="#X">X</a>|<a class="navig" href="#Y">Y</a>|<a class="navig" href="#Z">Z</a>|

View file

@ -0,0 +1,97 @@
/**
* Get the prototype of any doc-object (either a prototype, a function or a tag)
*/
function getDocPrototype(obj) {
var tmp = obj;
while (tmp != null && tmp.getType() != this.PROTOTYPE) {
tmp = tmp.getParentElement();
}
return tmp;
}
/**
* Get a prototype of this docapplication, ie get on of the children of this object
*/
function getPrototype(name) {
return this.getChildElement("prototype_" + name);
}
/**
* Method used by Helma for URL composition.
*/
function href(action) {
var base = this.getParentElement().href() + "api/";
return action ? base + action : base;
}
function getDir(dir, obj) {
dir.mkdir();
if (obj.getType() == this.APPLICATION) {
return dir;
} else {
var protoObj = this.getDocPrototype(obj);
var dir = new File (dir, protoObj.getElementName());
dir.mkdir();
return dir;
}
}
function renderApi() {
var prefix = this.href("");
this.storePage(this, "main", "", "index.html");
this.storePage(this, "prototypes");
this.storePage(this, "summary");
this.storePage(this, "functionindex");
var ct = 4;
var arr = this.listChildren();
for (var i = 0; i < arr.length; i++) {
this.storePage(arr[i], "list", "../");
this.storePage(arr[i], "main", "../");
ct += 2;
var subarr = arr[i].listChildren();
for (var j = 0; j < subarr.length; j++) {
this.storePage(subarr[j], "main", "../", subarr[j].getElementName() + ".html");
ct += 1;
}
}
return ct;
}
function storePage(obj, action, backPath, filename) {
if (filename == null)
var filename = action + ".html";
var str = this.getPage(obj, action, backPath);
var appObj = this.getParentElement();
var dir = new File (appObj.getAppDir().getAbsolutePath(), ".docs");
dir = this.getDir(dir, obj);
var f = new File (dir, filename);
f.remove();
f.open();
f.write(str);
f.close();
app.log("wrote file " + f.getAbsolutePath());
}
function getPage(obj, action, backPath) {
backPath = (backPath == null) ? "" : backPath;
res.pushStringBuffer();
eval("obj." + action + "_action ();");
var str = res.popStringBuffer();
// get the baseURI out of the url and replace
// it with the given relative prefix
// (keep anchors in regex!)
var reg = new RegExp ("href=\"" + this.href("") + "([^\"#]+)([^\"]*)\"", "gim");
str = str.replace(reg, "href=\"" + backPath + "$1.html$2\"");
var reg = new RegExp ("src=\"" + this.href("") + "([^\"#]+)([^\"]*)\"", "gim");
str = str.replace(reg, "src=\"" + backPath + "$1.html$2\"");
// shorten links, so that function files can move up one directory
// in the hierarchy
var reg = new RegExp ("(prototype_[^/]+/[^/]+)/main.html", "gim");
str = str.replace(reg, "$1.html");
return str;
}

View file

@ -0,0 +1,3 @@
<tr><td class='headline'><a name="<% param.letter %>"><!-- --></a>
<big><% param.letter %></big>
</td></tr>

View file

@ -0,0 +1,106 @@
/**
* macro rendering a skin
* @param name name of skin
*/
function skin_macro(par) {
if (par && par.name) {
this.renderSkin(par.name);
}
}
/**
* macro-wrapper for href-function
* @param action name of action to call on this prototype, default main
*/
function href_macro(param) {
return this.href((param && param.action) ? param.action : "main");
}
function comment_macro(param) {
return renderComment(this, param);
}
function content_macro(param) {
return this.getContent();
}
function tags_macro(param) {
return renderTags(this, param);
}
function location_macro(param) {
return renderLocation(this, param);
}
function link_macro(param) {
return renderLink(this, param);
}
//// END OF COPIED FUNCTIONS
function linkToManage_macro(param) {
if (res.data.rendering != true) {
return ('<a href="' + root.href("main") + '" target="_top">back to manage console</a>');
}
}
function headline_macro(param) {
res.write(this.getName());
}
function hrefRoot_macro(param) {
var obj = this.getChildElement("prototype_root");
if (obj == null) {
var obj = this.getChildElement("prototype_Root");
}
if (obj != null) {
var action = (param.action) ? param.action : "main";
return obj.href(action);
}
}
/**
* list all prototypes of this application
* @param skin name of skin to render on prototype
* @param separator
*/
function prototypes_macro(param) {
var skin = (param.skin) ? param.skin : "asPrototypeList";
var separator = (param.separator) ? param.separator : "";
var arr = this.listChildren();
for (var i = 0; i < arr.length; i++) {
arr[i].renderSkin(skin);
if (i < arr.length - 1)
res.write(separator);
}
}
/**
* list all methods of all prototypes, sort them alphabetically
* @param skin name of skin to render on each method
* @param skinSeparator name of skin to render as separator between each letters
*/
function functions_macro(param) {
var skinname = (param.skin) ? param.skin : "asListItem";
var skinIndexSeparator = (param.indexSeparator) ? param.indexSeparator : "indexSeparator";
var separator = (param.separator) ? param.separator : "";
var arr = this.listFunctions();
var lastLetter = "";
for (var i = 0; i < arr.length; i++) {
if (arr[i].getName().substring(0, 1) != lastLetter) {
lastLetter = arr[i].getName().substring(0, 1);
var tmp = new Object ();
tmp.letter = lastLetter.toUpperCase();
this.renderSkin(skinIndexSeparator, tmp);
}
arr[i].renderSkin(skinname);
if (i < arr.length - 1)
res.write(separator);
}
}

View file

@ -0,0 +1,10 @@
<% this.linkToManage suffix="<br/><br/>" %>
<big class="top">Application <a href="<% this.href action="summary" %>" target="main"><% this.name %></a></big><br><br>
<% this.prototypes %>

View file

@ -0,0 +1,29 @@
<table width="90%" border="0" cellspacing="1" cellpadding="5">
<tr>
<td class="headline">
<big class="top">Application <% this.headline %></tt></b></big><br>
</td>
</tr>
</table>
<a class="navig" href="<% this.href action="summary"%>">SUMMARY</a> |
<a class="navig" href="<% this.href action="functionindex" %>">INDEX</a> |
<% this.comment encoding="html" %>
<hr>
<table width="90%" border="0" cellspacing="1" cellpadding="5">
<% this.prototypes skin="asSummary"
separator="<tr><td class='mainbox'><img src='' width=0 height=0></td></tr>"
%>
</table>
<a class="navig" href="<% this.href action="summary"%>">SUMMARY</a> |
<a class="navig" href="<% this.href action="functionindex" %>">INDEX</a> |

View file

@ -0,0 +1,11 @@
function main_action() {
if (checkAddress() == false)
return;
if (checkAuth() == false)
return;
res.data.body = this.renderSkinAsString("main");
renderSkin("api");
}

View file

@ -0,0 +1,7 @@
<tr><td>
<% this.link handler="false" %>
- <% this.type %> in <% docprototype.name %>
<br/>
<% this.comment length="200" %>
</td></tr>

View file

@ -0,0 +1,5 @@
<tr><td>
<a href="<% this.href action="main" %>" target="main"><% this.link %></a><br/>
<% this.comment length="200" %>
</td></tr>

View file

@ -0,0 +1,8 @@
<tr><td>
<a href="<% this.href action="main" %>" target="main"><% this.link %></a><br/>
<% this.comment length="200" %>
<% this.skinparameters separator=", "%>
</td></tr>

View file

@ -0,0 +1,2 @@
<% this.link %><br>

View file

@ -0,0 +1 @@
<% this.link %>

View file

@ -0,0 +1,10 @@
/**
* Method used by Helma for URL composition.
*/
function href(action) {
var base = this.getParentElement().href()
+ this.getElementName() + "/";
return action ? base + action : base;
}

View file

@ -0,0 +1,150 @@
/**
* macro rendering a skin
* @param name name of skin
*/
function skin_macro(par) {
if (par && par.name) {
this.renderSkin(par.name);
}
}
/**
* macro-wrapper for href-function
* @param action name of action to call on this prototype, default main
*/
function href_macro(param) {
return this.href((param && param.action) ? param.action : "main");
}
function comment_macro(param) {
return renderComment(this, param);
}
function content_macro(param) {
return this.getContent();
}
function tags_macro(param) {
return renderTags(this, param);
}
function location_macro(param) {
return renderLocation(this, param);
}
function link_macro(param) {
return renderLink(this, param);
}
//// END OF COPIED FUNCTIONS
function headline_macro(param) {
var p = this.getParentElement();
var handler = (p != null) ? p.getName() : "";
if (this.getType() == this.ACTION) {
res.write("/" + this.getName());
} else if (this.getType() == this.FUNCTION) {
if (handler != "" && handler != "global")
res.write(handler + ".");
res.write(this.getName() + "&nbsp;(");
var arr = this.listParameters();
for (var i = 0; i < arr.length; i++) {
res.write(arr[i]);
if (i < arr.length - 1) {
res.write(",&nbsp;");
}
}
res.write(")");
} else if (this.getType() == this.MACRO) {
res.write("&lt;%&nbsp;");
if (handler != "" && handler != "global")
res.write(handler + ".");
var name = this.getName();
if (name.indexOf("_macro") > -1)
name = name.substring(0, name.length - 6);
res.write(name);
res.write("&nbsp;%&gt;");
} else if (this.getType() == this.SKIN) {
if (handler != "" && handler != "global")
res.write(handler + "/");
res.write(this.getName());
res.write(".skin");
} else if (this.getType() == this.PROPERTIES) {
res.write(this.getName());
}
}
function skinparameters_macro(param) {
if (this.getType() == this.SKIN) {
this.parameters_macro(param);
}
}
function parameters_macro(param) {
var separator = (param.separator) ? param.separator : ", ";
var arr = this.listParameters();
for (var i = 0; i < arr.length; i++) {
res.write(arr[i]);
if (i < arr.length - 1)
res.write(separator);
}
}
function type_macro(param) {
return this.getTypeName();
}
/**
* macro returning nicely formatted sourcecode of this method.
* code is encoded, &gt% %&lt;-tags are colorcoded, line numbers are added
*/
function source_macro(param) {
var sourcecode = this.getContent();
if (param.as == "highlighted") {
sourcecode = encode(sourcecode);
// highlight macro tags
r = new RegExp("&lt;%", "gim");
sourcecode = sourcecode.replace(r, '<font color="#aa3300">&lt;%');
r = new RegExp("%&gt;", "gim");
sourcecode = sourcecode.replace(r, '%&gt;</font>');
// highlight js-comments
r = new RegExp("^([ \\t]*//.*)", "gm");
sourcecode = sourcecode.replace(r, '<font color="#33aa00">$1</font>');
// highlight quotation marks, but not for skins
if (this.getTypeName() != "Skin") {
r = new RegExp("(&quot;.*?&quot;)", "gm");
sourcecode = sourcecode.replace(r, '<font color="#9999aa">$1</font>');
r = new RegExp("(\'[\']*\')", "gm");
sourcecode = sourcecode.replace(r, '<font color="#9999aa">$1</font>');
}
// remove all CR and LF, just <br> remains
var r = new RegExp("[\\r\\n]", "gm");
sourcecode = sourcecode.replace(r, "");
var arr = sourcecode.split("<br />");
var line = this.getStartLine ? this.getStartLine() : 1;
for (var i = 0; i < arr.length; i++) {
res.write('<font color="#aaaaaa">' + (line++) + ':</font> ');
if (i < 99) {
res.write(' ');
}
if (i < 9) {
res.write(' ');
}
res.write(arr[i] + "\n");
}
} else {
res.write(sourcecode);
}
}

View file

@ -0,0 +1,34 @@
<table width="90%" border="0" cellspacing="1" cellpadding="5">
<tr>
<td class="headline">
<big><tt><% this.headline %></tt></big><br>
</td>
</tr>
<tr>
<td class="mainbox">
<% this.comment suffix="<br><br>" %>
<% this.skinparameters prefix="general parameters used in this skin:<ul><li><code>" separator="</code><li><code>" suffix="</code></ul><br>" %>
<ul>
<% this.tags type="param" skin="parameter" %>
<% this.tags type="return" skin="return" %>
<% this.tags type="author" skin="author" %>
<% this.tags type="see" skin="see" %>
<% this.tags type="deprecated" skin="deprecated" %>
<% this.tags type="overrides" skin="overrides" %>
</ul>
</td>
</tr>
</table>
<table width="90%" border="0" cellspacing="1" cellpadding="5">
<tr>
<td>Sourcecode in <% this.location %>:
<pre><% this.source as="highlighted" %></pre>
</td>
</tr>
</table>

View file

@ -0,0 +1,18 @@
function list_action() {
if (checkAddress() == false)
return;
if (checkAuth() == false)
return;
res.data.body = this.renderSkinAsString("list");
renderSkin("api");
}
function main_action() {
if (checkAddress() == false)
return;
if (checkAuth() == false)
return;
res.data.body = this.renderSkinAsString("main");
renderSkin("api");
}

View file

@ -0,0 +1 @@
extends Prototype <a href="<% this.href action="list" %>"><% this.name %></a>

View file

@ -0,0 +1,16 @@
<tr><td class='headline'><b>Inherited from prototype <% this.link %>:</b><br></td></tr>
<tr><td>
<% this.methods separator=", " filter="actions" skin="asParentListItem" prefix="<b>Actions: </b>" suffix="<br/>" %>
<% this.methods separator=", " filter="functions" skin="asParentListItem" prefix="<b>Functions: </b>" suffix="<br/>" %>
<% this.methods separator=", " filter="macros" skin="asParentListItem" prefix="<b>Macros: </b>" suffix="<br/>" %>
<% this.methods separator=", " filter="skins" skin="asParentListItem" prefix="<b>Skins: </b>" suffix="<br/>" %>
</td></tr>

View file

@ -0,0 +1,10 @@
<a href="<% this.href action="main" %>" onClick="parent.changePrototypeList(this);" target="main"><% this.name %></a>
<%
this.inheritance action="main" target="main"
onClick="parent.changePrototypeList(this);" hopobject="false"
prefix=" (extends " suffix=")"
%>
<br />

View file

@ -0,0 +1,4 @@
<tr><td>
<a href="<% this.href action="main" %>"><% this.name %></a><br/>
<% this.comment length="200" %>
</td></tr>

View file

@ -0,0 +1,30 @@
function translateType(filter) {
if (filter == "actions")
return Packages.helma.doc.DocElement.ACTION;
else if (filter == "functions")
return Packages.helma.doc.DocElement.FUNCTION;
else if (filter == "macros")
return Packages.helma.doc.DocElement.MACRO;
else if (filter == "skins")
return Packages.helma.doc.DocElement.SKIN;
else if (filter == "properties")
return Packages.helma.doc.DocElement.PROPERTIES;
else
return -1;
}
/**
* Get the application we're part of.
*/
function getApplication() {
return this.getParentElement();
}
/**
* Method used by Helma for URL composition.
*/
function href(action) {
var base = this.getParentElement().href()
+ this.getElementName() + "/";
return action ? base + action : base;
}

View file

@ -0,0 +1,10 @@
<big>Prototype <a href="<% this.href action="main" %>" target="main"><% this.name %></a></big><br/>
<% this.inheritance action="list" %>
<% this.inheritance deep="true" hopobject="true" action="main" target="main" onClick="parent.changePrototypeList(this);" separator=", " prefix="extends: " suffix="<br>" %><br>
<% this.methods filter="actions" skin="asListItem" prefix="<p><b>Actions:</b><br/>" suffix="</p>" %>
<% this.methods filter="functions" skin="asListItem" prefix="<p><b>Functions:</b><br/>" suffix="</p>" %>
<% this.methods filter="macros" skin="asListItem" prefix="<p><b>Macros:</b><br/>" suffix="</p>" %>
<% this.methods filter="skins" skin="asListItem" prefix="<p><b>Skins:</b><br/>" suffix="</p>" %>

View file

@ -0,0 +1,165 @@
/**
* macro rendering a skin
* @param name name of skin
*/
function skin_macro(par) {
if (par && par.name) {
this.renderSkin(par.name);
}
}
/**
* macro-wrapper for href-function
* @param action name of action to call on this prototype, default main
*/
function href_macro(param) {
return this.href((param && param.action) ? param.action : "main");
}
function comment_macro(param) {
return renderComment(this, param);
}
function content_macro(param) {
return this.getContent();
}
function tags_macro(param) {
return renderTags(this, param);
}
function location_macro(param) {
return renderLocation(this, param);
}
function link_macro(param) {
return renderLink(this, param);
}
//// END OF COPIED FUNCTIONS
function headline_macro(param) {
res.write(this.getName());
}
/**
* macro formatting list of methods of this prototype
* @param filter actions | functions | macros | skins
* @param skin skin to apply to the docfunction object
* @param separator
* @param desc Description that is passed on to the called skin
*/
function methods_macro(param) {
var skinname = (param.skin) ? param.skin : "list";
var separator = (param.separator) ? param.separator : "";
var arr = this.listChildren();
var type = this.translateType(param.filter);
var sb = new java.lang.StringBuffer ();
for (var i = 0; i < arr.length; i++) {
if (arr[i].getType() == type) {
sb.append(arr[i].renderSkinAsString(skinname, param));
sb.append(separator);
}
}
var str = sb.toString();
if (str.length > 0)
return str.substring(0, str.length - separator.length);
else
return str;
}
function inheritance_macro(param) {
var action = param.action ? param.action : "main";
var target = param.target ? ('target="' + param.target + '" ') : '';
var obj = this.getParentPrototype();
if (obj != null) {
obj = this.inheritanceUtil(obj, param);
}
if (param.deep == "true") {
while (obj != null) {
obj = this.inheritanceUtil(obj, param);
}
}
}
function inheritanceUtil(obj, param) {
if (obj.getName() == "hopobject" && param.hopobject != "true")
return null;
var tmp = new Object ();
for (var i in param)
tmp[i] = param[i];
tmp.href = obj.href((param.action) ? param.action : "main");
delete tmp.hopobject;
delete tmp.action;
delete tmp.deep;
delete tmp.separator;
res.write(renderLinkTag(tmp));
res.write(obj.getName() + "</a>");
if (obj.getParentPrototype())
res.write(param.separator);
return obj.getParentPrototype();
}
/**
* loops through the parent prototypes and renders a skin on each
* if it has got any functions.
* @param skin
*/
function parentPrototype_macro(param) {
var skinname = (param.skin) ? param.skin : "asParentList";
var obj = this.getParentPrototype();
while (obj != null) {
if (obj.listChildren().length > 0) {
obj.renderSkin(skinname);
}
obj = obj.getParentPrototype();
}
}
/**
* macro rendering a skin depending on wheter this prototype has got
* type-properties or not.
* @param skin
*/
function typeProperties_macro(param) {
var props = this.getTypeProperties();
var iter = props.getResources();
while (iter.hasNext()) {
var tmp = this.renderTypePropertiesResource(iter.next(), props);
var skinname = (param.skinname) ? param.skinname : "typeproperties";
this.renderSkin(skinname, tmp);
}
}
function renderTypePropertiesResource(res, props) {
if (res.getContent() != "") {
var sb = new java.lang.StringBuffer ();
// map of all mappings....
var mappings = props.getMappings();
// parse type.properties linewise:
var arr = res.getContent().split("\n");
for (var i = 0; i < arr.length; i++) {
arr [i] = arr[i].trim();
// look up in mappings table if line matches:
for (var e = mappings.keys(); e.hasMoreElements();) {
var key = e.nextElement();
var reg = new RegExp ('^' + key + '\\s');
if (arr[i].match(reg)) {
// it matched, wrap line in a link to that prototype:
var docProtoObj = this.getApplication().getPrototype(mappings.getProperty(key));
if (docProtoObj != null) {
arr[i] = '<a href="' + docProtoObj.href("main") + '#typeproperties">' + arr[i] + '</a>';
}
}
}
sb.append(arr[i] + "\n");
}
var tmp = new Object ();
tmp.content = sb.toString();
tmp.source = res.getName();
return tmp;
}
}

View file

@ -0,0 +1,81 @@
<table width="90%" border="0" cellspacing="1" cellpadding="5">
<tr>
<td class="headline">
<big><tt>Prototype <% this.headline %></tt></big><br>
<% this.inheritance deep="true" hopobject="true" action="main" target="main" onClick="parent.changePrototypeList(this);" separator=", " prefix="extends: " suffix="<br>" %>
</td>
</tr>
</table>
<a class="navig" href="#actions">ACTIONS</a> |
<a class="navig" href="#functions">FUNCTIONS</a> |
<a class="navig" href="#macros">MACROS</a> |
<a class="navig" href="#skins">SKINS</a> |
<a class="navig" href="#typeproperties">TYPE.PROPERTIES</a>
<br/><br/>
<table width="90%" border="0" cellspacing="1" cellpadding="5">
<tr>
<td class="mainbox">
<% this.comment suffix="<br><br>" %>
<ul>
<% this.tags type="author" skin="author" %>
<% this.tags type="see" skin="see" %>
<% this.tags type="deprecated" skin="deprecated" %>
<% this.tags type="overrides" skin="overrides" %>
</ul>
</td>
</tr>
</table>
<table width="90%" border="0" cellspacing="1" cellpadding="3">
<% this.methods separator="<tr><td class='mainbox'><img src='' width=0 height=0></td></tr>"
filter="actions"
skin="asLargeListItem"
prefix="<tr><td class='headline'>Actions<a name='actions'><!-- --></a></td></tr>"
suffix="<tr><td height='8'>&nbsp;</td></tr>"
%>
<% this.methods separator="<tr><td class='mainbox'><img src='' width=0 height=0></td></tr>"
filter="functions"
skin="asLargeListItem"
prefix="<tr><td class='headline'>Functions<a name='functions'><!-- --></a></td></tr>"
suffix="<tr><td height='8'>&nbsp;</td></tr>"
%>
<% this.methods separator="<tr><td class='mainbox'><img src='' width=0 height=0></td></tr>"
filter="macros"
skin="asLargeListItem"
prefix="<tr><td class='headline'>Macros<a name='macros'><!-- --></a></td></tr>"
suffix="<tr><td height='8'>&nbsp;</td></tr>"
%>
<% this.methods separator="<tr><td class='mainbox'><img src='' width=0 height=0></td></tr>"
filter="skins"
skin="asLargeListItemSkin"
prefix="<tr><td class='headline'>Skins<a name='skins'><!-- --></a></td></tr>"
suffix="<tr><td height='8'>&nbsp;</td></tr>"
%>
<% this.methods separator="<tr><td class='mainbox'><img src='' width=0 height=0></td></tr>"
filter="properties"
skin="asLargeListItemSkin"
prefix="<tr><td class='headline'>type.properties<a name='typeproperties'><!-- --></a></td></tr>"
suffix="<tr><td height='8'>&nbsp;</td></tr>"
%>
<% this.parentPrototype skin="asParentList" %>
</table>
<br/><br/>
<!-- % this.typeProperties % -->

View file

@ -0,0 +1,9 @@
<a name='typeproperties'><!-- --></a>
<table width='90%' border='0' cellspacing='1' cellpadding='5'><tr>
<td class="headline">type.properties in <% param.source %></td>
</tr>
<tr>
<td class="mainbox"><pre><% param.content %></pre></td>
</tr>
</table>

View file

@ -0,0 +1,2 @@
<li><b>Author</b><br/>
<% this.text %>

View file

@ -0,0 +1,2 @@
<li><b>Deprecated</b><br/>
<% this.text %>

View file

@ -0,0 +1 @@
<li><% this.text %>

View file

@ -0,0 +1,3 @@
<li><b>Overrides</b><br/>
<% param.link %>

View file

@ -0,0 +1,2 @@
<li><b>Parameter</b> <code><% this.name %></code>:<br/>
<% this.text %>

View file

@ -0,0 +1,2 @@
<li><b>Returns</b><br>
<% this.text %>

View file

@ -0,0 +1,2 @@
<li><b>See also</b><br>
<% param.link %>

View file

@ -0,0 +1,67 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<html>
<head>
<title></title>
<style type="text/css">
body, p, td, th, li {
font-family: verdana, sans-serif;
font-size: 10pt;
}
big.top {
font-size: 18pt;
font-weight: bold;
}
big {
font-size: 13pt;
font-weight: bold;
}
a {
font-weight:bold;
color: #cc3333;
text-decoration:none;
}
a:hover {
text-decoration:underline;
}
.navig {
font-size: 9px;
text-decoration: none;
font-weight:normal;
}
li {
padding-bottom: 5px;
}
.mainbox {
border-color:#999999;
padding-top:5px;
padding-bottom:5px;
border-bottom-width:1px;
border-bottom-style:dotted;
}
.headline {
font-weight:bold;
background:#dfdfdf;
border-color:#999999;
padding-top:5px;
padding-bottom:5px;
}
</style>
</head>
<body>
<% response.body %>
</body>
</html>

View file

@ -0,0 +1,5 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<% response.head %>
<% response.body %>
</html>

View file

@ -0,0 +1,262 @@
/**
* scheduler function, runs global.appStat every minute
*/
function scheduler() {
appStat();
return 60000;
}
/**
* initializes app.data.stat storage on startup,
* creates app.data.addressFilter
*/
function onStart() {
app.data.addressFilter = createAddressFilter();
app.data.addressString = root.getProperty("allowadmin");
}
/**
* initializes addressFilter from app.properties,
* hostnames are converted, wildcards are only allowed in ip-addresses
* (so, no network-names, sorry)
*/
function createAddressFilter() {
var filter = new Packages.helma.util.InetAddressFilter();
var str = root.getProperty("allowadmin");
if (str != null && str != "") {
var arr = str.split(",");
for (var i in arr) {
str = new java.lang.String(arr[i]);
try {
filter.addAddress(str.trim());
} catch (a) {
try {
str = java.net.InetAddress.getByName(str.trim()).getHostAddress();
filter.addAddress(str);
} catch (b) {
app.log("error using address " + arr[i] + ": " + b);
}
}
}
} else {
app.log("no addresses allowed for app manage, all access will be denied");
}
return filter;
}
/**
* updates the stats in app.data.stat every 5 minutes
*/
function appStat() {
if (app.data.stat == null)
app.data.stat = new HopObject ();
if ((new Date() - 300000) < app.data.stat.lastRun)
return;
var arr = root.getApplications();
for (var i = 0; i < arr.length; i++) {
var tmp = app.data.stat[arr[i].getName()];
if (tmp == null) {
tmp = new HopObject();
tmp.lastTotalRequestCount = 0;
tmp.lastTotalErrorCount = 0;
}
tmp.requestCount = arr[i].getRequestCount() - tmp.lastTotalRequestCount;
tmp.lastTotalRequestCount = arr[i].getRequestCount();
tmp.errorCount = arr[i].getErrorCount() - tmp.lastTotalErrorCount;
tmp.lastTotalErrorCount = arr[i].getErrorCount();
app.data.stat[arr[i].getName()] = tmp;
}
app.data.stat.lastRun = new Date();
}
/**
* utility function to sort object-arrays by name
*/
function sortByName(a, b) {
if (a.name > b.name)
return 1;
else if (a.name == b.name)
return 0;
else
return -1;
}
/**
* utility function to sort property-arrays by key
*/
function sortProps(a, b) {
if (a > b)
return 1;
else if (a == b)
return 0;
else
return -1;
}
/**
* check access to an application or the whole server, authenticate against md5-encrypted
* properties of base-app or the particular application. if username or password aren't set
* go into stealth-mode and return a 404. if username|password are wrong, prepare response-
* object for http-auth and return false.
* @arg appObj application object to check against (if adminUsername etc are set in app.properties)
*/
function checkAuth(appObj) {
if (res && res.data.noWeb == true) {
return true;
}
var ok = false;
// check against root
var adminAccess = root.getProperty("adminAccess");
if (adminAccess == null || adminAccess == "") {
res.redirect(root.href("makekey"));
}
var uname = req.username;
var pwd = req.password;
if (uname == null || uname == "" || pwd == null || pwd == "")
return forceAuth();
var md5key = Packages.helma.util.MD5Encoder.encode(uname + "-" + pwd);
if (md5key == adminAccess)
return true;
if (appObj != null && appObj.isActive()) {
// check against application
adminAccess = appObj.getProperty("adminAccess");
if (md5key == adminAccess)
return true;
}
return forceAuth();
}
/**
* check access to the manage-app by ip-addresses
*/
function checkAddress() {
if (res && res.data.noWeb == true) {
return true;
}
// if allowadmin value in server.properties has changed,
// re-construct the addressFilter
if (app.data.addressString != root.getProperty("allowadmin")) {
app.data.addressFilter = createAddressFilter();
app.data.addressString = root.getProperty("allowadmin");
}
if (!app.data.addressFilter.matches(java.net.InetAddress.getByName(req.data.http_remotehost))) {
app.log("denied request from " + req.data.http_remotehost);
// forceStealth seems a bit like overkill here.
// display a message that the ip address must be added to server.properties
res.write("Access from address " + req.data.http_remotehost + " denied.");
return false;
} else {
return true;
}
}
/**
* response is reset to 401 / authorization required
* @arg realm realm for http-auth
*/
function forceAuth(realm) {
res.reset();
res.status = 401;
res.realm = (realm != null) ? realm : "helma";
res.write("Authorization Required. The server could not verify that you are authorized to access the requested page.");
return false;
}
/**
* macro-utility: formatting property lists
*/
function formatProperties(props, par) {
if (props.size() == 0)
return "";
var e = props.keys();
var arr = new Array();
while (e.hasMoreElements()) {
arr[arr.length] = e.nextElement();
}
arr.sort(sortProps);
for (var i in arr) {
// don't print the admin-password
if (arr[i].toLowerCase() == "adminusername" || arr[i].toLowerCase() == "adminpassword") continue;
res.write(par.itemprefix + arr[i] + par.separator + props.getProperty(arr[i]) + par.itemsuffix);
}
}
/**
* macro-utility: formatting an integer value as human readable bytes
*/
function formatBytes(bytes) {
if (bytes > Math.pow(2, 30)) {
res.write(Math.round(100 * bytes / Math.pow(2, 30)) / 100 + "gb");
} else if (bytes > Math.pow(2, 20)) {
res.write(Math.round(100 * bytes / Math.pow(2, 20)) / 100 + "mb");
} else {
res.write(Math.round(100 * bytes / Math.pow(2, 10)) / 100 + "kb");
}
}
/**
* macro-utility: formatting time in millis as human readable age
*/
function formatAge(age) {
var str = "";
var days = Math.floor(age / 86400);
age = age - days * 86400;
var hours = Math.floor(age / 3600);
age = age - hours * 3600;
var minutes = Math.floor(age / 60);
var seconds = Math.floor(age - minutes * 60);
if (days > 0)
str += (days + " days, ");
if (hours > 0)
str += (hours + "h, ");
str += (minutes + "min");
if (days == 0) str += (", " + seconds + "sec");
return(str);
}
/**
* macro-utility: formatting a number-suffix by choosing between singular and plural
* @arg value number to be formatted
* @arg param-object object to get fields
* @param singular string used for value==1
* @param plural string used for value!=1
*/
function formatCount(ct, par) {
if (!par || !par.singular || !par.plural) {
return "";
}
if (ct == 1)
return par.singular;
else
return par.plural;
}
/**
* tries to make out if this server is running linux from java's system properties
*/
function isLinux() {
var str = java.lang.System.getProperty("os.name");
return (str != null && str.toLowerCase().indexOf("linux") != -1);
}

View file

@ -0,0 +1,14 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<% skin name="head" %>
<body bgcolor="white">
<table width="90%" border="0" cellspacing="1" cellpadding="5" bgcolor="#000000">
<tr>
<td width="30%" align="left" valign="top" bgcolor="#cccc99"><% skin name="navig" %></td>
<td width="70%" align="left" valign="top" bgcolor="#ffffff"><% response.body %></td>
</tr>
</table>
</body>
</html>

View file

@ -0,0 +1,59 @@
<head>
<title><% response.title %></title>
<style type="text/css">
<!--
body, p, td, th, li {
font-family: verdana, sans-serif;
font-size: 10pt;
}
.formEl {
border-color:#000000;
border-style:solid;
border-width:1px;
}
.list_apps {
border-color:#ffffff;
padding-top:5px;
padding-bottom:5px;
border-bottom-width:1px;
border-bottom-style:dotted;
}
.list_property {
border-color:#999999;
padding-top:5px;
padding-bottom:5px;
border-bottom-width:1px;
border-bottom-style:dotted;
}
.list_separator {
font-weight:bold;
background:#dfdfdf;
border-color:#999999;
padding-top:5px;
padding-bottom:5px;
border-bottom-width:1px;
border-bottom-style:dotted;
}
big {
font-size: 18pt;
font-weight: bold;
}
a {
font-weight:bold;
color: #cc3333;
text-decoration:none;
}
a:hover {
text-decoration:underline;
}
// -->
</style>
</head>

View file

@ -0,0 +1,18 @@
/**
* macro rendering a skin
* @param name name of skin
*/
function skin_macro(par) {
if (par && par.name) {
renderSkin(par.name);
}
}
/**
* Macro returning the actual date and time.
*/
function now_macro() {
var date = new Date();
return(date.format("dd.MM.yyyy, HH:mm'h' zzz"));
}

View file

@ -0,0 +1,30 @@
<p><a href="<% root.href action="main" %>"><img src="<% root.href action="image" %>" title="helma" border="0" width="174" height="35" align="baseline" style="border-width:3px;border-color:white;"></a>
</p>
<div class="list_apps">
<i><% root.appCount filter="active" singular=" app" plural=" apps"%> on
<a href="<% root.href action="main" %>"><% root.hostname %> (<% root.hostaddress %>)</a></i>
</div>
<% root.appList filter="active" %>
<p></p>
<div class="list_apps">
<i>disabled apps:</i>
</div>
<% root.appList filter="disabled" skin="navig_disabled" %>
<br/><br/>
<p>
Information on <a href="http://helma.org/">helma.org</a>:<br/>
<li><a href="http://helma.org/docs">reference</a><br/>
<li><a href="http://dev.helma.org/Mailing+Lists/">mailinglist</a><br/>
<li><a href="https://dev.helma.org/trac/helma/browser/helma/helma/trunk">svn</a><br/>
<li><a href="http://helma.org/download/">download</a><br/>
</p>
<p>
<li><a href="<% root.href action="makekey" %>">generate server password</a>
</p>

View file

@ -0,0 +1,20 @@
<body bgcolor="white">
<table width="500" border="0" cellspacing="0" cellpadding="5" bgcolor="#000000">
<tr>
<td width="500" align="left" valign="top" bgcolor="#ffffff">
<big>Generated username and password for helma's manager:</big><br>
<p>Please copy/paste this line into the server.properties file of your
helma installation.</p>
<pre><% param.propsString %></pre>
<p>After that proceed to <a href="<% root.href action="main" %>">the manage console</a>,
enter your credentials and you should be allowed in.</p>
</td></tr>
</table>
</body>

View file

@ -0,0 +1,28 @@
<body bgcolor="white">
<table width="500" border="0" cellspacing="0" cellpadding="5" bgcolor="#000000">
<tr>
<td width="500" align="left" valign="top" bgcolor="#ffffff">
<big>Username and password for helma's manager:</big><br>
<p>Please choose an username and password combination to access the
manage application of this server. They will be printed md5-encoded
in a format that you've got to copy/paste into the server.properties
file.</p>
<font color="red"><% param.msg %></font>
<form method="post">
<input class="formEl" name="username" size="25" value="<% param.username %>"> (username)<br>
<input class="formEl" type="password" name="password" size="25"> (password)<br>
<input class="formEl" type="submit" value="md5 encode"><br>
</form>
<p><b>Warning:</b> The used http-authorization transmits username and password
in an unsafe cleartext way. Therefore you're strongly discouraged to
use any given combination that is normally protected through SSH.</p>
</td></tr>
</table>
</body>

View file

@ -0,0 +1,153 @@
function renderLink(docEl, param) {
var text = "";
if (docEl.getType() == docEl.APPLICATION || docEl.getType() == docEl.PROTOTYPE) {
text = docEl.getName();
} else if (docEl.getType() == docEl.SKIN) {
text = docEl.getName() + ".skin";
} else if (docEl.getType() == docEl.MACRO) {
if (param.handler != "false" && docEl.getParentElement() && docEl.getParentElement().getName() != "global") {
text = docEl.getParentElement().getName() + ".";
}
var str = docEl.getName();
if (str.indexOf("_macro")) {
text += str.substring(0, str.length - 6);
}
} else if (docEl.getType() == docEl.FUNCTION) {
text = docEl.getName() + "(";
var arr = docEl.listParameters();
for (var i = 0; i < arr.length; i++) {
text += arr[i];
if (i < arr.length - 1)
text += ",&nbsp;";
}
text += ")";
} else {
text = docEl.getName();
}
param.href = docEl.href("main");
if (!param.target) {
param.target = "main";
}
return renderLinkTag(param) + text + '</a>';
}
function renderLinkTag(param) {
var sb = new java.lang.StringBuffer ();
sb.append('<a');
for (var i in param) {
sb.append(' ');
sb.append(i);
sb.append('="');
sb.append(param[i]);
sb.append('"');
}
sb.append('>');
return sb.toString();
}
/**
* renders the name of the location of a doc element.
*/
function renderLocation (docEl, param) {
return docEl.toString();
}
/**
* renders tag list.
* @param param.skin skin to render on found DocTags
* @param param.separator String printed between tags
* @param param.type type string (param|return|author|version|see) to filter tags.
*/
function renderTags(docEl, param) {
var skinname = (param.skin) ? param.skin : "main";
var type = param.type;
if (type == "params")
type = "param";
else if (type == "returns")
type = "return";
else if (type == "arg")
type = "param";
var str = "";
var arr = docEl.listTags();
for (var i = 0; i < arr.length; i++) {
if (arr[i].getType() == type) {
if (type == "see" || type == "overrides") {
param.link = renderReference(arr[i], docEl);
}
str += arr[i].renderSkinAsString(skinname, param);
str += (param.separator) ? param.separator : "";
}
}
return str;
}
/**
* renders a reference to functions in other prototypes, masks
* urls in a see tag
* (see- and overrides-tags)
* @param docTagObj
* @param docEl needed to be able to walk up to application object
*/
function renderReference(docTagObj, docEl) {
// prepare the text:
var text = docTagObj.getText();
text = new java.lang.String (text);
text = text.trim();
if (text.indexOf("http://") == 0) {
// an url is a simple job
return '<a href="' + text + '" target="_new">' + text + '</a>';
} else {
// make sure we only use the first item in the text so that unlinked comments
// can follow, store & split the that
var tok = new java.util.StringTokenizer (text);
var tmp = tok.nextToken();
text = " " + text.substring(tmp.length + 1);
var parts = tmp.split(".");
// try to find the application object
var obj = docEl;
while (obj != null) {
if (obj.getType() == Packages.helma.doc.DocElement.APPLICATION) {
var appObj = obj;
break;
}
obj = obj.getParentElement();
}
var protoObj = appObj.getChildElement("prototype_" + parts[0]);
if (protoObj == null) {
// prototype wasn't found, return the unlinked tag
return tmp + text;
}
if (parts.length == 1) {
// no function specified, return the linked prototype
return '<a href="' + protoObj.href("main") + '">' + format(tmp) + '</a>' + text;
}
// try to find a function object:
var arr = protoObj.listChildren();
for (var i = 0; i < arr.length; i++) {
if (arr[i].getName() == parts [1]) {
return '<a href="' + arr[i].href("main") + '">' + format(tmp) + '</a>' + text;
}
}
// function not found:
return tmp + text;
}
}
/**
* function rendering a comment.
* @param param.length comment is shortened to the given length.
* @returns string
*/
function renderComment(docEl, param) {
var str = docEl.getComment();
if (param.length) {
if (param.length < str.length) {
return str.substring(0, param.length) + " ...";
}
}
return str;
}

130
apps/manage/Root/actions.js Normal file
View file

@ -0,0 +1,130 @@
/**
* main action, show server-stats
* perform start, stop, restart and flush-action
*
*/
function main_action() {
if (checkAddress() == false) return;
if (req.data.app != null && req.data.app != "" && req.data.action != null && req.data.action != "") {
var appObj = root.getApp(req.data.app);
// check access for application. md5-encoded uname/pwd can also be put in
// app.properties to limit access to a single app
if (checkAuth(appObj) == false) return;
if (req.data.action == "start") {
this.startApplication(req.data.app);
res.redirect(appObj.href("main"));
} else if (req.data.action == "stop") {
if (checkAuth() == false) return;
this.stopApplication(req.data.app);
res.redirect(root.href("main"));
} else if (req.data.action == "restart") {
this.stopApplication(req.data.app);
this.startApplication(req.data.app);
res.redirect(appObj.href("main"));
} else if (req.data.action == "flush") {
appObj.clearCache();
res.redirect(appObj.href("main"));
}
}
// output only to root
if (checkAuth() == false) return;
res.data.title = "Helma Object Publisher - Serverinfo";
res.data.body = this.renderSkinAsString("main");
renderSkin("global");
}
/**
* return the helma object publisher logo, built into hop core
* to be independent of static html-paths
*/
function image_action() {
if (checkAddress() == false) return;
res.contentType = "image/gif";
res.writeBinary(Packages.helma.util.Logo.hop);
}
function makekey_action() {
if (checkAddress() == false)
return;
var obj = new Object();
obj.msg = "";
if (req.data.username != null && req.data.password != null) {
// we have input from webform
if (req.data.username == "")
obj.msg += "username can't be left empty!<br>";
if (req.data.password == "")
obj.msg += "password can't be left empty!<br>";
if (obj.msg != "") {
obj.username = req.data.username;
res.reset();
res.data.body = renderSkinAsString("pwdform", obj);
} else {
// render the md5-string:
obj.propsString = "adminAccess=" + Packages.helma.util.MD5Encoder.encode(req.data.username + "-" + req.data.password) + "<br>\n";
res.data.body = renderSkinAsString("pwdfeedback", obj);
}
} else {
// no input from webform, so print it
res.data.body = renderSkinAsString("pwdform", obj);
}
res.data.title = "username & password on " + root.hostname_macro();
res.data.head = renderSkinAsString("head");
renderSkin("basic");
}
/**
* prints server-stats for mrtg-tool.
* doesn't check username or password, so that we don't have
* to write them cleartext in a mrtg-configfile but checks the
* remote address.
*/
function mrtg_action() {
if (checkAddress() == false)
return;
if (req.data.action == "memory") {
res.write(this.jvmTotalMemory_macro() + "\n");
res.write(this.jvmFreeMemory_macro() + "\n");
res.write("0\n0\n");
} else if (req.data.action == "netstat" && isLinux()) {
var str = (new File("/proc/net/tcp")).readAll();
var arr = str.split("\n");
res.write(arr.length - 2 + "\n");
res.write("0\n0\n0\n");
} else if (req.data.action == "loadavg" && isLinux()) {
// load average of last 5 minutes:
var str = (new File("/proc/loadavg")).readAll();
var arr = str.split(" ");
res.write(arr[1] * 100 + "\n");
res.write("0\n0\n0\n");
} else {
res.write("0\n0\n0\n0\n");
}
}

View file

@ -0,0 +1,76 @@
/**
* renders the api of a given application. used from commandline.
*/
function renderApi(appName) {
// supress security checks when accessing actions
res.data.noWeb = true;
// start the application
this.startApplication(appName);
var appObj = this.getApp(appName);
var docApp = appObj.getChildElement("api");
// now render the api
var ct = docApp.renderApi();
writeln("rendered " + ct + " files");
// cleanup
this.stopApplication(appName);
}
/**
* lists all applications in appdir.
* for active apps use this.getApplications() = helma.main.Server.getApplications()
*/
function getAllApplications() {
var appsDir = this.getAppsHome();
var dir = appsDir.listFiles();
var arr = new Array();
var seen = {};
// first check apps directory for apps directories
if (dir) {
for (var i = 0; i < dir.length; i++) {
if (dir[i].isDirectory() && dir[i].name.toLowerCase() != "cvs") {
arr[arr.length] = this.getApp(dir[i].name);
seen[dir[i].name] = true;
}
}
}
// then check entries in apps.properties for apps not currently running
var props = wrapJavaMap(root.getAppsProperties(null));
for (var i in props) {
if (i.indexOf(".") < 0 && !seen[i] && !root.getApplication(i)) {
arr[arr.length] = this.getApp(i);
}
}
return arr;
}
/**
* get application by name, constructs an hopobject of the prototype application
* if the app is not running (and therefore can't be access through
* helma.main.ApplicationManager).
* ATTENTION: javascript should not overwrite helma.main.Server.getApplication() which
* retrieves active applications.
* @arg name of application
*/
function getApp(name) {
if (name == null || name == "")
return null;
var appObj = this.getApplication(name);
if (appObj == null)
appObj = new Application(name);
return appObj;
}
/**
* Method used by Helma path resolution.
*/
function getChildElement(name) {
return this.getApp(name);
}

284
apps/manage/Root/macros.js Normal file
View file

@ -0,0 +1,284 @@
/**
* macro rendering a skin
* @param name name of skin
*/
function skin_macro(par) {
if (par && par.name) {
this.renderSkin(par.name);
}
}
/**
* macro-wrapper for href-function
* @param action name of action to call on this prototype, default main
*/
function href_macro(par) {
return this.href((par && par.action)?par.action:"main");
}
/**
* macro returning the total number of sessions on this server
* @see global.formatCount
*/
function countSessions_macro(par) {
var arr = this.getApplications();
var sum = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i].getName() != app.__app__.getName()) {
sum += arr[i].sessions.size();
}
}
return sum + formatCount(sum, par);
}
/**
* macro returning the number of requests during the last 5 minutes
* @see global.formatCount
*/
function requestCount_macro(par) {
if (app.data.stat == null) {
return;
}
var arr = this.getApplications();
var sum = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i].getName() != app.__app__.getName()) { // don't include manage app
var obj = app.data.stat[arr[i].name];
if (obj != null) {
sum += obj.requestCount;
}
}
}
return sum + formatCount(sum, par);
}
/**
* macro returning the number of errors during the last 5 minutes
* @see global.formatCount
*/
function errorCount_macro(par) {
if (app.data.stat == null) {
return;
}
var arr = this.getApplications();
var sum = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i].getName() != app.__app__.getName()) { // don't include manage app
var obj = app.data.stat[arr[i].name];
if (obj != null) {
sum += obj.errorCount;
}
}
}
return sum + formatCount(sum, par);
}
function extensions_macro(par) {
var vec = this.getExtensions();
var str = "";
for (var i = 0; i < vec.size(); i++) {
str += vec.elementAt(i).getClass().getName();
if (i != (vec.size() - 1)) {
str += (par && par.separator) ? par.separator : ", ";
}
}
return (str == "") ? null : str;
}
/**
* Macro returning hostname of this machine
*/
function hostname_macro(par) {
return java.net.InetAddress.getLocalHost().getHostName()
}
/**
* Macro returning address of this machine
*/
function hostaddress_macro(par) {
return java.net.InetAddress.getLocalHost().getHostAddress()
}
/**
* Macro returning the number of running applications,
* the manage application being excluded.
*/
function appCount_macro(par) {
if (par && par.filter == "active") {
var ct = root.getApplications().length - 1;
} else if (par && par.filter == "disabled") {
var ct = root.getAllApplications().length - root.getApplications().length;
} else {
var ct = root.getAllApplications().length - 1;
}
return ct + formatCount(ct, par);
}
/**
* Macro that lists all running applications,
* the manage application being excluded (-1).
* @param skin skin of application that will be used.
*/
function appList_macro(par) {
var skin = (par && par.skin) ? par.skin : "navig_active";
var apps = new Array();
if (par && par.filter == "active") {
var arr = root.getApplications();
for (var i = 0; i < arr.length; i++) {
apps[apps.length] = arr[i];
}
} else if (par && par.filter == "disabled") {
var arr = root.getAllApplications();
for (var i in arr) {
if (arr[i].isActive() == false) {
apps[apps.length] = arr[i];
}
}
} else {
var apps = root.getAllApplications();
}
apps = apps.sort(sortByName);
var html = "";
var param = new Object();
for (var n in apps) {
var a = apps[n];
if (apps[n].name == app.__app__.getName())
continue;
var item = a.renderSkinAsString(skin);
html += item;
}
return(html);
}
/**
* Macro that returns the server's uptime nicely formatted
*/
function uptime_macro() {
return formatAge((java.lang.System.currentTimeMillis() - this.starttime) / 1000);
}
/**
* Macro that returns the server's version string
*/
function version_macro() {
return this.version;
}
/**
* Macro that returns the home directory of the hop installation
*/
function home_macro() {
return this.getHopHome().toString();
}
/**
* Macro that returns the free memory in the java virtual machine
* @param format if "hr", value will be printed human readable
*/
function jvmFreeMemory_macro(param) {
var m = java.lang.Runtime.getRuntime().freeMemory();
return (param && param.hr) ? formatBytes(m) : m;
}
/**
* Macro that returns the total memory available to the java virtual machine
* @param format if "hr", value will be printed human readable
*/
function jvmTotalMemory_macro(param) {
var m = java.lang.Runtime.getRuntime().totalMemory();
return (param && param.hr) ? formatBytes(m) : m;
}
/**
* Macro that returns the used memory in the java virtual machine
* @param format if "hr", value will be printed human readable
*/
function jvmUsedMemory_macro(param) {
var m = java.lang.Runtime.getRuntime().totalMemory() - java.lang.Runtime.getRuntime().freeMemory();
return (param && param.hr) ? formatBytes(m) : m;
}
/**
* Macro that returns the version and type of the java virtual machine
*/
function jvm_macro() {
return java.lang.System.getProperty("java.version") + " " + java.lang.System.getProperty("java.vendor");
}
/**
* Macro that returns the home directory of the java virtual machine
*/
function jvmHome_macro() {
return java.lang.System.getProperty("java.home");
}
/**
* Macro that greps all jar-files from the class path variable and lists them.
* @param separator string that is printed between the items
*/
function jvmJars_macro(par) {
var separator = (par && par.separator ) ? par.separator : ", ";
var str = java.lang.System.getProperty("java.class.path");
var arr = str.split(".jar");
for (var i in arr) {
var str = arr[i];
var pos = ( str.lastIndexOf('\\') > str.lastIndexOf('/') ) ? str.lastIndexOf('\\') : str.lastIndexOf('/');
res.write(arr[i].substring(pos + 1) + ".jar");
if (i < arr.length - 1) res.write(separator);
}
}
/**
* Macro that returns the name and version of the server's os
*/
function os_macro() {
return java.lang.System.getProperty("os.name") + " " + java.lang.System.getProperty("os.arch") + " " + java.lang.System.getProperty("os.version");
}
/**
* Macro that returns anything from server.properties
*/
function property_macro(par) {
if (par && par.key) {
return this.getProperty(key);
} else {
return "";
}
}
/**
* Macro formatting server.properties
*/
function properties_macro(par) {
formatProperties(this.getProperties(), par);
}
/**
* Macro that returns the timezone of this server
*/
function timezone_macro(par) {
return java.util.TimeZone.getDefault().getDisplayName(false, java.util.TimeZone.LONG) + " (" + java.util.TimeZone.getDefault().getID() + ")";
}

111
apps/manage/Root/main.skin Normal file
View file

@ -0,0 +1,111 @@
<big><% this.hostname %> (<% this.hostaddress %>)</big><br/><br/>
<table border="0" cellspacing="0" cellpadding="3">
<tr>
<td class="list_separator" colspan="3">helma</td>
</tr>
<tr>
<td class="list_property">uptime:</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.uptime %></td>
</tr>
<tr>
<td class="list_property">version:</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.version %></td>
</tr>
<tr>
<td class="list_property">homedir:</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.home %></td>
</tr>
<tr>
<td class="list_property" valign="top">total active sessions:</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.countSessions default="&nbsp;" %></td>
</tr>
<tr>
<td class="list_property" nowrap valign="top">total requests / 5 min:</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.requestCount default="&nbsp;" %></td>
</tr>
<tr>
<td class="list_property" norwrap valign="top">total errors / 5 min:</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.errorCount default="&nbsp;" %></td>
</tr>
<tr>
<td class="list_property" valign="top">loaded extensions:</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.extensions default="&nbsp;" %></td>
</tr>
<tr>
<td class="list_separator" colspan="3">jre</td>
</tr>
<tr>
<td class="list_property">free memory:</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.jvmFreeMemory hr="true" %></td>
</tr>
<tr>
<td class="list_property">used memory:</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.jvmUsedMemory hr="true" %></td>
</tr>
<tr>
<td class="list_property">total memory:</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.jvmTotalMemory hr="true" %></td>
</tr>
<tr>
<td class="list_property">java:</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.jvm %></td>
</tr>
<tr>
<td class="list_property">javahome:</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.jvmHome %></td>
</tr>
<tr>
<td class="list_property">os:</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.os %></td>
</tr>
<tr>
<td class="list_property">localtime:</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% now %></td>
</tr>
<tr>
<td class="list_property" valign="top">timezone:</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.timezone %></td>
</tr>
<tr>
<td class="list_property" valign="top">loaded Jars:</td>
<td class="list_property" width="5">&nbsp;</td>
<td class="list_property" align="left"><% this.jvmJars %></td>
</tr>
<tr>
<td class="list_separator" colspan="3">server.properties</td>
</tr>
<% this.properties itemprefix='<tr><td class="list_property">' separator='</td><td class="list_property" width="5">&nbsp;</td><td class="list_property" align="left">' itemsuffix='</td></tr>' %>
</table>

View file

@ -0,0 +1,12 @@
# Set baseURI for application generated URLs, if necessary.
# baseURI = /manage
# A short description of what this application is about:
_description = Helma's server management console. Start applications, introspection etc.
# use higher request timeout because rendering the apidocs
# might take more than one minute on a slow computer
requestTimeout = 300
# run scheduler function each minute
cron.scheduler.function = scheduler

View file

@ -0,0 +1,27 @@
#
# define the root class of this application
#
root = helma.main.Server
#
# root.factory is used to retrieve the root class of the application
# when the instance has already been created when the application comes up.
# this is true for the helma server that is scripted here.
#
root.factory.class = helma.main.Server
root.factory.method = getServer
#
# Map Java classes to the prototype used to script them
# and, yes, map the root class again.
#
helma.main.Server = Root
helma.framework.core.Application = Application
helma.doc.DocApplication = DocApplication
helma.doc.DocPrototype = DocPrototype
helma.doc.DocFunction = DocFunction
helma.doc.DocProperties = DocFunction
helma.doc.DocSkin = DocFunction
helma.doc.DocTag = DocTag

17
apps/manage/readme.txt Normal file
View file

@ -0,0 +1,17 @@
To get the manage-application to work you must:
- add it to the apps.properties file with the following line:
manage
- use helma distribution 1.5 or later.
- add the following properties to server.properties:
allowAdmin = [comma-separated list of hosts or ip-addresses that
are allowed to access this application. wildcards
are only allowed in addresses, not in hostnames!]
adminAccess = <MD5-encoded credentials>
Creating the credentials can be done after you've got the application
up and running at this address: http://<your-server-name>/manage/makekey