vgritsenko 02/04/18 06:48:40 Modified: . build.xml changes.xml src/java/org/apache/cocoon cocoon.roles Added: src/java/org/apache/cocoon/components/language/markup/xsp PythonGenerator.java src/java/org/apache/cocoon/components/language/markup/xsp/python python.xconf python.xpipe xsp.xsl src/java/org/apache/cocoon/components/language/programming/python PythonLanguage.java PythonProgram.java python.xconf src/webapp/docs/samples/xsp-py hello.xsp Log: XSP pages in Python language. Due to Python syntax specifics, pages must be perfectly aligned, including comment nodes. Revision Changes Path 1.200 +4 -0 xml-cocoon2/build.xml Index: build.xml =================================================================== RCS file: /home/cvs/xml-cocoon2/build.xml,v retrieving revision 1.199 retrieving revision 1.200 diff -u -r1.199 -r1.200 --- build.xml 17 Apr 2002 13:09:02 -0000 1.199 +++ build.xml 18 Apr 2002 13:48:40 -0000 1.200 @@ -784,6 +784,10 @@ <exclude name="**/xsp/JSGenerator.java" unless="rhino.interpreter.present"/> <exclude name="**/xsp/javascript/**" unless="rhino.interpreter.present"/> + <exclude name="**/programming/python/*" unless="python.present"/> + <exclude name="**/xsp/PythonGenerator*" unless="python.present"/> + <exclude name="**/xsp/python/*" unless="python.present"/> + <exclude name="**/components/resolver/ResolverImpl.java" unless="resolver.present"/> <exclude name="**/resolver.x*" unless="resolver.present"/> 1.142 +7 -1 xml-cocoon2/changes.xml Index: changes.xml =================================================================== RCS file: /home/cvs/xml-cocoon2/changes.xml,v retrieving revision 1.141 retrieving revision 1.142 diff -u -r1.141 -r1.142 --- changes.xml 17 Apr 2002 21:50:46 -0000 1.141 +++ changes.xml 18 Apr 2002 13:48:40 -0000 1.142 @@ -4,7 +4,7 @@ <!-- History of Cocoon changes - $Id: changes.xml,v 1.141 2002/04/17 21:50:46 sylvain Exp $ + $Id: changes.xml,v 1.142 2002/04/18 13:48:40 vgritsenko Exp $ --> <changes title="History of Changes"> @@ -35,6 +35,12 @@ </devs> <release version="@version@" date="@date@"> + <action dev="VG" type="add"> + Python language support for the XSP pages. + </action> + <action dev="VG" type="add"> + Python programming language using jython interpreter. + </action> <action dev="SW" type="add" due-to="Marcus Crafter" due-to-email="[EMAIL PROTECTED]"> New SwitchSelector that uses a common context object for all map:when tests. </action> 1.21 +1 -0 xml-cocoon2/src/java/org/apache/cocoon/cocoon.roles Index: cocoon.roles =================================================================== RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/cocoon.roles,v retrieving revision 1.20 retrieving revision 1.21 diff -u -r1.20 -r1.21 --- cocoon.roles 18 Apr 2002 09:48:53 -0000 1.20 +++ cocoon.roles 18 Apr 2002 13:48:40 -0000 1.21 @@ -76,6 +76,7 @@ default-class="org.apache.avalon.excalibur.component.ExcaliburComponentSelector"> <hint shorthand="java-language" class="org.apache.cocoon.components.language.programming.java.JavaLanguage"/> <hint shorthand="js-language" class="org.apache.cocoon.components.language.programming.javascript.JavascriptLanguage"/> + <hint shorthand="python-language" class="org.apache.cocoon.components.language.programming.python.PythonLanguage"/> </role> <role name="org.apache.cocoon.components.language.generator.ProgramGenerator" 1.1 xml-cocoon2/src/java/org/apache/cocoon/components/language/markup/xsp/PythonGenerator.java Index: PythonGenerator.java =================================================================== /* * The Apache Software License, Version 1.1 * * * Copyright (c) 2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache Cocoon" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.apache.cocoon.components.language.markup.xsp; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.activity.Initializable; import org.apache.avalon.framework.parameters.Parameters; import org.apache.cocoon.environment.SourceResolver; import org.apache.cocoon.ProcessingException; import org.apache.cocoon.Constants; import org.apache.cocoon.util.ClassUtils; import org.apache.cocoon.xml.XMLizable; import org.python.util.PythonInterpreter; import org.python.core.Py; import org.python.core.PyCode; import org.python.core.PySystemState; import org.w3c.dom.Node; import org.xml.sax.helpers.AttributesImpl; import org.xml.sax.SAXException; import java.io.File; import java.io.IOException; import java.io.FileInputStream; import java.util.Collection; import java.util.Properties; import java.util.Map; public class PythonGenerator extends XSPGenerator implements Configurable, Initializable { /** * Python source file */ private File file; private PythonInterpreter python; private PyCode code; private Exception compileError; public void configure(Configuration configuration) throws ConfigurationException { this.file = new File(configuration.getChild("file").getValue()); Configuration[] dependencies = configuration.getChildren("dependency"); this.dependencies = new File[dependencies.length]; for (int i = 0; i < dependencies.length; i ++) { this.dependencies[i] = new File(dependencies[i].getValue()); } } /** * Determines whether this generator's source files have changed * * @return Whether any of the files this generator depends on has changed * since it was created */ public boolean modifiedSince(long date) { if (this.file.lastModified() < date) { return true; } for (int i = 0; i < dependencies.length; i++) { if (this.file.lastModified() < dependencies[i].lastModified()) { return true; } } return false; } public void initialize() throws Exception { try { Properties properties = new Properties(); File workDir = (File)avalonContext.get(Constants.CONTEXT_WORK_DIR); properties.setProperty("python.home", workDir.toString()); properties.setProperty("python.packages.fakepath", (String)avalonContext.get(Constants.CONTEXT_CLASSPATH)); PythonInterpreter.initialize(System.getProperties(), properties, new String[]{}); python = new PythonInterpreter(); python.set("page", this); python.set("logger", getLogger()); python.set("xspAttr", new AttributesImpl()); if (getLogger().isDebugEnabled()) { getLogger().debug("Compiling script " + file); } this.code = Py.compile_flags( new FileInputStream(this.file), this.file.toString(), "exec", null); } catch (Exception e) { this.compileError = e; } } public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par) throws ProcessingException, SAXException, IOException { super.setup(resolver, objectModel, src, par); if (this.compileError != null) { throw new ProcessingException("Failed to compile script", compileError); } python.set("objectModel", this.objectModel); python.set("request", this.request); python.set("response", this.response); python.set("context", this.context); python.set("resolver", this.resolver); python.set("parameters", this.parameters); } public void generate() throws IOException, ProcessingException { try { python.set("contentHandler", this.contentHandler); if (getLogger().isDebugEnabled()) { getLogger().debug("Executing script " + file); } python.exec(code); } catch (Exception e) { throw new ProcessingException("generate: Got Python exception", e); } } public void recycle() { python.set("contentHandler", null); python.set("objectModel", null); python.set("request", null); python.set("response", null); python.set("context", null); python.set("resolver", null); python.set("parameters", null); super.recycle(); } public void dispose() { python.set("page", null); python.set("logger", null); python.set("xspAttr", null); this.python = null; this.compileError = null; this.code = null; super.dispose(); } } 1.1 xml-cocoon2/src/java/org/apache/cocoon/components/language/markup/xsp/python/python.xconf Index: python.xconf =================================================================== <?xml version="1.0"?> <xconf xpath="cocoon/markup-languages/xsp-language[@name='xsp']" unless="target-language[@name='python']"> <!-- XSP in Python --> <target-language name="python"> <parameter name="core-logicsheet" value="resource://org/apache/cocoon/components/language/markup/xsp/python/xsp.xsl"/> </target-language> </xconf> 1.1 xml-cocoon2/src/java/org/apache/cocoon/components/language/markup/xsp/python/python.xpipe Index: python.xpipe =================================================================== <?xml version="1.0"?> <xpipe xpath="/sitemap/pipelines/pipeline[@id='optional']" unless="match[@pattern='xsp-py/*']"> <!-- XSP pages written in Python --> <map:match pattern="xsp-py/*"> <map:generate type="serverpages" src="docs/samples/xsp-py/{1}.xsp"> <map:parameter name="programming-language" value="python"/> </map:generate> <map:transform src="stylesheets/dynamic-page2html.xsl"> <map:parameter name="view-source" value="docs/samples/xsp-js/{1}.xsp"/> </map:transform> <map:serialize/> </map:match> </xpipe> 1.1 xml-cocoon2/src/java/org/apache/cocoon/components/language/markup/xsp/python/xsp.xsl Index: xsp.xsl =================================================================== <?xml version="1.0"?> <!-- $Id: xsp.xsl,v 1.1 2002/04/18 13:48:40 vgritsenko Exp $--> <!-- ***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * _________________________________________________________________________ * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * ***************************************************************************** --> <!-- * XSP Core logicsheet for the Python language * * @author <a href="mailto:[EMAIL PROTECTED]>Vadim Gritsenko</a> * @version CVS $Revision: 1.1 $ $Date: 2002/04/18 13:48:40 $ --> <xsl:stylesheet version="1.0" xmlns:xsp="http://apache.org/xsp" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:XSLTExtension="org.apache.cocoon.components.language.markup.xsp.XSLTExtension"> <xsl:output method="text"/> <xsl:variable name="xsp-uri" select="'http://apache.org/xsp'"/> <!-- this variable holds the instance of extension class to properly escape text into Java strings ovidiu: use the class name as the namespace to identify the class. This is supposedly portable across XSLT implementations. --> <xsl:variable name="extension" select="XSLTExtension:new()" xmlns:XSLTExtension="org.apache.cocoon.components.language.markup.xsp.XSLTExtension"/> <xsl:template match="/"> <code> <xsl:text>""" $Cocoon extends: org.apache.cocoon.components.language.markup.xsp.PythonGenerator$ """ </xsl:text> <xsl:for-each select="//xsp:dependency"> <xsl:text>""" $Cocoon depends: </xsl:text> <xsl:value-of select="translate(., '\','/')"/> <xsl:text>$ """ </xsl:text> </xsl:for-each> <xsl:apply-templates select="xsp:page"/> </code> </xsl:template> <xsl:template match="xsp:page"> """ Generated by XSP. Edit at your own risk, :-) Built-in beans for internal use: page - "this" in Java contentHandler - page.contentHandler xspAttr - AttributesImpl Built-in beans available for use: objectModel - Map logger - Logger context - ServletContext request - Request response - Response resolver - SourceResolver parameters - Parameters defined in the sitemap """ from java import lang from java import util <xsl:text>""" User Class "Declarations" """ </xsl:text> <xsl:apply-templates select="xsp:logic"> <xsl:with-param name="indent" select="''"/> </xsl:apply-templates> <xsl:text>""" User Class Initialization """ </xsl:text> <xsl:value-of select="xsp:init-page"/> <xsl:text>""" Document Body """ </xsl:text> <xsl:text>contentHandler.startDocument() </xsl:text> <!-- Generate top-level processing instructions --> <xsl:apply-templates select="/processing-instruction()"/> <!-- Process only 1st non-XSP element as generated root --> <xsl:call-template name="process-first-element"> <xsl:with-param name="content" select="*[not(namespace-uri(.) = $xsp-uri)][1]"/> </xsl:call-template> <xsl:text>contentHandler.endDocument() </xsl:text> </xsl:template> <xsl:template name="process-first-element"> <xsl:param name="content"/> <!-- Generate top-level namespaces declarations --> <xsl:variable name="parent-element" select="$content/.."/> <xsl:for-each select="$content/namespace::*"> <xsl:variable name="ns-prefix" select="local-name(.)"/> <xsl:variable name="ns-uri" select="string(.)"/> <!-- Declare namespaces that also exist on the parent (i.e. not locally declared), and filter out "xmlns:xmlns" namespace produced by Xerces+Saxon --> <xsl:if test="($ns-prefix != 'xmlns') and $parent-element/namespace::*[local-name(.) = $ns-prefix and string(.) = $ns-uri]"> <xsl:text>contentHandler.startPrefixMapping("</xsl:text> <xsl:value-of select="$ns-prefix"/>", "<xsl:value-of select="$ns-uri"/> <xsl:text>") </xsl:text> </xsl:if> </xsl:for-each> <xsl:text>if 1: # Process First Element </xsl:text> <!-- Generate content --> <xsl:apply-templates select="$content"> <xsl:with-param name="indent" select="''"/> </xsl:apply-templates> <!-- Close top-level namespaces declarations--> <xsl:for-each select="$content/namespace::*"> <xsl:variable name="ns-prefix" select="local-name(.)"/> <xsl:variable name="ns-uri" select="string(.)"/> <xsl:if test="($ns-prefix != 'xmlns') and $parent-element/namespace::*[local-name(.) = $ns-prefix and string(.) = $ns-uri]"> <xsl:text>contentHandler.endPrefixMapping("</xsl:text> <xsl:value-of select="local-name(.)"/> <xsl:text>") </xsl:text> </xsl:if> </xsl:for-each> </xsl:template> <xsl:template match="xsp:element"> <xsl:param name="indent"/> <xsl:variable name="zindent"> <xsl:choose> <xsl:when test="string-length(XSLTExtension:suffix($extension, preceding-sibling::xsp:text[1])) > 0"> <xsl:value-of select="XSLTExtension:suffix($extension, preceding-sibling::xsp:text[1])"/> </xsl:when> <xsl:when test="string-length(XSLTExtension:suffix($extension, preceding-sibling::text()[1])) > 0"> <xsl:value-of select="XSLTExtension:suffix($extension, preceding-sibling::text()[1])"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$indent"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="uri"> <xsl:call-template name="get-parameter"> <xsl:with-param name="name">uri</xsl:with-param> <xsl:with-param name="indent" select="$indent"/> </xsl:call-template> </xsl:variable> <xsl:variable name="prefix"> <xsl:call-template name="get-parameter"> <xsl:with-param name="name">prefix</xsl:with-param> <xsl:with-param name="indent" select="$indent"/> </xsl:call-template> </xsl:variable> <xsl:variable name="name"> <xsl:call-template name="get-parameter"> <xsl:with-param name="name">name</xsl:with-param> <xsl:with-param name="required">true</xsl:with-param> <xsl:with-param name="indent" select="$indent"/> </xsl:call-template> </xsl:variable> <xsl:variable name="raw-name"> <xsl:if test=" ($uri = '""' and $prefix != '""') or ($uri != '""' and $prefix = '""')"> <xsl:call-template name="error"> <xsl:with-param name="message">[<xsp:element>] Either both 'uri' and 'prefix' or none of them must be specified </xsl:with-param> </xsl:call-template> </xsl:if> <xsl:choose> <xsl:when test="$prefix = '""'"> <xsl:copy-of select="$name"/> </xsl:when> <xsl:otherwise> <xsl:text>(</xsl:text> <xsl:copy-of select="$prefix"/> + ":" + <xsl:copy-of select="$name"/> <xsl:text>)</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:variable> <!-- Start Element --> <xsl:value-of select="$zindent"/> <xsl:text># <</xsl:text> <xsl:value-of select="name(.)"/> <xsl:text>> </xsl:text> <!-- Declare namespaces that are not already present on the parent element. Note : we could use "../../namespace::*[...]" to get parent element namespaces but Xalan 2.0.1 retunrs only the first namespace (Saxon is OK). That's why we store the parent element in a variable --> <xsl:variable name="parent-element" select=".."/> <xsl:for-each select="namespace::*"> <xsl:variable name="ns-prefix" select="local-name(.)"/> <xsl:variable name="ns-uri" select="string(.)"/> <xsl:if test="not($parent-element/namespace::*[local-name(.) = $ns-prefix and string(.) = $ns-uri])"> <xsl:value-of select="$zindent"/> <xsl:text>contentHandler.startPrefixMapping("</xsl:text> <xsl:value-of select="local-name(.)"/>", "<xsl:value-of select="."/> <xsl:text>") </xsl:text> </xsl:if> </xsl:for-each> <!-- Declare namespace defined by @uri and @prefix attribute --> <xsl:if test="$uri != '""'"> <xsl:if test="not($parent-element/namespace::*[local-name(.) = $prefix and string(.) = $uri])"> <xsl:value-of select="$zindent"/> <xsl:text>contentHandler.startPrefixMapping(</xsl:text> <xsl:value-of select="$prefix"/>, <xsl:value-of select="$uri"/> <xsl:text>) </xsl:text> </xsl:if> <xsl:for-each select="$parent-element/namespace::*[local-name(.) = $prefix and string(.) = $uri]"> </xsl:for-each> </xsl:if> <!-- Attributes --> <xsl:apply-templates select="xsp:attribute | xsp:logic[xsp:attribute]"> <xsl:with-param name="indent" select="$zindent"/> </xsl:apply-templates> <xsl:value-of select="$zindent"/> <xsl:text>contentHandler.startElement(</xsl:text> <xsl:copy-of select="$uri"/>, <xsl:copy-of select="$name"/>, <xsl:copy-of select="$raw-name"/> <xsl:text>, xspAttr) </xsl:text> <xsl:value-of select="$zindent"/> <xsl:text>xspAttr.clear() </xsl:text> <xsl:value-of select="$zindent"/> <xsl:text>if 1: </xsl:text> <!-- Element body --> <xsl:apply-templates select="node()[not( (namespace-uri(.) = $xsp-uri and local-name(.) = 'attribute') or (namespace-uri(.) = $xsp-uri and local-name(.) = 'logic' and ./xsp:attribute) )]"> <xsl:with-param name="indent" select="concat($zindent, ' ')"/> </xsl:apply-templates> <xsl:value-of select="$zindent"/> <xsl:text>contentHandler.endElement(</xsl:text> <xsl:copy-of select="$uri"/>, <xsl:copy-of select="$name"/>, <xsl:copy-of select="$raw-name"/> <xsl:text>) </xsl:text> <!-- Declare namespace defined by @uri and @prefix attribute --> <xsl:if test="$uri != '""'"> <xsl:if test="not($parent-element/namespace::*[local-name(.) = $prefix and string(.) = $uri])"> <xsl:value-of select="$zindent"/> <xsl:text>contentHandler.endPrefixMapping(</xsl:text> <xsl:value-of select="$prefix"/> <xsl:text>) </xsl:text> </xsl:if> <xsl:for-each select="$parent-element/namespace::*[local-name(.) = $prefix and string(.) = $uri]"> </xsl:for-each> </xsl:if> <!-- End Namespaces --> <xsl:for-each select="namespace::*"> <xsl:variable name="ns-prefix" select="local-name(.)"/> <xsl:variable name="ns-uri" select="string(.)"/> <xsl:if test="not($parent-element/namespace::*[local-name(.) = $ns-prefix and string(.) = $ns-uri])"> <xsl:value-of select="$zindent"/> <xsl:text>contentHandler.endPrefixMapping("</xsl:text> <xsl:value-of select="local-name(.)"/> <xsl:text>") </xsl:text> </xsl:if> </xsl:for-each> <!-- End Element --> <xsl:value-of select="$zindent"/> <xsl:text># </</xsl:text> <xsl:value-of select="name(.)"/> <xsl:text>> </xsl:text> </xsl:template> <xsl:template match="xsp:attribute"> <xsl:param name="indent" select="XSLTExtension:suffix($extension, preceding-sibling::text()[1])"/> <xsl:variable name="uri"> <xsl:call-template name="get-parameter"> <xsl:with-param name="name">uri</xsl:with-param> <xsl:with-param name="indent" select="$indent"/> </xsl:call-template> </xsl:variable> <xsl:variable name="prefix"> <xsl:call-template name="get-parameter"> <xsl:with-param name="name">prefix</xsl:with-param> <xsl:with-param name="indent" select="$indent"/> </xsl:call-template> </xsl:variable> <xsl:variable name="name"> <xsl:call-template name="get-parameter"> <xsl:with-param name="name">name</xsl:with-param> <xsl:with-param name="required">true</xsl:with-param> <xsl:with-param name="indent" select="$indent"/> </xsl:call-template> </xsl:variable> <xsl:variable name="raw-name"> <xsl:if test=" ($uri = '""' and $prefix != '""') or ($uri != '""' and $prefix = '""') "> <xsl:call-template name="error"> <xsl:with-param name="message">[<xsp:attribute>] Either both 'uri' and 'prefix' or none of them must be specified </xsl:with-param> </xsl:call-template> </xsl:if> <xsl:choose> <xsl:when test="$prefix = '""'"> <xsl:copy-of select="$name"/> </xsl:when> <xsl:otherwise> <xsl:text>(</xsl:text> <xsl:copy-of select="$prefix"/> + ":" + <xsl:copy-of select="$name"/> <xsl:text>)</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="content"> <xsl:for-each select="text()|xsp:expr|xsp:text"> <xsl:if test="position() > 1"> <xsl:text> + </xsl:text> </xsl:if> <xsl:choose> <xsl:when test="namespace-uri(.) = $xsp-uri and local-name(.) = 'expr'"> <xsl:text>(</xsl:text> <xsl:value-of select="."/> <xsl:text>)</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>"</xsl:text> <xsl:value-of select="."/> <xsl:text>"</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:for-each> <xsl:if test="not(text()|xsp:expr|xsp:text)"> <xsl:text>""</xsl:text> </xsl:if> </xsl:variable> <xsl:text> </xsl:text> <xsl:value-of select="$indent"/> <xsl:text>xspAttr.addAttribute(</xsl:text> <xsl:copy-of select="$uri"/>, <xsl:copy-of select="$name"/>, <xsl:copy-of select="$raw-name"/> <xsl:text>, "CDATA", </xsl:text><xsl:value-of select="normalize-space($content)"/> <xsl:text>) </xsl:text> </xsl:template> <xsl:template match="xsp:expr"> <xsl:variable name="indent"> <xsl:choose> <xsl:when test="preceding-sibling::xsp:text[1]"> <xsl:value-of select="XSLTExtension:suffix($extension, preceding-sibling::xsp:text[1])"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="XSLTExtension:suffix($extension, preceding-sibling::text()[1])"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:choose> <xsl:when test="namespace-uri(..) = $xsp-uri and local-name(..) != 'content' and local-name(..) != 'element'"> <!-- Expression is nested inside another XSP tag: preserve its Java type --> <xsl:text>(</xsl:text> <xsl:value-of select="."/> <xsl:text>)</xsl:text> </xsl:when> <xsl:when test="string-length(.) = 0"> <!-- Do nothing --> </xsl:when> <xsl:otherwise> <!-- Output the value as elements or character data depending on its type --> <xsl:value-of select="$indent"/> <xsl:text>page.xspExpr(</xsl:text> <xsl:value-of select="."/> <xsl:text>) </xsl:text> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- FIXME: Is this _really_ necessary? --> <xsl:template match="xsp:content"> <xsl:variable name="zindent" select="XSLTExtension:suffix($extension, preceding-sibling::text()[1])"/> <xsl:text> </xsl:text> <xsl:value-of select="$zindent"/> <xsl:text># <xsp:content> </xsl:text> <xsl:value-of select="$zindent"/> <xsl:text>if 1: </xsl:text> <xsl:apply-templates> <xsl:with-param name="indent" select="XSLTExtension:suffix($extension, text()[1])"/> </xsl:apply-templates> <xsl:text> </xsl:text> <xsl:value-of select="$zindent"/> <xsl:text># </xsp:content> </xsl:text> </xsl:template> <xsl:template match="xsp:logic"> <xsl:variable name="zindent" select="XSLTExtension:suffix($extension, preceding-sibling::xsp:text[1])"/> <xsl:value-of select="$zindent"/> <xsl:text># <xsp:logic> </xsl:text> <xsl:value-of select="$zindent"/> <xsl:text>if 1: </xsl:text> <xsl:apply-templates/> <xsl:text> </xsl:text> <xsl:value-of select="$zindent"/> <xsl:text># </xsp:logic> </xsl:text> </xsl:template> <xsl:template match="xsp:pi"> <xsl:variable name="indent" select="XSLTExtension:suffix($extension, preceding-sibling::text()[1])"/> <xsl:variable name="target"> <xsl:call-template name="get-parameter"> <xsl:with-param name="name">target</xsl:with-param> <xsl:with-param name="indent" select="$indent"/> </xsl:call-template> </xsl:variable> <xsl:variable name="content"> <xsl:for-each select="text()|xsp:expr"> <xsl:choose> <xsl:when test="namespace-uri(.) = $xsp-uri and local-name(.) = 'expr'"> <xsl:text>String(</xsl:text> <xsl:value-of select="."/> <xsl:text>)</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>"</xsl:text> <xsl:value-of select="."/> <xsl:text>"</xsl:text> </xsl:otherwise> </xsl:choose> <xsp:text> + </xsp:text> </xsl:for-each> <xsl:text>""</xsl:text> </xsl:variable> <xsl:value-of select="$indent"/> <xsl:text>contentHandler.processingInstruction(</xsl:text> <xsl:copy-of select="$target"/>, <xsl:value-of select="normalize-space($content)"/> <xsl:text>) </xsl:text> </xsl:template> <!-- FIXME: How to create comments in SAX? --> <xsl:template match="xsp:comment"> <xsl:variable name="indent" select="XSLTExtension:suffix($extension, preceding-sibling::text()[1])"/> <xsl:value-of select="$indent"/> <xsl:text>page.xspComment("</xsl:text> <xsl:value-of select="."/> <xsl:text>") </xsl:text> </xsl:template> <xsl:template match="*[not(namespace-uri(.) = $xsp-uri)]"> <xsl:param name="indent"/> <xsl:variable name="text-siblings" select="preceding-sibling::xsp:text[string-length(XSLTExtension:suffix($extension, .)) > 0]"/> <xsl:variable name="textn-siblings" select="preceding-sibling::text()[string-length(XSLTExtension:suffix($extension, .)) > 0]"/> <xsl:variable name="zindent"> <xsl:choose> <xsl:when test="$text-siblings"> <xsl:value-of select="XSLTExtension:suffix($extension, $text-siblings[1])"/> </xsl:when> <xsl:when test="$textn-siblings"> <xsl:value-of select="XSLTExtension:suffix($extension, $textn-siblings[1])"/> </xsl:when> <!-- <xsl:when test="string-length(XSLTExtension:suffix($extension, preceding-sibling::xsp:text[1])) > 0"> <xsl:value-of select="XSLTExtension:suffix($extension, preceding-sibling::xsp:text[1])"/> </xsl:when> <xsl:when test="string-length(XSLTExtension:suffix($extension, preceding-sibling::text()[1])) > 0"> <xsl:value-of select="XSLTExtension:suffix($extension, preceding-sibling::text()[1])"/> </xsl:when> --> <xsl:otherwise> <xsl:value-of select="$indent"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <!-- Start Element --> <xsl:value-of select="$zindent"/> <xsl:text># <</xsl:text> <xsl:value-of select="name(.)"/> <xsl:text>> </xsl:text> <xsl:variable name="parent-element" select=".."/> <xsl:for-each select="namespace::*"> <xsl:variable name="ns-prefix" select="local-name(.)"/> <xsl:variable name="ns-uri" select="string(.)"/> <xsl:if test="not($parent-element/namespace::*[local-name(.) = $ns-prefix and string(.) = $ns-uri])"> <xsl:value-of select="$zindent"/> <xsl:text>contentHandler.startPrefixMapping("</xsl:text> <xsl:value-of select="local-name(.)"/>", "<xsl:value-of select="."/> <xsl:text>") </xsl:text> </xsl:if> </xsl:for-each> <xsl:apply-templates select="@*"/> <xsl:apply-templates select="xsp:attribute | xsp:logic[xsp:attribute]"> <xsl:with-param name="indent" select="$zindent"/> </xsl:apply-templates> <xsl:value-of select="$zindent"/> <xsl:text>contentHandler.startElement("</xsl:text> <xsl:value-of select="namespace-uri(.)"/>", "<xsl:value-of select="local-name(.)"/>", "<xsl:value-of select="name(.)"/> <xsl:text>", xspAttr) </xsl:text> <xsl:value-of select="$zindent"/> <xsl:text>xspAttr.clear() </xsl:text> <xsl:value-of select="$zindent"/> <xsl:text>if 1: </xsl:text> <xsl:apply-templates select="node()[not( (namespace-uri(.) = $xsp-uri and local-name(.) = 'attribute') or (namespace-uri(.) = $xsp-uri and local-name(.) = 'logic' and ./xsp:attribute) )]"> <xsl:with-param name="indent" select="concat($zindent, ' ')"/> </xsl:apply-templates> <xsl:value-of select="$zindent"/> <xsl:text>contentHandler.endElement("</xsl:text> <xsl:value-of select="namespace-uri(.)"/>", "<xsl:value-of select="local-name(.)"/>", "<xsl:value-of select="name(.)"/> <xsl:text>") </xsl:text> <xsl:for-each select="namespace::*"> <xsl:variable name="ns-prefix" select="local-name(.)"/> <xsl:variable name="ns-uri" select="string(.)"/> <xsl:if test="not($parent-element/namespace::*[local-name(.) = $ns-prefix and string(.) = $ns-uri])"> <xsl:value-of select="$zindent"/> <xsl:text>contentHandler.endPrefixMapping("</xsl:text> <xsl:value-of select="local-name(.)"/> <xsl:text>") </xsl:text> </xsl:if> </xsl:for-each> <!-- End Element --> <xsl:value-of select="$zindent"/> <xsl:text># </</xsl:text> <xsl:value-of select="name(.)"/> <xsl:text>> </xsl:text> </xsl:template> <xsl:template match="@*"> <xsl:param name="indent" select="XSLTExtension:suffix($extension, preceding-sibling::text()[1])"/> <!-- Filter out namespace declaration attributes --> <xsl:if test="not(starts-with(name(.), 'xmlns:'))"> <xsl:value-of select="$indent"/> <xsl:text>xspAttr.addAttribute("</xsl:text> <xsl:value-of select="namespace-uri(.)"/>", "<xsl:value-of select="local-name(.)"/>", "<xsl:value-of select="name(.)"/>", "CDATA", "<xsl:value-of select="."/> <xsl:text>") </xsl:text> </xsl:if> </xsl:template> <xsl:template match="xsp:text"> <xsl:param name="indent"/> <xsl:variable name="text-siblings" select="preceding-sibling::xsp:text[string-length(XSLTExtension:suffix($extension, .)) > 0]"/> <xsl:variable name="zindent"> <xsl:choose> <xsl:when test="string-length(XSLTExtension:prefix($extension, .)) > 0"> <xsl:value-of select="XSLTExtension:prefix($extension, .)"/> </xsl:when> <xsl:when test="$text-siblings"> <xsl:value-of select="XSLTExtension:suffix($extension, $text-siblings[1])"/> </xsl:when> <!-- <xsl:when test="string-length(XSLTExtension:suffix($extension, preceding-sibling::xsp:text[1])) > 0"> <xsl:value-of select="XSLTExtension:suffix($extension, preceding-sibling::xsp:text[1])"/> </xsl:when> --> <xsl:otherwise> <xsl:value-of select="$indent"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:choose> <xsl:when test="namespace-uri(..) = $xsp-uri and (local-name(..) = 'logic' or local-name(..) = 'expr')"> <xsl:value-of select="."/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$zindent"/> <xsl:text>page.xspCharacters("</xsl:text> <xsl:value-of select="XSLTExtension:escape($extension, .)"/> <xsl:text>") </xsl:text> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="text()" mode="value"> <xsl:value-of select="."/> </xsl:template> <xsl:template match="processing-instruction()"> <xsl:text> </xsl:text> <xsl:text>contentHandler.processingInstruction("</xsl:text> <xsl:value-of select="name()"/>", "<xsl:value-of select="."/> <xsl:text>") </xsl:text> </xsl:template> <!-- Utility templates --> <xsl:template name="get-parameter"> <xsl:param name="indent" select="'????'"/> <xsl:param name="name"/> <xsl:param name="default"/> <xsl:param name="required">false</xsl:param> <xsl:choose> <xsl:when test="@*[name(.) = $name]">"<xsl:value-of select="@*[name(.) = $name]"/>"</xsl:when> <xsl:when test="(*[namespace-uri(.)=$xsp-uri and local-name(.) = 'param'])[@name = $name]"> <xsl:call-template name="get-parameter-content"> <xsl:with-param name="content" select="(*[namespace-uri(.)=$xsp-uri and local-name(.) = 'param'])[@name = $name]"/> <xsl:with-param name="indent" select="$indent"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:choose> <xsl:when test="string-length($default) = 0"> <xsl:choose> <xsl:when test="$required = 'true'"> <xsl:call-template name="error"> <xsl:with-param name="message">[Logicsheet processor] Parameter '<xsl:value-of select="$name"/>' missing in dynamic tag <<xsl:value-of select="name(.)"/>> </xsl:with-param> </xsl:call-template> </xsl:when> <xsl:otherwise>""</xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise><xsl:copy-of select="$default"/></xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-parameter-content"> <xsl:param name="indent" select="'????'"/> <xsl:param name="content"/> <xsl:choose> <xsl:when test="$content/*[namespace-uri(.)=$xsp-uri and local-name(.) != 'text']"> <xsl:apply-templates select="$content/*[namespace-uri(.)=$xsp-uri and local-name(.) != 'text']"> <xsl:with-param name="indent" select="$indent"/> </xsl:apply-templates> </xsl:when> <xsl:otherwise>"<xsl:value-of select="$content"/>"</xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-nested-content"> <xsl:param name="indent" select="'????'"/> <xsl:param name="content"/> <xsl:choose> <xsl:when test="$content/*"> <xsl:apply-templates select="$content/*"> <xsl:with-param name="indent" select="$indent"/> </xsl:apply-templates> </xsl:when> <xsl:otherwise>"<xsl:value-of select="$content"/>"</xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="error"> <xsl:param name="message"/> <xsl:message terminate="yes"><xsl:value-of select="$message"/></xsl:message> </xsl:template> <!-- Ignored elements --> <xsl:template match="xsp:logicsheet|xsp:dependency|xsp:param"/> </xsl:stylesheet> 1.1 xml-cocoon2/src/java/org/apache/cocoon/components/language/programming/python/PythonLanguage.java Index: PythonLanguage.java =================================================================== /* * The Apache Software License, Version 1.1 * * * Copyright (c) 2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache Cocoon" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.apache.cocoon.components.language.programming.python; import org.apache.cocoon.components.language.programming.AbstractProgrammingLanguage; import org.apache.cocoon.components.language.programming.ProgrammingLanguage; import org.apache.cocoon.components.language.programming.Program; import org.apache.cocoon.components.language.LanguageException; import org.apache.cocoon.components.language.markup.xsp.XSLTExtension; import org.apache.cocoon.util.IOUtils; import org.apache.cocoon.util.ClassUtils; import java.io.File; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.FileInputStream; import java.util.ArrayList; public class PythonLanguage extends AbstractProgrammingLanguage implements ProgrammingLanguage { public Program preload(String filename, File baseDirectory, String encoding) throws LanguageException { return load(filename, baseDirectory, encoding); } public Program load(String filename, File baseDirectory, String encoding) throws LanguageException { // Does source file exist? File sourceFile = new File(baseDirectory, filename + "." + this.getSourceExtension()); if (!sourceFile.exists()) { throw new LanguageException("Can't load program - File doesn't exist: " + IOUtils.getFullFilename(sourceFile)); } if (!sourceFile.isFile()) { throw new LanguageException("Can't load program - File is not a normal file: " + IOUtils.getFullFilename(sourceFile)); } if (!sourceFile.canRead()) { throw new LanguageException("Can't load program - File cannot be read: " + IOUtils.getFullFilename(sourceFile)); } Class clazz = null; ArrayList dependecies = new ArrayList(); String className = null; BufferedReader r = null; try { r = new BufferedReader( (encoding == null)? new FileReader(sourceFile): new InputStreamReader(new FileInputStream(sourceFile), encoding)); className = getMeta(r.readLine(), "extends"); if (className == null) { throw new LanguageException("Can't load program - Signature is not found: " + IOUtils.getFullFilename(sourceFile)); } clazz = ClassUtils.loadClass(className); String line; while((line = getMeta(r.readLine(), "depends")) != null) { dependecies.add(line); } } catch (IOException e) { throw new LanguageException("Can't load program - Signature is not found: " + IOUtils.getFullFilename(sourceFile)); } catch (ClassNotFoundException e) { throw new LanguageException("Can't load program - Base class " + className + " is not found: " + IOUtils.getFullFilename(sourceFile)); } finally { if (r != null) try { r.close(); } catch (IOException ignored) { } } return new PythonProgram(sourceFile, clazz, dependecies); } private String getMeta(String line, String meta) { if (line == null) { return null; } meta = "$Cocoon " + meta + ": "; int i = line.indexOf(meta); if (i != -1) { int j = line.indexOf("$", i + 1); if (j != -1) { line = line.substring(i + meta.length(), j); } else { line = null; } } else { line = null; } return line; } protected void doUnload(Object program, String filename, File baseDir) throws LanguageException { // Do nothing. Source is already deleted by the AbstractProgrammingLanguage. } public String quoteString(String constant) { return XSLTExtension.escapeString(constant); } /** * Return the language's canonical source file extension. * * @return The source file extension */ public String getSourceExtension() { return "py"; } } 1.1 xml-cocoon2/src/java/org/apache/cocoon/components/language/programming/python/PythonProgram.java Index: PythonProgram.java =================================================================== /* * The Apache Software License, Version 1.1 * * * Copyright (c) 2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache Cocoon" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.apache.cocoon.components.language.programming.python; import org.apache.avalon.framework.configuration.DefaultConfiguration; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.component.ComponentManager; import org.apache.avalon.framework.context.Context; import org.apache.avalon.excalibur.component.ComponentHandler; import org.apache.avalon.excalibur.component.RoleManager; import org.apache.avalon.excalibur.logger.LogKitManager; import org.apache.cocoon.components.language.programming.Program; import org.apache.cocoon.components.language.generator.CompiledComponent; import java.io.File; import java.util.Collection; import java.util.Iterator; public class PythonProgram implements Program { protected File file; protected Class clazz; protected DefaultConfiguration config; public PythonProgram(File file, Class clazz, Collection dependecies) { this.file = file; this.clazz = clazz; config = new DefaultConfiguration("", "GeneratorSelector"); DefaultConfiguration child = new DefaultConfiguration("file", ""); child.setValue(file.toString()); config.addChild(child); for (Iterator i = dependecies.iterator(); i.hasNext(); ) { child = new DefaultConfiguration("dependency", ""); child.setValue(i.next().toString()); config.addChild(child); } } public String getName() { return file.toString(); } public ComponentHandler getHandler(ComponentManager manager, Context context, RoleManager roles, LogKitManager logKitManager) throws Exception { return ComponentHandler.getComponentHandler( clazz, config, manager, context, roles, logKitManager); } public CompiledComponent newInstance() throws Exception { CompiledComponent instance = (CompiledComponent) clazz.newInstance(); if (instance instanceof Configurable) ((Configurable) instance).configure(config); return instance; } } 1.1 xml-cocoon2/src/java/org/apache/cocoon/components/language/programming/python/python.xconf Index: python.xconf =================================================================== <?xml version="1.0"?> <xconf xpath="cocoon/programming-languages" unless="python-language"> <!-- Python language --> <python-language name="python" logger="core.language.python"/> </xconf> 1.1 xml-cocoon2/src/webapp/docs/samples/xsp-py/hello.xsp Index: hello.xsp =================================================================== <?xml version="1.0" encoding="ISO-8859-1"?> <xsp:page language="python" xmlns:xsp="http://apache.org/xsp"> <page> <title>Hello from XSP page in Python</title> <para> <b>This</b> is my first <b>Cocoon</b> page! </para> <xsp:element> <xsp:param name="name">para</xsp:param> With the help of XSP and Python! </xsp:element> <para> <xsp:logic> align = "center"; <p> <xsp:attribute name="align"><xsp:expr>align</xsp:expr></xsp:attribute> <xsp:logic> msg = "Executed at: " import time now = time.asctime(time.localtime()) <xsp:content> Executed at: <xsp:expr>now</xsp:expr> </xsp:content> </xsp:logic> </p> </xsp:logic> </para> </page> </xsp:page>
---------------------------------------------------------------------- In case of troubles, e-mail: [EMAIL PROTECTED] To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]