sanders 02/01/25 18:47:42
Added: io/src/conf MANIFEST.MF
io/src/java/org/apache/commons/io FileUtils.java
LockableFileWriter.java StreamUtils.java
io/src/test/org/apache/commons/io IOTestCase.java
Log:
Savepoint. Does not compile or work yet. More work this weekend.
Revision Changes Path
1.1 jakarta-commons-sandbox/io/src/conf/MANIFEST.MF
Index: MANIFEST.MF
===================================================================
Extension-Name: @package@
Specification-Vendor: Apache Software Foundation
Specification-Version: 1.0
Implementation-Vendor: Apache Software Foundation
Implementation-Version: @version@
1.1
jakarta-commons-sandbox/io/src/java/org/apache/commons/io/FileUtils.java
Index: FileUtils.java
===================================================================
package org.apache.commons.io;
/* ====================================================================
* 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" and "Apache Software Foundation" and
* "Apache Turbine" 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",
* "Apache Turbine", 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/>.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* Common {@link java.io.File} manipulation routines.
*
* Taken from the commons-utils repo.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Scott Sanders</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Daniel Rall</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Christoph.Reck</a>
* @version $Id: FileUtils.java,v 1.1 2002/01/26 02:47:42 sanders Exp $
*/
public class FileUtils
{
/**
* The number of bytes in a kilobyte.
*/
public static final int ONE_KB = 1024;
/**
* The number of bytes in a megabyte.
*/
public static final int ONE_MB = ONE_KB * ONE_KB;
/**
* The number of bytes in a gigabyte.
*/
public static final int ONE_GB = ONE_KB * ONE_MB;
/**
* Returns a human-readable version of the file size (original is in
* bytes).
*
* @param size The number of bytes.
* @return A human-readable display value (includes units).
*/
public static String byteCountToDisplaySize(int size)
{
String displaySize;
if (size / ONE_GB > 0)
{
displaySize = String.valueOf(size / ONE_GB) + " GB";
}
else if (size / ONE_MB > 0)
{
displaySize = String.valueOf(size / ONE_MB) + " MB";
}
else if (size / ONE_KB > 0)
{
displaySize = String.valueOf(size / ONE_KB) + " KB";
}
else
{
displaySize = String.valueOf(size) + " bytes";
}
return displaySize;
}
/**
* Returns the directory path portion of a file specification string.
* Matches the equally named unix command.
* @return The directory portion excluding the ending file separator.
*/
public static String dirname(String filename)
{
int i = filename.lastIndexOf(File.separator);
return (i >= 0 ? filename.substring(0, i) : "");
}
/**
* Returns the filename portion of a file specification string.
* @return The filename string with extension.
*/
public static String filename(String filename)
{
int i = filename.lastIndexOf(File.separator);
return (i >= 0 ? filename.substring(i + 1) : filename);
}
/**
* Returns the filename portion of a file specification string.
* Matches the equally named unix command.
* @return The filename string without extension.
*/
public static String basename(String filename)
{
return basename(filename, extension(filename));
}
/**
* Returns the filename portion of a file specification string.
* Matches the equally named unix command.
*/
public static String basename(String filename, String suffix)
{
int i = filename.lastIndexOf(File.separator) + 1;
int lastDot = ((suffix != null) && (suffix.length() > 0))
? filename.lastIndexOf(suffix) : -1;
if (lastDot >= 0)
{
return filename.substring(i, lastDot);
}
else if (i > 0)
{
return filename.substring(i);
}
else
{
return filename; // else returns all (no path and no extension)
}
}
/**
* Returns the extension portion of a file specification string.
* This everything after the last dot '.' in the filename (including
* the dot).
*/
public static String extension(String filename)
{
int lastDot = filename.lastIndexOf('.');
if (lastDot >= 0)
{
return filename.substring(lastDot);
}
else
{
return "";
}
}
/**
* Check if a file exits.
*
* @param fileName The name of the file to check.
* @return true if file exists.
*/
public static boolean fileExists(String fileName)
{
File file = new File(fileName);
return file.exists();
}
/**
* Reads the contents of a file.
*
* @param fileName The name of the file to read.
* @return The file contents or null if read failed.
*/
public static String fileRead(String fileName) throws Exception
{
StringBuffer buf = new StringBuffer();
FileInputStream in = new FileInputStream(fileName);
int count;
byte[] b = new byte[512];
while ( (count = in.read(b)) > 0 ) // blocking read
{
buf.append( new String(b, 0, count) );
}
in.close();
return buf.toString();
}
/**
* Writes data to a file. The file will be created if it does not exist.
*
* @param fileName The name of the file to write.
* @param data The content to write to the file.
*/
public static void fileWrite(String fileName, String data) throws Exception
{
FileOutputStream out = new FileOutputStream(fileName);
out.write( data.getBytes() );
out.close();
}
/**
* Deletes a file.
*
* @param fileName The name of the file to delete.
*/
public static void fileDelete(String fileName)
{
File file = new File(fileName);
file.delete();
}
/**
* Waits for NFS to propagate a file creation, imposing a timeout.
*
* @param fileName The name of the file.
* @param seconds The maximum time in seconds to wait.
* @return True if file exists.
*/
public static boolean waitFor(String fileName, int seconds)
{
File file = new File(fileName);
int timeout = 0;
int tick = 0;
while ( ! file.exists() )
{
if (tick++ >= 10)
{
tick = 0;
if (timeout++ > seconds)
{
return false;
}
}
try
{
Thread.sleep(100);
}
catch(InterruptedException ignore)
{
}
catch(Exception ex)
{
break;
}
}
return true;
}
/**
* Creates a file handle.
*
* @param fileName The name of the file.
* @return A <code>File</code> instance.
*/
public static File getFile(String fileName)
{
return new File(fileName);
}
}
1.1
jakarta-commons-sandbox/io/src/java/org/apache/commons/io/LockableFileWriter.java
Index: LockableFileWriter.java
===================================================================
package org.apache.commons.io;
/* ====================================================================
* 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" and "Apache Software Foundation" and
* "Apache Turbine" 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",
* "Apache Turbine", 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/>.
*/
import java.io.File;
import java.io.Writer;
import java.io.FileWriter;
import java.io.IOException;
/**
* FileWriter that will create and honor lock files to allow simple
* cross thread file lock handling. If <code>Writer</code> attributes
* are unspecified, the default behavior is to overwrite (rather than
* to append), and to use the value of the system property
* <code>java.io.tmpdir</code> for the lock file directory.
*
* Borrowed from the commons-util repo.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Scott Sanders</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Michael Salmon</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Jon S. Stevens</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Daniel Rall</a>
* @version $Id: LockableFileWriter.java,v 1.1 2002/01/26 02:47:42 sanders Exp $
*/
public class LockableFileWriter extends Writer
{
private static final String LCK = ".lck";
private File lockFile = null;
private FileWriter writer = null;
private boolean append = false;
public LockableFileWriter(String fileName)
throws IOException
{
this(fileName, false, null);
}
public LockableFileWriter(String fileName, boolean append)
throws IOException
{
this(fileName, append, null);
}
public LockableFileWriter(String fileName, boolean append, String lockDir)
throws IOException
{
this(new File(fileName), append, lockDir);
}
public LockableFileWriter(File file)
throws IOException
{
this(file, false, null);
}
public LockableFileWriter(File file, boolean append)
throws IOException
{
this(file, append, null);
}
public LockableFileWriter(File file, boolean append, String lockDir)
throws IOException
{
this.append = append;
if (lockDir == null)
{
lockDir = System.getProperty("java.io.tmpdir");
}
testLockDir(new File(lockDir));
this.lockFile = new File(lockDir, file.getName() + LCK);
createLock();
this.writer = new FileWriter(file.getAbsolutePath(), this.append);
}
private void testLockDir(File lockDir)
throws IOException
{
if (!lockDir.exists())
{
throw new IOException(
"Could not find lockDir: " + lockDir.getAbsolutePath());
}
if (!lockDir.canWrite())
{
throw new IOException(
"Could not write to lockDir: " + lockDir.getAbsolutePath());
}
}
private void createLock()
throws IOException
{
synchronized (LockableFileWriter.class)
{
if (!lockFile.createNewFile())
{
throw new IOException("Can't write file, lock " +
lockFile.getAbsolutePath() + " exists");
}
lockFile.deleteOnExit();
}
}
public void close()
throws IOException
{
try
{
writer.close();
}
finally
{
lockFile.delete();
}
}
public void write(char[] cbuf, int off, int len)
throws IOException
{
writer.write(cbuf, off, len);
}
public void flush()
throws IOException
{
writer.flush();
}
}
1.1
jakarta-commons-sandbox/io/src/java/org/apache/commons/io/StreamUtils.java
Index: StreamUtils.java
===================================================================
package org.apache.commons.io;
/* ====================================================================
* 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" and "Apache Software Foundation" and
* "Apache Turbine" 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",
* "Apache Turbine", 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/>.
*/
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.StringBuffer;
/**
* Methods for manipulating streams.
*
* Borrowed from the commons-util repo.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Scott Sanders</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Leonard Richardson</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Daniel Rall</a>
* @version $Id: StreamUtils.java,v 1.1 2002/01/26 02:47:42 sanders Exp $
*/
public class StreamUtils
{
/**
* Buffer size to use if one is not specified.
*/
private static final int DEFAULT_BUFFER_SIZE = 1024;
/**
* Reads from a stream until EOF, and returns everything read as a
* string. Uses the default buffer size, and the platform's
* default character encoding.
*
* @param toRead Stream to use as source.
* @return A String version of the contents of <code>toRead</code>.
*/
public static String streamAsString(InputStream toRead)
throws IOException
{
return streamAsString(toRead, DEFAULT_BUFFER_SIZE, null);
}
/**
* Reads from a stream until EOF, and returns everything read as a
* string.
*
* @param toRead Stream to use as source.
* @param bufferSize Size of buffer to use when reading from source.
* @param encoding Encoding to use when converting bytes to
* characters. A null value means to use the
* platforms's default character encoding.
* @return A String version of the contents of <code>toRead</code>.
*/
public static String streamAsString(InputStream toRead, int bufferSize,
String encoding)
throws IOException
{
ByteArrayOutputStream contents = readStream(toRead, bufferSize);
return (encoding == null ? contents.toString() :
contents.toString(encoding));
}
/**
* Reads from a stream until EOF, and returns the bytes read.
*
* @param toRead Stream to use as source.
* @param bufferSize Size of buffer to use when reading from source.
* @return The contents of <code>toRead</code>.
*/
public static byte[] streamAsBytes(InputStream toRead, int bufferSize)
throws IOException
{
ByteArrayOutputStream contents = readStream(toRead, bufferSize);
return contents.toByteArray();
}
/**
* Reads from a stream util EOF, placing the resulting data into a
* <code>ByteArrayOutputStream</code> which is subsequently returned.
*
* @param toRead Stream to use as source.
* @param bufferSize Size of buffer to use when reading from source.
*
* @return a <code>ByteArrayOutputStream</code> containing the
* contents of <code>toRead</code>.
*/
protected static ByteArrayOutputStream readStream(InputStream toRead,
int bufferSize)
throws IOException
{
ByteArrayOutputStream contents = new ByteArrayOutputStream();
byte[] buffer = new byte[bufferSize];
int bytesRead;
while ( (bytesRead = toRead.read(buffer)) != -1 )
{
contents.write(buffer, 0, bytesRead);
}
return contents;
}
/**
* Pipes the contents of an InputStream into an OutputStream.
* Uses the default buffer size. Note that you still need to close
* the OutputStream.
*
* @param toRead Stream to use as source.
* @param toWrite Stream to use as sink.
*/
public static void pipe(InputStream toRead, OutputStream toWrite)
throws IOException
{
pipe(toRead, toWrite, DEFAULT_BUFFER_SIZE);
}
/**
* Pipes the contents of an InputStream into an OutputStream.
* Note that you still need to close the OutputStream.
*
* @param toRead Stream to use as source.
* @param toWrite Stream to use as sink.
* @param bufferSize Size of buffer to use when reading from source.
*/
public static void pipe(InputStream toRead, OutputStream toWrite,
int bufferSize)
throws IOException
{
byte[] buffer = new byte[bufferSize];
int bytesRead;
while ( (bytesRead = toRead.read(buffer)) != -1 )
{
toWrite.write(buffer, 0, bytesRead);
}
}
}
1.1
jakarta-commons-sandbox/io/src/test/org/apache/commons/io/IOTestCase.java
Index: IOTestCase.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-commons-sandbox/io/src/test/org/apache/commons/io/IOTestCase.java,v
1.1 2002/01/26 02:47:42 sanders Exp $
* $Revision: 1.1 $
* $Date: 2002/01/26 02:47:42 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2002 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 acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Commons", 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 names without prior written
* permission of the Apache Group.
*
* 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.commons.io;
import java.lang.reflect.InvocationTargetException;
import junit.framework.TestCase;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* <p>
* Test Case for the IO classes. </p>
*
* <p>
* Template for this stolen from Craigs BeanUtils PropertyUtilsTestCase
* </p>
*
* @author <a href="mailto:[EMAIL PROTECTED]">Scott Sanders</a>
* @version $Revision: 1.1 $
*/
public class IOTestCase extends TestCase {
/**
* Construct a new instance of this test case.
*
* @param name Name of the test case
*/
public IOTestCase(String name) {
super(name);
}
/**
* Set up instance variables required by this test case.
*/
public void setUp() {
}
/**
* Return the tests included in this test suite.
*/
public static Test suite() {
return (new TestSuite(IOTestCase.class));
}
/**
* Tear down instance variables required by this test case.
*/
public void tearDown() {
}
/**
* tests the string and int arrays of TestBean
*/
public void testSomething() {
}
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>