dims 01/08/14 05:45:27
Modified: . build.xml
src/org/apache/cocoon/serialization PCLSerializer.java
PSSerializer.java
xdocs jars.xml pdf-serializer.xml uc2.xml
Added: src/org/apache/cocoon/serialization
AbstractFOPSerializer.java PDFSerializer.java
Removed: src/org/apache/cocoon/serialization FOPSerializer.java
Log:
Patch from John Morrison for "Refactored FOPSerializer".
Revision Changes Path
1.49 +4 -2 xml-cocoon2/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/xml-cocoon2/build.xml,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -r1.48 -r1.49
--- build.xml 2001/08/14 08:40:57 1.48
+++ build.xml 2001/08/14 12:45:26 1.49
@@ -113,7 +113,7 @@
Serializers
- fo2pdf serializer : Requires the FOP package (included in the dist)
- <map:serializer name="fo2pdf"
src="org.apache.cocoon.serialization.FOPSerializer"
mime-type="application/pdf"/>
+ <map:serializer name="fo2pdf"
src="org.apache.cocoon.serialization.PDFSerializer"
mime-type="application/pdf"/>
- fo2ps serializer : Requires the FOP package (included in the dist)
<map:serializer name="fo2ps"
src="org.apache.cocoon.serialization.PSSerializer" mime-type="application/ps"/>
- fo2pcl serializer : Requires the FOP package (included in the dist)
@@ -401,6 +401,8 @@
<exclude name="**/Javascript*" unless="rhino.present"/>
<exclude name="**/Jstyle*" unless="jstyle.present"/>
<exclude name="**/FOP*" unless="fop.present"/>
+ <exclude name="**/serialization/AbstractFOP*" unless="fop.present"/>
+ <exclude name="**/serialization/PDF*" unless="fop.present"/>
<exclude name="**/serialization/PCL*" unless="fop.present"/>
<exclude name="**/serialization/PS*" unless="fop.present"/>
<exclude name="**/Php*" unless="php.present"/>
@@ -572,7 +574,7 @@
<!-- ===================================================================
-->
<target name="prepare-webapp-fop" depends="copy-webapp" if="fop.present">
<java classname="st">
- <arg line="-i ${build.war}/sitemap.xmap -o ${build.war}/sitemap.xmap
-m application/pdf -a serializers fo2pdf
org.apache.cocoon.serialization.FOPSerializer"/>
+ <arg line="-i ${build.war}/sitemap.xmap -o ${build.war}/sitemap.xmap
-m application/pdf -a serializers fo2pdf
org.apache.cocoon.serialization.PDFSerializer"/>
<classpath>
<pathelement location="${bin.dir}"/>
</classpath>
1.2 +4 -156
xml-cocoon2/src/org/apache/cocoon/serialization/PCLSerializer.java
Index: PCLSerializer.java
===================================================================
RCS file:
/home/cvs/xml-cocoon2/src/org/apache/cocoon/serialization/PCLSerializer.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- PCLSerializer.java 2001/08/10 12:36:30 1.1
+++ PCLSerializer.java 2001/08/14 12:45:26 1.2
@@ -8,28 +8,6 @@
package org.apache.cocoon.serialization;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import org.apache.cocoon.caching.CacheValidity;
-import org.apache.cocoon.caching.Cacheable;
-import org.apache.cocoon.caching.NOPCacheValidity;
-import org.apache.avalon.excalibur.pool.Recyclable;
-import org.apache.avalon.framework.configuration.Configurable;
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.fop.apps.Driver;
-import org.apache.fop.apps.FOPException;
-import org.apache.fop.apps.Options;
-import org.apache.fop.apps.Version;
-import org.apache.fop.messaging.MessageEvent;
-import org.apache.fop.messaging.MessageHandler;
-import org.apache.fop.messaging.MessageListener;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-
/**
* FOP PCL serializer.
*
@@ -38,7 +16,7 @@
* @author <a href="mailto:[EMAIL PROTECTED]">Stefano Mazzocchi</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Carsten Ziegeler</a>
* @author <a href="mailto:[EMAIL PROTECTED]">John Morrison</a>
- * @version CVS $Revision: 1.1 $ $Date: 2001/08/10 12:36:30 $
+ * @version CVS $Revision: 1.2 $ $Date: 2001/08/14 12:45:26 $
*
* The use of a config file for FOP is enabled by adding a configuration
* element to the serializer in the sitemap.
@@ -47,89 +25,10 @@
* started the JVM, or absolute. If any one wants to fix this, go ahead!
* (colin britton)
*/
-public class PCLSerializer extends AbstractSerializer
-implements MessageListener, Recyclable, Configurable, Cacheable {
-
- //Declare options for FOP
- private Options options;
-
- //Declare the FOP driver
- private Driver driver;
-
- /**
- * Set the configurations for this serializer.
- */
- public void configure(Configuration conf)
- throws ConfigurationException {
- String userConfig = null;
- File userConfigFile = null;
-
- if (conf != null) {
- Configuration child = conf.getChild("user-config");
- if (child != null) {
- try{
- userConfig = child.getAttribute("src");
- } catch(Exception ex) {
- // getLogger().debug("PCLSerializer: No config file
specified ");
- }
- }
- }
-
- // Check for null, use external or inbuilt config.
- if(userConfig != null){
- try {
- userConfigFile = new File(userConfig);
- options = new Options(userConfigFile);
- getLogger().debug("PCLSerializer: Using config file " +
userConfig);
- } catch (Exception ex) {
- getLogger().error("PCLSerializer: Cannot load config "
+ userConfig, ex);
- throw new ConfigurationException("PCLSerializer: Cannot
load config " + userConfig, ex);
- }
- } else {
- try {
- options = new Options();
- getLogger().debug("PCLSerializer: Using default config
file");
- } catch (Exception e) {
- getLogger().error("PCLSerializer: Cannot load default
config ", e);
- }
- }
- }
-
-
- /**
- * Create the FOP driver
- * Set the <code>OutputStream</code> where the XML should be serialized.
- */
- public void setOutputStream(OutputStream out) {
- // load the fop driver
- this.driver = new Driver();
-
- // the use of static resources sucks for servlet enviornments
- // since we could have multiple FOP that all logs in this pipe
- // It's a concurrency and security nightmare! (SM)
- MessageHandler.setOutputMethod(MessageHandler.EVENT);
- MessageHandler.addListener(this);
+public class PCLSerializer extends AbstractFOPSerializer {
- this.driver.setRenderer(new org.apache.fop.render.pcl.PCLRenderer());
- this.driver.setOutputStream(out);
- this.setContentHandler(this.driver.getContentHandler());
- }
-
- /**
- * Receive notification of the end of a document.
- */
- public void endDocument() throws SAXException {
- super.endDocument();
- try {
- this.driver.format();
- this.driver.render();
- } catch (IOException e) {
- getLogger().error("PCLSerializer.endDocument()", e);
- throw new SAXException (e);
- } catch (FOPException e) {
- getLogger().error("PCLSerializer.endDocument()", e);
- throw new SAXException (e);
- }
+ public org.apache.fop.render.Renderer getRenderer() {
+ return new org.apache.fop.render.pcl.PCLRenderer();
}
/**
@@ -137,57 +36,6 @@
*/
public String getMimeType() {
return "application/vnd.hp-PCL";
- }
-
- /**
- * Receive FOP events.
- */
- public void processMessage (MessageEvent event) {
- // Output FOP messgaes to Cocoon logging system
- // Rather verbose, so wrote all as debug (including errors)
- // Could be cleaned up to handle different messages as required (CB)
- getLogger().debug("FOP Message: "+event.getMessage());
- }
-
- /**
- * Generate the unique key.
- * This key must be unique inside the space of this component.
- * This method must be invoked before the generateValidity() method.
- *
- * @return The generated key or <code>0</code> if the component
- * is currently not cacheable.
- */
- public long generateKey() {
- return 1;
- }
-
- /**
- * Generate the validity object.
- * Before this method can be invoked the generateKey() method
- * must be invoked.
- *
- * @return The generated validity object or <code>null</code> if the
- * component is currently not cacheable.
- */
- public CacheValidity generateValidity() {
- return new NOPCacheValidity();
- }
-
- /**
- * Recycle the component and remove it from the MessageList
- */
- public void recycle() {
- super.recycle();
- MessageHandler.removeListener(this);
- this.options = null;
- this.driver = null;
- }
-
- /**
- * Test if the component wants to set the content length
- */
- public boolean shouldSetContentLength() {
- return true;
}
}
1.2 +5 -157
xml-cocoon2/src/org/apache/cocoon/serialization/PSSerializer.java
Index: PSSerializer.java
===================================================================
RCS file:
/home/cvs/xml-cocoon2/src/org/apache/cocoon/serialization/PSSerializer.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- PSSerializer.java 2001/08/10 12:36:30 1.1
+++ PSSerializer.java 2001/08/14 12:45:26 1.2
@@ -8,37 +8,15 @@
package org.apache.cocoon.serialization;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import org.apache.cocoon.caching.CacheValidity;
-import org.apache.cocoon.caching.Cacheable;
-import org.apache.cocoon.caching.NOPCacheValidity;
-import org.apache.avalon.excalibur.pool.Recyclable;
-import org.apache.avalon.framework.configuration.Configurable;
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.fop.apps.Driver;
-import org.apache.fop.apps.FOPException;
-import org.apache.fop.apps.Options;
-import org.apache.fop.apps.Version;
-import org.apache.fop.messaging.MessageEvent;
-import org.apache.fop.messaging.MessageHandler;
-import org.apache.fop.messaging.MessageListener;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-
/**
- * FOP PS serializer.
+ * FOP Postscript serializer.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Giacomo Pati</a>
* (PWR Organisation & Entwicklung)
* @author <a href="mailto:[EMAIL PROTECTED]">Stefano Mazzocchi</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Carsten Ziegeler</a>
* @author <a href="mailto:[EMAIL PROTECTED]">John Morrison</a>
- * @version CVS $Revision: 1.1 $ $Date: 2001/08/10 12:36:30 $
+ * @version CVS $Revision: 1.2 $ $Date: 2001/08/14 12:45:26 $
*
* The use of a config file for FOP is enabled by adding a configuration
* element to the serializer in the sitemap.
@@ -47,89 +25,10 @@
* started the JVM, or absolute. If any one wants to fix this, go ahead!
* (colin britton)
*/
-public class PSSerializer extends AbstractSerializer
-implements MessageListener, Recyclable, Configurable, Cacheable {
-
- //Declare options for FOP
- private Options options;
-
- //Declare the FOP driver
- private Driver driver;
-
- /**
- * Set the configurations for this serializer.
- */
- public void configure(Configuration conf)
- throws ConfigurationException {
- String userConfig = null;
- File userConfigFile = null;
-
- if (conf != null) {
- Configuration child = conf.getChild("user-config");
- if (child != null) {
- try{
- userConfig = child.getAttribute("src");
- } catch(Exception ex) {
- // getLogger().debug("FOPSerializer: No config file
specified ");
- }
- }
- }
-
- // Check for null, use external or inbuilt config.
- if(userConfig != null){
- try {
- userConfigFile = new File(userConfig);
- options = new Options(userConfigFile);
- getLogger().debug("PSSerializer: Using config file " +
userConfig);
- } catch (Exception ex) {
- getLogger().error("PSSerializer: Cannot load config "
+ userConfig, ex);
- throw new ConfigurationException("PSSerializer: Cannot
load config " + userConfig, ex);
- }
- } else {
- try {
- options = new Options();
- getLogger().debug("PSSerializer: Using default config
file");
- } catch (Exception e) {
- getLogger().error("PSSerializer: Cannot load default config
", e);
- }
- }
- }
-
-
- /**
- * Create the FOP driver
- * Set the <code>OutputStream</code> where the XML should be serialized.
- */
- public void setOutputStream(OutputStream out) {
- // load the fop driver
- this.driver = new Driver();
-
- // the use of static resources sucks for servlet enviornments
- // since we could have multiple FOP that all logs in this pipe
- // It's a concurrency and security nightmare! (SM)
- MessageHandler.setOutputMethod(MessageHandler.EVENT);
- MessageHandler.addListener(this);
+public class PSSerializer extends AbstractFOPSerializer {
- this.driver.setRenderer(new org.apache.fop.render.ps.PSRenderer());
- this.driver.setOutputStream(out);
- this.setContentHandler(this.driver.getContentHandler());
- }
-
- /**
- * Receive notification of the end of a document.
- */
- public void endDocument() throws SAXException {
- super.endDocument();
- try {
- this.driver.format();
- this.driver.render();
- } catch (IOException e) {
- getLogger().error("PSSerializer.endDocument()", e);
- throw new SAXException (e);
- } catch (FOPException e) {
- getLogger().error("PSSerializer.endDocument()", e);
- throw new SAXException (e);
- }
+ public org.apache.fop.render.Renderer getRenderer() {
+ return new org.apache.fop.render.ps.PSRenderer();
}
/**
@@ -137,57 +36,6 @@
*/
public String getMimeType() {
return "application/postscript";
- }
-
- /**
- * Receive FOP events.
- */
- public void processMessage (MessageEvent event) {
- // Output FOP messgaes to Cocoon logging system
- // Rather verbose, so wrote all as debug (including errors)
- // Could be cleaned up to handle different messages as required (CB)
- getLogger().debug("FOP Message: "+event.getMessage());
- }
-
- /**
- * Generate the unique key.
- * This key must be unique inside the space of this component.
- * This method must be invoked before the generateValidity() method.
- *
- * @return The generated key or <code>0</code> if the component
- * is currently not cacheable.
- */
- public long generateKey() {
- return 1;
- }
-
- /**
- * Generate the validity object.
- * Before this method can be invoked the generateKey() method
- * must be invoked.
- *
- * @return The generated validity object or <code>null</code> if the
- * component is currently not cacheable.
- */
- public CacheValidity generateValidity() {
- return new NOPCacheValidity();
- }
-
- /**
- * Recycle the component and remove it from the MessageList
- */
- public void recycle() {
- super.recycle();
- MessageHandler.removeListener(this);
- this.options = null;
- this.driver = null;
- }
-
- /**
- * Test if the component wants to set the content length
- */
- public boolean shouldSetContentLength() {
- return true;
}
}
1.1
xml-cocoon2/src/org/apache/cocoon/serialization/AbstractFOPSerializer.java
Index: AbstractFOPSerializer.java
===================================================================
/*****************************************************************************
* 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. *
*****************************************************************************/
package org.apache.cocoon.serialization;
import java.io.OutputStream;
import java.io.IOException;
import org.apache.cocoon.caching.Cacheable;
import org.apache.cocoon.caching.CacheValidity;
import org.apache.cocoon.caching.NOPCacheValidity;
import org.apache.avalon.excalibur.pool.Recyclable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.fop.apps.Driver;
import org.apache.fop.apps.Options;
import org.apache.fop.apps.FOPException;
import org.apache.fop.messaging.MessageEvent;
import org.apache.fop.messaging.MessageHandler;
import org.apache.fop.messaging.MessageListener;
import org.xml.sax.SAXException;
public abstract class AbstractFOPSerializer extends AbstractSerializer
implements MessageListener, Recyclable, Configurable, Cacheable {
/**
* The <code>Options</code> used by FOP.
*/
protected Options options;
/**
* The <code>Driver</code> which is FOP.
*/
protected Driver driver;
/**
* Set the configurations for this serializer.
*/
public void configure(Configuration conf)
throws ConfigurationException {
String userConfig = null;
java.io.File userConfigFile = null;
if (conf != null) {
Configuration child = conf.getChild("user-config");
if (child != null) {
try {
userConfig = child.getAttribute("src");
} catch(Exception ex) {
// No config file specified
}
}
}
// Check for null, use external or inbuilt config.
if(userConfig != null) {
try {
userConfigFile = new java.io.File(userConfig);
options = new Options(userConfigFile);
getLogger().debug("Using config file " + userConfig);
} catch (Exception ex) {
getLogger().error("Cannot load config " + userConfig, ex);
throw new ConfigurationException("Cannot load config " +
userConfig, ex);
}
} else {
try {
options = new Options();
getLogger().debug("Using default config file");
} catch (Exception e) {
getLogger().error("Cannot load default config ", e);
}
}
}
/**
* Create the FOP driver
* Set the <code>OutputStream</code> where the XML should be serialized.
*/
public void setOutputStream(OutputStream out) {
// load the fop driver
driver = new Driver();
// the use of static resources sucks for servlet enviornments
// since we could have multiple FOP that all logs in this pipe
// It's a concurrency and security nightmare! (SM)
MessageHandler.setOutputMethod(MessageHandler.EVENT);
MessageHandler.addListener(this);
driver.setRenderer(getRenderer());
driver.setOutputStream(out);
setContentHandler(driver.getContentHandler());
}
/**
* Let the sub classes specify the renderer.
*/
abstract org.apache.fop.render.Renderer getRenderer();
/**
* Receive notification of the end of a document.
*/
public void endDocument() throws SAXException {
super.endDocument();
try {
driver.format();
driver.render();
} catch (IOException e) {
getLogger().error("endDocument()", e);
throw new SAXException (e);
} catch (FOPException e) {
getLogger().error("endDocument()", e);
throw new SAXException (e);
}
}
/**
* Receive FOP events.
*/
public void processMessage(MessageEvent event) {
// Output FOP messgaes to Cocoon logging system
// Rather verbose, so wrote all as debug (including errors)
// Could be cleaned up to handle different messages as required (CB)
getLogger().debug("FOP Message: " + event.getMessage());
}
/**
* Generate the unique key.
* This key must be unique inside the space of this component.
* This method must be invoked before the generateValidity() method.
*
* @return The generated key or <code>0</code> if the component
* is currently not cacheable.
*/
public long generateKey() {
return 1;
}
/**
* Generate the validity object.
* Before this method can be invoked the generateKey() method
* must be invoked.
*
* @return The generated validity object or <code>null</code> if the
* component is currently not cacheable.
*/
public CacheValidity generateValidity() {
return new NOPCacheValidity();
}
/**
* Recycle serializer by removing references
*/
public void recycle() {
super.recycle();
options = null;
driver = null;
}
/**
* Test if the component wants to set the content length
*/
public boolean shouldSetContentLength() {
return true;
}
}
1.1
xml-cocoon2/src/org/apache/cocoon/serialization/PDFSerializer.java
Index: PDFSerializer.java
===================================================================
/*****************************************************************************
* 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. *
*****************************************************************************/
package org.apache.cocoon.serialization;
/**
* FOP PDF serializer.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Giacomo Pati</a>
* (PWR Organisation & Entwicklung)
* @author <a href="mailto:[EMAIL PROTECTED]">Stefano Mazzocchi</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Carsten Ziegeler</a>
* @author <a href="mailto:[EMAIL PROTECTED]">John Morrison</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/08/14 12:45:26 $
*
* The use of a config file for FOP is enabled by adding a configuration
* element to the serializer in the sitemap.
* <user-config src="../webapps/cocoon/WEB-INF/fop_config.xml"/>
* note the path to the config file has to be relative to where the
application
* started the JVM, or absolute. If any one wants to fix this, go ahead!
* (colin britton)
*/
public class PDFSerializer extends AbstractFOPSerializer {
public org.apache.fop.render.Renderer getRenderer() {
return new org.apache.fop.render.pdf.PDFRenderer();
}
/**
* Return the MIME type.
*/
public String getMimeType() {
return "application/pdf";
}
}
1.10 +1 -1 xml-cocoon2/xdocs/jars.xml
Index: jars.xml
===================================================================
RCS file: /home/cvs/xml-cocoon2/xdocs/jars.xml,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- jars.xml 2001/07/20 09:43:49 1.9
+++ jars.xml 2001/08/14 12:45:26 1.10
@@ -108,7 +108,7 @@
conforming to the XSL candidate release and then turns it into a PDF
document or allows you to preview it directly on screen.</td>
<td>No</td>
- <td>FOPSerializer serializer ("fo2pdf")</td>
+ <td>PDFSerializer serializer ("fo2pdf")</td>
<td>Hello World - PDF, Static content - formatting objects</td>
<td/>
</tr>
1.6 +3 -3 xml-cocoon2/xdocs/pdf-serializer.xml
Index: pdf-serializer.xml
===================================================================
RCS file: /home/cvs/xml-cocoon2/xdocs/pdf-serializer.xml,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- pdf-serializer.xml 2001/08/03 10:36:28 1.5
+++ pdf-serializer.xml 2001/08/14 12:45:26 1.6
@@ -21,7 +21,7 @@
the distribution includes this package already.</p>
<ul>
<li>Name : fo2pdf</li>
- <li>Class: org.apache.cocoon.serialization.FOPSerializer</li>
+ <li>Class: org.apache.cocoon.serialization.PDFSerializer</li>
<li>Cacheable: yes.</li>
</ul>
</s1>
@@ -130,11 +130,11 @@
located. Find the line in your sitemap which looks
like:</p>
<source><![CDATA[
-<map:serializer name="fo2pdf"
src="org.apache.cocoon.serialization.FOPSerializer"
mime-type="application/pdf"/>
+<map:serializer name="fo2pdf"
src="org.apache.cocoon.serialization.PDFSerializer"
mime-type="application/pdf"/>
]]></source>
<p>and replace it with...</p>
<source><![CDATA[
-<map:serializer name="fo2pdf"
src="org.apache.cocoon.serialization.FOPSerializer" mime-type="application/pdf">
+<map:serializer name="fo2pdf"
src="org.apache.cocoon.serialization.PDFSerializer" mime-type="application/pdf">
<user-config src="D:/fop-fonts/config.xml"/>
</map:serializer>
]]></source>
1.7 +1 -1 xml-cocoon2/xdocs/uc2.xml
Index: uc2.xml
===================================================================
RCS file: /home/cvs/xml-cocoon2/xdocs/uc2.xml,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- uc2.xml 2001/07/19 14:20:23 1.6
+++ uc2.xml 2001/08/14 12:45:26 1.7
@@ -414,7 +414,7 @@
src="org.apache.cocoon.serialization.HTMLSerializer"/>
<map:serializer name="fo2pdf"
mime-type="application/pdf"
- src="org.apache.cocoon.serialization.FOPSerializer"/>
+ src="org.apache.cocoon.serialization.PDFSerializer"/>
<map:serializer name="vrml"
mime-type="model/vrml"
src="org.apache.cocoon.serialization.TextSerializer"/>
----------------------------------------------------------------------
In case of troubles, e-mail: [EMAIL PROTECTED]
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]