/*
* $Id: SystemModule.java,v 1.36 2002/09/16 08:05:03 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.core.system;
import anvil.core.Any;
import anvil.core.AnyString;
import anvil.core.Array;
import anvil.core.io.AnyFile;
import anvil.core.io.AnyInputStream;
import anvil.core.time.AnyCalendar;
import anvil.parser.DocumentHandler;
import anvil.parser.Locator;
import anvil.parser.Parser;
import anvil.parser.StreamInputSource;
import anvil.parser.Tag;
import anvil.script.Context;
import anvil.script.parser.Token;
import anvil.script.parser.Tokenizer;
import anvil.script.parser.ParserBaseConstants;
import anvil.script.statements.Statement;
import anvil.script.ModuleEnvelope;
import anvil.script.ModuleCache;
import anvil.util.Conversions;
import anvil.Version;
import anvil.server.Server;
import anvil.server.Address;
import anvil.server.Resource;
import anvil.server.Configurable;
import anvil.server.ApplicationPreferences;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Properties;
import java.util.TimeZone;
///
/// @module anvil.system
/// Provides access to system related operations,
/// such as server's resources and configuration.
public class SystemModule implements ParserBaseConstants
{
/// @function rawImport
/// Imports resource pointed at given path 'as is'.
/// @synopsis Resource rawImport(string pathinfo)
/// @throws ImportError If import failed
public static final Any rawImport(Context context, String pathinfo)
{
Address address = context.address();
Address importing = null;
try {
importing = address.resolve(pathinfo);
} catch (anvil.server.ZoneInactiveException e) {
throw context.ImportError(e.getMessage(), null);
}
context.checkImport(importing.getPathinfo());
try {
Resource resource = importing.openResource();
return new AnyResource(resource);
} catch (anvil.server.ContainerException t) {
throw context.ImportError(t.getMessage(), null);
}
}
/// @function getVersion
/// Returns the version of Anvil software.
/// @synopsis string getVersion()
public static final Any getVersion()
{
return Any.create(anvil.Version.getVersion());
}
/// @function getBuild
/// Returns the build id of Anvil software.
/// @synopsis string getBuild()
public static final Any getBuild()
{
return Any.create(anvil.Version.getBuild());
}
/// @function getFullVersion
/// Returns the full version of Anvil software.
/// @synopsis string getFullVersion()
public static final Any getFullVersion()
{
return Any.create(anvil.Version.getFullVersion());
}
/// @function getTotalMemory
/// Returns the total size of memory allocated for JVM heap, in bytes.
/// @synopsis int getTotalMemory()
public static final Any getTotalMemory()
{
return Any.create(Runtime.getRuntime().totalMemory());
}
/// @function getFreeMemory
/// Returns the amount of free memory at JVM heap, in bytes.
/// @synopsis int getFreeMemory()
public static final Any getFreeMemory()
{
return Any.create(Runtime.getRuntime().freeMemory());
}
/// @function getProperty
/// Returns a named property from <code>application</code> configuration
/// section, or <code>undefined</code> if property does not exist.
/// @synopsis string getProperty(string propertyName)
public static final Any getProperty(Context context, String property)
{
ApplicationPreferences app = context.address().getZone().getApplicationPreferences();
return (app != null) ?
Any.create(app.getPreference(property)) : Any.UNDEFINED;
}
/// @function getProperties
/// Returns an array containing all the properties from
/// <code>application</code> configuration section.
/// @synopsis array getProperties()
public static final Any getProperties(Context context)
{
Array props = new Array();
ApplicationPreferences app = context.address().getZone().getApplicationPreferences();
if (app != null) {
String[] names = app.getAdditionalPreferenceNames();
final int n = names.length;
for(int i=0; i<n; i++) {
props.put(new AnyString(names[i]), Any.create(app.getPreference(names[i])));
}
}
return props;
}
/// @function getSystemProperty
/// Returns a system property from underlying JVM.
/// @synopsis string getSystemProperty(string propertyName)
public static final Any getSystemProperty(String property)
{
if (property.equals("anvil.version")) {
return Any.create(anvil.Version.getVersion());
} else if (property.equals("anvil.build")) {
return Any.create(anvil.Version.getBuild());
} else if (property.equals("anvil.fullversion")) {
return Any.create(anvil.Version.getFullVersion());
} else {
return Any.create(System.getProperty(property));
}
}
/// @function getSystemProperties
/// Returns an array of system properties from underlying JVM.
/// @synopsis array getSystemProperties()
public static final Any getSystemProperties()
{
Properties properties = System.getProperties();
Array list = new Array(properties.size());
list.append("anvil.version", Any.create(anvil.Version.getVersion()));
list.append("anvil.build", Any.create(anvil.Version.getBuild()));
list.append("anvil.fullversion", Any.create(anvil.Version.getFullVersion()));
Enumeration e = properties.propertyNames();
while(e.hasMoreElements()) {
String name = (String)e.nextElement();
list.append(name, Any.create(properties.getProperty(name)));
}
return Any.create(list);
}
/// @function getServer
/// Returns the root configuration.
/// @synopsis Configurable getServer()
public static final Any getServer(Context context)
{
context.checkAccess(anvil.core.system.AnyConfigurable.CAN_READ);
return new AnyConfigurable(context.address().getServer());
}
private static final InputStream getInputStream(Context context, Any source) throws IOException
{
if (source instanceof AnyFile) {
File file = (File)source.toObject();
context.checkRead(file.getPath());
return new FileInputStream(file);
} else if (source instanceof AnyInputStream) {
return (InputStream)source.toObject();
} else {
return new ByteArrayInputStream(source.toString().getBytes());
}
}
/// @function formatScript
/// Assumes data pointed by given parameter is an anvil script
/// and formats and outputs it accordingly.
/// If optional handler is given it may contain any number of predefined
/// callbacks, which should output representation of
/// element they reflect.
/// <ul>
/// <li><code>onWhitespace(line, column, image)</code> - called on whitespace sequences
/// <li><code>onComment(line, column, image)</code> - called on comments
/// <li><code>onString(line, column, image)</code> - called on strings literals
/// <li><code>onNumber(line, column, image)</code> - called on number literals
/// <li><code>onPattern(line, column, image)</code> - called on pattern literals
/// <li><code>onSymbol(line, column, image)</code> - called on symbols
/// <li><code>onDelimiter(line, column, image)</code> - called on delimiter operator
/// <li><code>onOperator(line, column, image)</code> - called on operator
/// <li><code>onOperatorKeyword(line, column, image)</code> - called on operator keyword
/// <li><code>onKeyword(line, column, image)</code> - called on keyword
/// <li><code>onDefault(line, column, image)</code> - called on anything else
/// </ul>
/// <p>
/// Handler may be:
/// <ul><li>class instance, returning functions or method delegates
/// <li>scope of functions (module, namespace, class, interface)
/// <li>array of functions or delegates
/// </ul>
/// </p>
/// @synopsis void formatScript(File file [, object handler] )
/// @synopsis void formatScript(InputStream inputStream [, object handler] )
/// @synopsis void formatScript(string script [, object handler] )
/// @throw
public static final Object[] p_formatScript = { null, "source", "*handler", null };
public static final Any formatScript(Context context, Any source, Any handler)
{
try {
InputStream input = getInputStream(context, source);
Tokenizer tokenizer = new Tokenizer(input, true);
FormattingCallbacks calls = new FormattingCallbacks(context, handler);
Token t = null;
out: for (;;) {
if ((t != null) && (t.next != null)) {
t = t.next;
} else {
t = tokenizer.getNextToken();
}
switch(t.kind) {
case Tokenizer.EOF:
break out;
case Tokenizer.WHITESPACE:
calls.onWhitespace(t);
break;
case Tokenizer.COMMENT:
case Tokenizer.DOC_COMMENT:
calls.onComment(t);
break;
case Tokenizer.FLOATING_POINT_LITERAL:
case Tokenizer.INTEGER_LITERAL:
calls.onNumber(t);
break;
case Tokenizer.STRING_LITERAL:
calls.onString(t);
break;
case Tokenizer.PATTERN:
calls.onPattern(t);
break;
case Tokenizer.SYMBOL:
calls.onSymbol(t);
break;
case LESS:
case LESS_OR_EQUAL:
case GREATER:
case GREATER_OR_EQUAL:
case ET:
t.image = anvil.util.Conversions.encodeEntities(t.image);
calls.onOperator(t);
break;
case BEGIN_LIST:
case BEGIN:
case END:
case OPEN:
case CLOSE:
case OPEN_BRACKET:
case CLOSE_BRACKET:
case COMMA:
case SEMICOLON:
case DOT:
calls.onDelimiter(t);
break;
case COLON:
case CARET:
case STAR:
case ASSIGN:
case RANGE:
case PIPE:
case BOOLEAN_OR:
case HOOK:
case ASSIGN_ADD:
case ASSIGN_SUBSTRACT:
case ASSIGN_MULTIPLY:
case ASSIGN_DIVIDE:
case ASSIGN_REMAINDER:
case ASSIGN_CONCAT:
case ASSIGN_INIT:
case MAP:
case HOOKHOOK:
case BOOLEAN_XOR:
case BOOLEAN_AND:
case EQUAL:
case NOT_EQUAL:
case EXACT_EQUAL:
case EXACT_NOT_EQUAL:
case COMPARE:
case EXACT_COMPARE:
case NEGATION:
case PLUS:
case MINUS:
case SLASH:
case REMAINDER:
case MATCH:
case NO_MATCH:
case MINUSMINUS:
case PLUSPLUS:
case AT:
case ARROW:
calls.onOperator(t);
break;
case IN:
case IS:
case NULL:
case COPYOF:
case CLONEOF:
case TYPEOF:
case SIZEOF:
case CLASSOF:
case BOOLEAN:
case INT:
case FLOAT:
case STRING:
case DEFINED:
case UNDEFINED:
case HAS:
case DELETE:
case INF:
case FALSE:
case TRUE:
case NEW:
calls.onOperatorKeyword(t);
break;
case MODULE:
case AS:
case IMPORT:
case FUNCTION:
case SUPER:
case SYNCHRONIZED:
case INTERFACE:
case EXTENDS:
case CLASS:
case IMPLEMENTS:
case VAR:
case CONST:
case IF:
case WHILE:
case TRY:
case CATCH:
case FINALLY:
case THROW:
case PRINT:
case PRINTLN:
case PRINTBR:
case ELSE:
case SWITCH:
case CASE:
case _DEFAULT:
case FOR:
case DO:
case FOREACH:
case BREAK:
case CONTINUE:
case EXIT:
case RETURN:
case YIELD:
case ASSERT:
case THIS:
case STATIC:
case NAMESPACE:
calls.onKeyword(t);
break;
default:
calls.onDefault(t);
}
}
input.close();
return Any.TRUE;
} catch (java.io.IOException e) {
throw context.exception(e);
}
}
/// @function formatTemplate
/// Assumes data pointed by given parameter is an anvil template
/// and formats and outputs it accordingly.
/// If optional handler is given it may contain any number of predefined
/// callbacks, which should output representation of
/// element they reflect.
/// <ul>
/// <li><code>onCharacters(line, column, cdata)</code> - called on character data
/// <li><code>onHtmlComment(line, column, cdata)</code> - called on HTML comment
/// <li><code>onProcessingInstruction(line, column, cdata)</code> - called on processing instruction
/// <li><code>onTagStart(line, column, tagname)</code> - called on start of tag
/// <li><code>onTagEnd(line, column, hasEndSlash)</code> - called on end of tag
/// <li><code>onAttribute(line, column, attrName, attrValue)</code> - called on tag attribute
/// </ul></p>
/// <p>
/// Handler may be:
/// <ul><li>class instance, returning functions or method delegates
/// <li>scope of functions (module, namespace, class, interface)
/// <li>array of functions or delegates
/// </ul>
/// </p>
/// @synopsis void formatTemplate(File file [, object handler] )
/// @synopsis void formatTemplate(InputStream inputStream [, object handler] )
/// @synopsis void formatTemplate(string script [, object handler] )
public static final Object[] p_formatTemplate = { null, "source", "*handler", null };
public static final Any formatTemplate(Context context, Any source, Any handler)
{
try {
//String namespace = context.getEnvironment().getNamespace();
String namespace = null;
StreamInputSource inputSource = new StreamInputSource(getInputStream(context, source));
FormattingCallbacks callbacks = new FormattingCallbacks(context, handler);
TemplateFormatter formatter = new TemplateFormatter(callbacks, namespace);
Parser parser = new Parser();
parser.parse(formatter, inputSource);
return Any.TRUE;
} catch (java.io.IOException e) {
throw context.exception(e);
}
}
public static class TemplateFormatter implements DocumentHandler
{
private Context _context;
private String _namespace;
private FormattingCallbacks _callbacks;
public TemplateFormatter(FormattingCallbacks callbacks, String namespace)
{
_callbacks = callbacks;
_namespace = namespace;
}
public void setDocumentLocator(Locator locator)
{
_callbacks.setLocator(locator);
}
public void startDocument()
{
}
public void endDocument()
{
}
public void handleCharacters(String characters)
{
_callbacks.onCharacters(characters);
}
public void handleComment(String characters)
{
_callbacks.onHtmlComment(characters);
}
public void handleTag(Tag tag)
{
int type = Statement.ST_INVALID;
String ns = tag.getNamespace();
if (_namespace != null) {
if (ns == null) {
type = Statement.ST_TAG;
} else {
if (ns.equals(_namespace)) {
type = Statement.getTagId(tag);
} else {
type = Statement.ST_TAG;
}
}
} else {
if (ns == null) {
type = Statement.getTagId(tag);
} else {
type = Statement.ST_TAG;
}
}
if (type == Statement.ST_TAG || type == Statement.ST_INVALID) {
_callbacks.onTag(tag);
} else {
_callbacks.onCodeTag(tag);
}
}
public void handleProcessingInstruction(String data)
{
if (data.startsWith("anvil ")) {
String ns = Parser.getAttributeValue(data, "namespace");
if (ns != null) {
_namespace = ns;
}
}
_callbacks.onProcessingInstruction(data);
}
}
public static final anvil.script.compiler.NativeNamespace __module__ =
new anvil.script.compiler.NativeNamespace(
"system",
SystemModule.class,
new Class[] {
AnyConfigurable.class,
AnyEnvelope.class,
AnyResource.class,
},
//DOC{{
""+
"\n" +
" @module anvil.system\n" +
" Provides access to system related operations,\n" +
" such as server's resources and configuration.\n" +
" @function rawImport\n" +
" Imports resource pointed at given path 'as is'.\n" +
" @synopsis Resource rawImport(string pathinfo)\n" +
" @throws ImportError If import failed\n" +
" @function getVersion\n" +
" Returns the version of Anvil software.\n" +
" @synopsis string getVersion()\n" +
" @function getBuild\n" +
" Returns the build id of Anvil software.\n" +
" @synopsis string getBuild()\n" +
" @function getFullVersion\n" +
" Returns the full version of Anvil software.\n" +
" @synopsis string getFullVersion()\n" +
" @function getTotalMemory\n" +
" Returns the total size of memory allocated for JVM heap, in bytes.\n" +
" @synopsis int getTotalMemory()\n" +
" @function getFreeMemory\n" +
" Returns the amount of free memory at JVM heap, in bytes.\n" +
" @synopsis int getFreeMemory()\n" +
" @function getProperty\n" +
" Returns a named property from <code>application</code> configuration\n" +
" section, or <code>undefined</code> if property does not exist.\n" +
" @synopsis string getProperty(string propertyName)\n" +
" @function getProperties\n" +
" Returns an array containing all the properties from\n" +
" <code>application</code> configuration section.\n" +
" @synopsis array getProperties()\n" +
" @function getSystemProperty\n" +
" Returns a system property from underlying JVM.\n" +
" @synopsis string getSystemProperty(string propertyName)\n" +
" @function getSystemProperties\n" +
" Returns an array of system properties from underlying JVM.\n" +
" @synopsis array getSystemProperties()\n" +
" @function getServer\n" +
" Returns the root configuration.\n" +
" @synopsis Configurable getServer()\n" +
" @function formatScript\n" +
" Assumes data pointed by given parameter is an anvil script\n" +
" and formats and outputs it accordingly.\n" +
" If optional handler is given it may contain any number of predefined\n" +
" callbacks, which should output representation of\n" +
" element they reflect.\n" +
" <ul> \n" +
" <li><code>onWhitespace(line, column, image)</code> - called on whitespace sequences\n" +
" <li><code>onComment(line, column, image)</code> - called on comments\n" +
" <li><code>onString(line, column, image)</code> - called on strings literals\n" +
" <li><code>onNumber(line, column, image)</code> - called on number literals\n" +
" <li><code>onPattern(line, column, image)</code> - called on pattern literals\n" +
" <li><code>onSymbol(line, column, image)</code> - called on symbols\n" +
" <li><code>onDelimiter(line, column, image)</code> - called on delimiter operator\n" +
" <li><code>onOperator(line, column, image)</code> - called on operator\n" +
" <li><code>onOperatorKeyword(line, column, image)</code> - called on operator keyword\n" +
" <li><code>onKeyword(line, column, image)</code> - called on keyword\n" +
" <li><code>onDefault(line, column, image)</code> - called on anything else\n" +
" </ul>\n" +
" <p>\n" +
" Handler may be:\n" +
" <ul><li>class instance, returning functions or method delegates\n" +
" <li>scope of functions (module, namespace, class, interface)\n" +
" <li>array of functions or delegates\n" +
" </ul>\n" +
" </p>\n" +
" @synopsis void formatScript(File file [, object handler] )\n" +
" @synopsis void formatScript(InputStream inputStream [, object handler] )\n" +
" @synopsis void formatScript(string script [, object handler] )\n" +
" @throw\n" +
" @function formatTemplate\n" +
" Assumes data pointed by given parameter is an anvil template\n" +
" and formats and outputs it accordingly.\n" +
" If optional handler is given it may contain any number of predefined\n" +
" callbacks, which should output representation of\n" +
" element they reflect.\n" +
" <ul>\n" +
" <li><code>onCharacters(line, column, cdata)</code> - called on character data\n" +
" <li><code>onHtmlComment(line, column, cdata)</code> - called on HTML comment\n" +
" <li><code>onProcessingInstruction(line, column, cdata)</code> - called on processing instruction\n" +
" <li><code>onTagStart(line, column, tagname)</code> - called on start of tag\n" +
" <li><code>onTagEnd(line, column, hasEndSlash)</code> - called on end of tag\n" +
" <li><code>onAttribute(line, column, attrName, attrValue)</code> - called on tag attribute\n" +
" </ul></p>\n" +
" <p>\n" +
" Handler may be:\n" +
" <ul><li>class instance, returning functions or method delegates\n" +
" <li>scope of functions (module, namespace, class, interface)\n" +
" <li>array of functions or delegates\n" +
" </ul>\n" +
" </p>\n" +
" @synopsis void formatTemplate(File file [, object handler] )\n" +
" @synopsis void formatTemplate(InputStream inputStream [, object handler] )\n" +
" @synopsis void formatTemplate(string script [, object handler] )\n"
//}}DOC
);
}