http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/core/MimeMessageWrapper.java ---------------------------------------------------------------------- diff --git a/server/container/core/src/main/java/org/apache/james/core/MimeMessageWrapper.java b/server/container/core/src/main/java/org/apache/james/core/MimeMessageWrapper.java deleted file mode 100644 index 71780ce..0000000 --- a/server/container/core/src/main/java/org/apache/james/core/MimeMessageWrapper.java +++ /dev/null @@ -1,705 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you under the Apache License, Version 2.0 (the * - * "License"); you may not use this file except in compliance * - * with the License. You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ****************************************************************/ - -package org.apache.james.core; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.LineNumberReader; -import java.io.OutputStream; -import java.io.SequenceInputStream; -import java.util.Enumeration; -import java.util.UUID; - -import javax.activation.DataHandler; -import javax.mail.MessagingException; -import javax.mail.Session; -import javax.mail.internet.InternetHeaders; -import javax.mail.internet.MimeMessage; -import javax.mail.util.SharedByteArrayInputStream; - -import org.apache.commons.io.IOUtils; -import org.apache.james.lifecycle.api.Disposable; -import org.apache.james.lifecycle.api.LifecycleUtil; - -/** - * This object wraps a MimeMessage, only loading the underlying MimeMessage - * object when needed. Also tracks if changes were made to reduce unnecessary - * saves. - */ -public class MimeMessageWrapper extends MimeMessage implements Disposable { - - /** - * System property which tells JAMES if it should copy a message in memory - * or via a temporary file. Default is the file - */ - public final static String USE_MEMORY_COPY = "james.message.usememorycopy"; - - /** - * Can provide an input stream to the data - */ - protected MimeMessageSource source = null; - - /** - * This is false until we parse the message - */ - protected boolean messageParsed = false; - - /** - * This is false until we parse the message - */ - protected boolean headersModified = false; - - /** - * This is false until we parse the message - */ - protected boolean bodyModified = false; - - /** - * Keep a reference to the sourceIn so we can close it only when we dispose - * the message. - */ - private InputStream sourceIn; - - private long initialHeaderSize; - - private MimeMessageWrapper(Session session) { - super(session); - this.headers = null; - this.modified = false; - this.headersModified = false; - this.bodyModified = false; - } - - /** - * A constructor that instantiates a MimeMessageWrapper based on a - * MimeMessageSource - * - * @param source - * the MimeMessageSource - * @throws MessagingException - */ - public MimeMessageWrapper(Session session, MimeMessageSource source) { - this(session); - this.source = source; - } - - /** - * A constructor that instantiates a MimeMessageWrapper based on a - * MimeMessageSource - * - * @param source - * the MimeMessageSource - * @throws MessagingException - * @throws MessagingException - */ - public MimeMessageWrapper(MimeMessageSource source) { - this(Session.getDefaultInstance(System.getProperties()), source); - } - - public MimeMessageWrapper(MimeMessage original) throws MessagingException { - this(Session.getDefaultInstance(System.getProperties())); - flags = original.getFlags(); - - if (source == null) { - InputStream in; - - boolean useMemoryCopy = false; - String memoryCopy = System.getProperty(USE_MEMORY_COPY); - if (memoryCopy != null) { - useMemoryCopy = Boolean.valueOf(memoryCopy); - } - try { - - if (useMemoryCopy) { - ByteArrayOutputStream bos; - int size = original.getSize(); - if (size > 0) { - bos = new ByteArrayOutputStream(size); - } else { - bos = new ByteArrayOutputStream(); - } - original.writeTo(bos); - bos.close(); - in = new SharedByteArrayInputStream(bos.toByteArray()); - parse(in); - in.close(); - saved = true; - } else { - MimeMessageInputStreamSource src = new MimeMessageInputStreamSource("MailCopy-" + UUID.randomUUID().toString()); - OutputStream out = src.getWritableOutputStream(); - original.writeTo(out); - out.close(); - source = src; - } - - } catch (IOException ex) { - // should never happen, but just in case... - throw new MessagingException("IOException while copying message", ex); - } - } - } - - /** - * Overrides default javamail behaviour by not altering the Message-ID by - * default, see <a href="https://issues.apache.org/jira/browse/JAMES-875">JAMES-875</a> and - * <a href="https://issues.apache.org/jira/browse/JAMES-1010">JAMES-1010</a> - * - * @see javax.mail.internet.MimeMessage#updateMessageID() - */ - @Override - protected void updateMessageID() throws MessagingException { - if (getMessageID() == null) - super.updateMessageID(); - } - - /** - * Returns the source ID of the MimeMessageSource that is supplying this - * with data. - * - * @see MimeMessageSource - */ - public synchronized String getSourceId() { - return source != null ? source.getSourceId() : null; - } - - /** - * Load the message headers from the internal source. - * - * @throws MessagingException - * if an error is encountered while loading the headers - */ - protected synchronized void loadHeaders() throws MessagingException { - if (headers != null) { - // Another thread has already loaded these headers - } else if (source != null) { - try { - InputStream in = source.getInputStream(); - try { - headers = createInternetHeaders(in); - - } finally { - IOUtils.closeQuietly(in); - } - } catch (IOException ioe) { - throw new MessagingException("Unable to parse headers from stream: " + ioe.getMessage(), ioe); - } - } else { - throw new MessagingException("loadHeaders called for a message with no source, contentStream or stream"); - } - } - - /** - * Load the complete MimeMessage from the internal source. - * - * @throws MessagingException - * if an error is encountered while loading the message - */ - public synchronized void loadMessage() throws MessagingException { - if (messageParsed) { - // Another thread has already loaded this message - } else if (source != null) { - sourceIn = null; - try { - sourceIn = source.getInputStream(); - - parse(sourceIn); - // TODO is it ok? - saved = true; - - } catch (IOException ioe) { - IOUtils.closeQuietly(sourceIn); - sourceIn = null; - throw new MessagingException("Unable to parse stream: " + ioe.getMessage(), ioe); - } - } else { - throw new MessagingException("loadHeaders called for an unparsed message with no source"); - } - } - - /** - * Get whether the message has been modified. - * - * @return whether the message has been modified - */ - public synchronized boolean isModified() { - return headersModified || bodyModified || modified; - } - - /** - * Get whether the body of the message has been modified - * - * @return bodyModified - */ - public synchronized boolean isBodyModified() { - return bodyModified; - } - - /** - * Get whether the header of the message has been modified - * - * @return headersModified - */ - public synchronized boolean isHeaderModified() { - return headersModified; - } - - /** - * Rewritten for optimization purposes - */ - @Override - public void writeTo(OutputStream os) throws IOException, MessagingException { - writeTo(os, os); - - } - - /** - * Rewritten for optimization purposes - */ - @Override - public void writeTo(OutputStream os, String[] ignoreList) throws IOException, MessagingException { - writeTo(os, os, ignoreList); - } - - /** - * Write - */ - public void writeTo(OutputStream headerOs, OutputStream bodyOs) throws IOException, MessagingException { - writeTo(headerOs, bodyOs, new String[0]); - } - - public void writeTo(OutputStream headerOs, OutputStream bodyOs, String[] ignoreList) throws IOException, MessagingException { - writeTo(headerOs, bodyOs, ignoreList, false); - } - - public synchronized void writeTo(OutputStream headerOs, OutputStream bodyOs, String[] ignoreList, boolean preLoad) throws IOException, MessagingException { - - if (!preLoad && source != null && !isBodyModified()) { - // We do not want to instantiate the message... just read from - // source - // and write to this outputstream - - // First handle the headers - InputStream in = source.getInputStream(); - try { - InternetHeaders myHeaders; - MailHeaders parsedHeaders = new MailHeaders(in); - - // check if we should use the parsed headers or not - if (!isHeaderModified()) { - myHeaders = parsedHeaders; - } else { - // The headers was modified so we need to call saveChanges() just to be sure - // See JAMES-1320 - if (!saved) - saveChanges(); - myHeaders = headers; - } - @SuppressWarnings("unchecked") - Enumeration<String> filteredHeaders = myHeaders.getNonMatchingHeaderLines(ignoreList); - IOUtils.copy(new InternetHeadersInputStream(filteredHeaders), headerOs); - IOUtils.copy(in, bodyOs); - } finally { - IOUtils.closeQuietly(in); - } - } else { - // save the changes as the message was modified - // See JAMES-1320 - if (!saved) - saveChanges(); - - // MimeMessageUtil.writeToInternal(this, headerOs, bodyOs, - // ignoreList); - if (headers == null) { - loadHeaders(); - } - @SuppressWarnings("unchecked") - Enumeration<String> filteredHeaders = headers.getNonMatchingHeaderLines(ignoreList); - IOUtils.copy(new InternetHeadersInputStream(filteredHeaders), headerOs); - - if (preLoad && !messageParsed) { - loadMessage(); - } - MimeMessageUtil.writeMessageBodyTo(this, bodyOs); - } - } - - /** - * This is the MimeMessage implementation - this should return ONLY the - * body, not the entire message (should not count headers). This size will - * never change on {@link #saveChanges()} - */ - @Override - public synchronized int getSize() throws MessagingException { - if (source != null) { - try { - long fullSize = source.getMessageSize(); - if (headers == null) { - loadHeaders(); - } - // 2 == CRLF - return (int) (fullSize - initialHeaderSize - 2); - - } catch (IOException e) { - throw new MessagingException("Unable to calculate message size"); - } - } else { - if (!messageParsed) { - loadMessage(); - } - - return super.getSize(); - } - - } - - /** - * Corrects JavaMail 1.1 version which always returns -1. Only corrected for - * content less than 5000 bytes, to avoid memory hogging. - */ - @Override - public int getLineCount() throws MessagingException { - InputStream in; - try { - in = getContentStream(); - } catch (Exception e) { - return -1; - } - if (in == null) { - return -1; - } - // Wrap input stream in LineNumberReader - // Not sure what encoding to use really... - InputStreamReader isr = null; - LineNumberReader counter = null; - try { - if (getEncoding() != null) { - isr = new InputStreamReader(in, getEncoding()); - counter = new LineNumberReader(isr); - } else { - isr = new InputStreamReader(in); - counter = new LineNumberReader(isr); - } - // Read through all the data - char[] block = new char[4096]; - while (counter.read(block) > -1) { - // Just keep reading - } - return counter.getLineNumber(); - } catch (IOException ioe) { - return -1; - } finally { - IOUtils.closeQuietly(counter); - IOUtils.closeQuietly(isr); - IOUtils.closeQuietly(in); - } - } - - /** - * Returns size of message, ie headers and content - */ - public long getMessageSize() throws MessagingException { - if (source != null && !isModified()) { - try { - return source.getMessageSize(); - } catch (IOException ioe) { - throw new MessagingException("Error retrieving message size", ioe); - } - } else { - return MimeMessageUtil.calculateMessageSize(this); - } - } - - /** - * We override all the "headers" access methods to be sure that we loaded - * the headers - */ - - @Override - public String[] getHeader(String name) throws MessagingException { - if (headers == null) { - loadHeaders(); - } - return headers.getHeader(name); - } - - @Override - public String getHeader(String name, String delimiter) throws MessagingException { - if (headers == null) { - loadHeaders(); - } - return headers.getHeader(name, delimiter); - } - - @SuppressWarnings("unchecked") - @Override - public Enumeration<String> getAllHeaders() throws MessagingException { - if (headers == null) { - loadHeaders(); - } - return headers.getAllHeaders(); - } - - @SuppressWarnings("unchecked") - @Override - public Enumeration<String> getMatchingHeaders(String[] names) throws MessagingException { - if (headers == null) { - loadHeaders(); - } - return headers.getMatchingHeaders(names); - } - - @SuppressWarnings("unchecked") - @Override - public Enumeration<String> getNonMatchingHeaders(String[] names) throws MessagingException { - if (headers == null) { - loadHeaders(); - } - return headers.getNonMatchingHeaders(names); - } - - @SuppressWarnings("unchecked") - @Override - public Enumeration<String> getAllHeaderLines() throws MessagingException { - if (headers == null) { - loadHeaders(); - } - return headers.getAllHeaderLines(); - } - - @SuppressWarnings("unchecked") - @Override - public Enumeration<String> getMatchingHeaderLines(String[] names) throws MessagingException { - if (headers == null) { - loadHeaders(); - } - return headers.getMatchingHeaderLines(names); - } - - @SuppressWarnings("unchecked") - @Override - public Enumeration<String> getNonMatchingHeaderLines(String[] names) throws MessagingException { - if (headers == null) { - loadHeaders(); - } - return headers.getNonMatchingHeaderLines(names); - } - - private synchronized void checkModifyHeaders() throws MessagingException { - // Disable only-header loading optimizations for JAMES-559 - /* - * if (!messageParsed) { loadMessage(); } - */ - - // End JAMES-559 - if (headers == null) { - loadHeaders(); - } - modified = true; - saved = false; - headersModified = true; - } - - @Override - public void setHeader(String name, String value) throws MessagingException { - checkModifyHeaders(); - super.setHeader(name, value); - } - - @Override - public void addHeader(String name, String value) throws MessagingException { - checkModifyHeaders(); - super.addHeader(name, value); - } - - @Override - public void removeHeader(String name) throws MessagingException { - checkModifyHeaders(); - super.removeHeader(name); - } - - @Override - public void addHeaderLine(String line) throws MessagingException { - checkModifyHeaders(); - super.addHeaderLine(line); - } - - /** - * The message is changed when working with headers and when altering the - * content. Every method that alter the content will fallback to this one. - * - * @see javax.mail.Part#setDataHandler(javax.activation.DataHandler) - */ - @Override - public synchronized void setDataHandler(DataHandler arg0) throws MessagingException { - modified = true; - saved = false; - bodyModified = true; - super.setDataHandler(arg0); - } - - @Override - public void dispose() { - if (sourceIn != null) { - IOUtils.closeQuietly(sourceIn); - } - if (source != null) { - LifecycleUtil.dispose(source); - } - } - - /** - * @see javax.mail.internet.MimeMessage#parse(java.io.InputStream) - */ - @Override - protected synchronized void parse(InputStream is) throws MessagingException { - // the super implementation calls - // headers = createInternetHeaders(is); - super.parse(is); - messageParsed = true; - } - - /** - * If we already parsed the headers then we simply return the updated ones. - * Otherwise we parse - * - * @see javax.mail.internet.MimeMessage#createInternetHeaders(java.io.InputStream) - */ - @Override - protected synchronized InternetHeaders createInternetHeaders(InputStream is) throws MessagingException { - /* - * This code is no more needed: see JAMES-570 and new tests - * - * InternetHeaders can be a bit awkward to work with due to its own - * internal handling of header order. This hack may not always be - * necessary, but for now we are trying to ensure that there is a - * Return-Path header, even if just a placeholder, so that later, e.g., - * in LocalDelivery, when we call setHeader, it will remove any other - * Return-Path headers, and ensure that ours is on the top. addHeader - * handles header order, but not setHeader. This may change in future - * JavaMail. But if there are other Return-Path header values, let's - * drop our placeholder. - * - * MailHeaders newHeaders = new MailHeaders(new - * ByteArrayInputStream((f.RETURN_PATH + ": placeholder").getBytes())); - * newHeaders.setHeader(RFC2822Headers.RETURN_PATH, null); - * newHeaders.load(is); String[] returnPathHeaders = - * newHeaders.getHeader(RFC2822Headers.RETURN_PATH); if - * (returnPathHeaders.length > 1) - * newHeaders.setHeader(RFC2822Headers.RETURN_PATH, - * returnPathHeaders[1]); - */ - - // Keep this: skip the headers from the stream - // we could put that code in the else and simple write an "header" - // skipping - // reader for the others. - MailHeaders newHeaders = new MailHeaders(is); - - if (headers != null) { - return headers; - } else { - initialHeaderSize = newHeaders.getSize(); - - return newHeaders; - } - } - - /** - * @see javax.mail.internet.MimeMessage#getContentStream() - */ - @Override - protected InputStream getContentStream() throws MessagingException { - if (!messageParsed) { - loadMessage(); - } - return super.getContentStream(); - } - - /** - * @see javax.mail.internet.MimeMessage#getRawInputStream() - */ - @Override - public synchronized InputStream getRawInputStream() throws MessagingException { - if (!messageParsed && !isModified() && source != null) { - InputStream is; - try { - is = source.getInputStream(); - // skip the headers. - new MailHeaders(is); - return is; - } catch (IOException e) { - throw new MessagingException("Unable to read the stream: " + e.getMessage(), e); - } - } else { - return super.getRawInputStream(); - } - } - - /** - * Return an {@link InputStream} which holds the full content of the - * message. This method tries to optimize this call as far as possible. This - * stream contains the updated {@link MimeMessage} content if something was - * changed - * - * @return messageInputStream - * @throws MessagingException - */ - - public synchronized InputStream getMessageInputStream() throws MessagingException { - if (!messageParsed && !isModified() && source != null) { - try { - return source.getInputStream(); - } catch (IOException e) { - throw new MessagingException("Unable to get inputstream", e); - } - } else { - try { - - // Try to optimize if possible to prevent OOM on big mails. - // See JAMES-1252 for an example - if (!bodyModified && source != null) { - // ok only the headers were modified so we don't need to - // copy the whole message content into memory - InputStream in = source.getInputStream(); - - // skip over headers from original stream we want to use the - // in memory ones - new MailHeaders(in); - - // now construct the new stream using the in memory headers - // and the body from the original source - return new SequenceInputStream(new InternetHeadersInputStream(getAllHeaderLines()), in); - } else { - // the body was changed so we have no other solution to copy - // it into memory first :( - ByteArrayOutputStream out = new ByteArrayOutputStream(); - writeTo(out); - return new ByteArrayInputStream(out.toByteArray()); - } - } catch (IOException e) { - throw new MessagingException("Unable to get inputstream", e); - } - } - } - -}
http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/core/filesystem/ClassPathResource.java ---------------------------------------------------------------------- diff --git a/server/container/core/src/main/java/org/apache/james/core/filesystem/ClassPathResource.java b/server/container/core/src/main/java/org/apache/james/core/filesystem/ClassPathResource.java deleted file mode 100644 index 473ce48..0000000 --- a/server/container/core/src/main/java/org/apache/james/core/filesystem/ClassPathResource.java +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you under the Apache License, Version 2.0 (the * - * "License"); you may not use this file except in compliance * - * with the License. You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ****************************************************************/ -package org.apache.james.core.filesystem; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; - -public class ClassPathResource implements Resource { - - private final String path; - private final ClassLoader classLoader; - - public ClassPathResource(String path) { - this.path = sanitizePath(path); - this.classLoader = getDefaultClassLoader(); - } - - private String sanitizePath(String path) { - String pathToUse = new SimpleUrl(path).getSimplified(); - if (pathToUse.startsWith("/")) { - return pathToUse.substring(1); - } - return pathToUse; - } - - @Override - public File getFile() throws IOException { - URL url = getURL(); - return ResourceUtils.getFile(url, getDescription()); - } - - public URL getURL() throws IOException { - URL url = resolveURL(); - if (url == null) { - throw new FileNotFoundException(getDescription() + " cannot be resolved to URL because it does not exist"); - } - return url; - } - - protected URL resolveURL() { - return this.classLoader.getResource(this.path); - } - - @Override - public InputStream getInputStream() throws IOException { - InputStream is = this.classLoader.getResourceAsStream(this.path); - if (is == null) { - throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist"); - } - return is; - } - - public String getDescription() { - return "class path resource [" + path + "]"; - } - - private ClassLoader getDefaultClassLoader() { - ClassLoader currentThreadClassLoader = getcurrentThreadClassLoader(); - if (currentThreadClassLoader != null) { - return currentThreadClassLoader; - } - - // No thread context class loader -> use class loader of this class. - ClassLoader currentClassClassLoader = ClassPathResource.class.getClassLoader(); - if (currentClassClassLoader != null) { - return currentClassClassLoader; - } - - // getClassLoader() returning null indicates the bootstrap ClassLoader - return getSystemClassLoader(); - } - - private ClassLoader getcurrentThreadClassLoader() { - try { - return Thread.currentThread().getContextClassLoader(); - } catch (Throwable ex) { - // Cannot access thread context ClassLoader - falling back... - return null; - } - } - - private ClassLoader getSystemClassLoader() { - try { - return ClassLoader.getSystemClassLoader(); - } catch (Throwable ex) { - // Cannot access system ClassLoader - oh well, maybe the - // caller can live with null... - return null; - } - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/core/filesystem/FileSystemImpl.java ---------------------------------------------------------------------- diff --git a/server/container/core/src/main/java/org/apache/james/core/filesystem/FileSystemImpl.java b/server/container/core/src/main/java/org/apache/james/core/filesystem/FileSystemImpl.java deleted file mode 100644 index b4dfadc..0000000 --- a/server/container/core/src/main/java/org/apache/james/core/filesystem/FileSystemImpl.java +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you under the Apache License, Version 2.0 (the * - * "License"); you may not use this file except in compliance * - * with the License. You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ****************************************************************/ -package org.apache.james.core.filesystem; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; - -import javax.inject.Inject; - -import org.apache.james.filesystem.api.FileSystem; -import org.apache.james.filesystem.api.JamesDirectoriesProvider; - -public class FileSystemImpl implements FileSystem { - - private final JamesDirectoriesProvider directoryProvider; - private final ResourceFactory resourceLoader; - - @Inject - public FileSystemImpl(JamesDirectoriesProvider directoryProvider) { - this.directoryProvider = directoryProvider; - this.resourceLoader = new ResourceFactory(directoryProvider); - } - - @Override - public File getBasedir() throws FileNotFoundException { - return new File(directoryProvider.getRootDirectory()); - } - - @Override - public InputStream getResource(String url) throws IOException { - return resourceLoader.getResource(url).getInputStream(); - } - - @Override - public File getFile(String fileURL) throws FileNotFoundException { - try { - return resourceLoader.getResource(fileURL).getFile(); - } catch (IOException e) { - throw new FileNotFoundException(e.getMessage()); - } - } -} http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/core/filesystem/FileSystemResource.java ---------------------------------------------------------------------- diff --git a/server/container/core/src/main/java/org/apache/james/core/filesystem/FileSystemResource.java b/server/container/core/src/main/java/org/apache/james/core/filesystem/FileSystemResource.java deleted file mode 100644 index bcd5d65..0000000 --- a/server/container/core/src/main/java/org/apache/james/core/filesystem/FileSystemResource.java +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you under the Apache License, Version 2.0 (the * - * "License"); you may not use this file except in compliance * - * with the License. You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ****************************************************************/ -package org.apache.james.core.filesystem; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; - -class FileSystemResource implements Resource { - - private final File file; - - public FileSystemResource(File file) { - this.file = file; - } - - @Override - public File getFile() { - return this.file; - } - - @Override - public InputStream getInputStream() throws IOException { - return new FileInputStream(this.file); - } - -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/core/filesystem/Resource.java ---------------------------------------------------------------------- diff --git a/server/container/core/src/main/java/org/apache/james/core/filesystem/Resource.java b/server/container/core/src/main/java/org/apache/james/core/filesystem/Resource.java deleted file mode 100644 index 08b86e3..0000000 --- a/server/container/core/src/main/java/org/apache/james/core/filesystem/Resource.java +++ /dev/null @@ -1,29 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you under the Apache License, Version 2.0 (the * - * "License"); you may not use this file except in compliance * - * with the License. You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ****************************************************************/ -package org.apache.james.core.filesystem; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; - -public interface Resource { - File getFile() throws IOException; - - InputStream getInputStream() throws IOException; -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/core/filesystem/ResourceFactory.java ---------------------------------------------------------------------- diff --git a/server/container/core/src/main/java/org/apache/james/core/filesystem/ResourceFactory.java b/server/container/core/src/main/java/org/apache/james/core/filesystem/ResourceFactory.java deleted file mode 100644 index 39272f2..0000000 --- a/server/container/core/src/main/java/org/apache/james/core/filesystem/ResourceFactory.java +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you under the Apache License, Version 2.0 (the * - * "License"); you may not use this file except in compliance * - * with the License. You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ****************************************************************/ -package org.apache.james.core.filesystem; - -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; - -import org.apache.james.filesystem.api.FileSystem; -import org.apache.james.filesystem.api.JamesDirectoriesProvider; - -public class ResourceFactory { - - private final JamesDirectoriesProvider directoryProvider; - - public ResourceFactory(JamesDirectoriesProvider directoryProvider) { - this.directoryProvider = directoryProvider; - } - - public Resource getResource(String fileURL) { - if (fileURL.startsWith(FileSystem.CLASSPATH_PROTOCOL)) { - return handleClasspathProtocol(fileURL); - } else if (fileURL.startsWith(FileSystem.FILE_PROTOCOL)) { - return handleFileProtocol(fileURL); - } else { - try { - // Try to parse the location as a URL... - return handleUrlResource(fileURL); - } catch (MalformedURLException ex) { - // No URL -> resolve as resource path. - return new ClassPathResource(fileURL); - } - } - } - - private Resource handleUrlResource(String fileURL) throws MalformedURLException { - URL url = new URL(fileURL); - return new UrlResource(url); - } - - private Resource handleClasspathProtocol(String fileURL) { - String resourceName = fileURL.substring(FileSystem.CLASSPATH_PROTOCOL.length()); - return new ClassPathResource(resourceName); - } - - private Resource handleFileProtocol(String fileURL) { - File file = interpretPath(fileURL); - return new FileSystemResource(file); - } - - private File interpretPath(String fileURL) { - if (FileProtocol.CONF.match(fileURL)) { - return new File(directoryProvider.getConfDirectory() + "/" + FileProtocol.CONF.removeProtocolFromPath(fileURL)); - } else if (FileProtocol.VAR.match(fileURL)) { - return new File(directoryProvider.getVarDirectory() + "/" + FileProtocol.VAR.removeProtocolFromPath(fileURL)); - } else if (FileProtocol.ABSOLUTE.match(fileURL)) { - return new File(directoryProvider.getAbsoluteDirectory() + FileProtocol.ABSOLUTE.removeProtocolFromPath(fileURL)); - } else { - // move to the root folder of the spring deployment - return new File(directoryProvider.getRootDirectory() + "/" + FileProtocol.OTHER.removeProtocolFromPath(fileURL)); - } - } - - private enum FileProtocol { - CONF(FileSystem.FILE_PROTOCOL_AND_CONF), - VAR(FileSystem.FILE_PROTOCOL_AND_VAR), - ABSOLUTE(FileSystem.FILE_PROTOCOL_ABSOLUTE), - OTHER(FileSystem.FILE_PROTOCOL); - - private final String protocolPrefix; - - FileProtocol(String protocolPrefix) { - this.protocolPrefix = protocolPrefix; - } - - private boolean match(String path) { - return path.startsWith(protocolPrefix); - } - - private String removeProtocolFromPath(String path) { - return path.substring(protocolPrefix.length()); - } - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/core/filesystem/ResourceUtils.java ---------------------------------------------------------------------- diff --git a/server/container/core/src/main/java/org/apache/james/core/filesystem/ResourceUtils.java b/server/container/core/src/main/java/org/apache/james/core/filesystem/ResourceUtils.java deleted file mode 100644 index b7fec52..0000000 --- a/server/container/core/src/main/java/org/apache/james/core/filesystem/ResourceUtils.java +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you under the Apache License, Version 2.0 (the * - * "License"); you may not use this file except in compliance * - * with the License. You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ****************************************************************/ -package org.apache.james.core.filesystem; - -import java.io.File; -import java.io.FileNotFoundException; -import java.net.URISyntaxException; -import java.net.URL; - -public class ResourceUtils { - public static final String URL_PROTOCOL_FILE = "file"; - - public static File getFile(URL url, String description) throws FileNotFoundException { - if (!URL_PROTOCOL_FILE.equals(url.getProtocol())) { - throw new FileNotFoundException(description + " cannot be resolved to absolute file path " + "because it does not reside in the file system: " + url); - } - try { - return new File(url.toURI().getSchemeSpecificPart()); - } catch (URISyntaxException ex) { - // Fallback for URLs that are not valid URIs (should hardly ever - // happen). - return new File(url.getFile()); - } - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/core/filesystem/SimpleUrl.java ---------------------------------------------------------------------- diff --git a/server/container/core/src/main/java/org/apache/james/core/filesystem/SimpleUrl.java b/server/container/core/src/main/java/org/apache/james/core/filesystem/SimpleUrl.java deleted file mode 100644 index 18b56bf..0000000 --- a/server/container/core/src/main/java/org/apache/james/core/filesystem/SimpleUrl.java +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you under the Apache License, Version 2.0 (the * - * "License"); you may not use this file except in compliance * - * with the License. You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ****************************************************************/ -package org.apache.james.core.filesystem; - -import java.util.Optional; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.CharMatcher; -import com.google.common.io.Files; - -public class SimpleUrl { - private static final String FOLDER_SEPARATOR = "/"; - - private static final char WINDOWS_FOLDER_SEPARATOR = '\\'; - - private static final String CURRENT_PATH = "."; - - private static final Pattern URL_REGEXP = Pattern.compile("^([^/][^/]*:(?://)?)?(.*)"); - - private static String url; - private static String protocol; - private static String path; - private static String simplifiedUrl; - - public SimpleUrl(String url) { - SimpleUrl.url = url; - String urlWithUnixSeparators = CharMatcher.is(WINDOWS_FOLDER_SEPARATOR).replaceFrom(url, FOLDER_SEPARATOR); - extractComponents(urlWithUnixSeparators); - simplifiedUrl = protocol + simplifyPath(path); - } - - private static void extractComponents(String urlWithUnixSeparators) { - Matcher m = URL_REGEXP.matcher(urlWithUnixSeparators); - m.matches(); - protocol = Optional.ofNullable(m.group(1)).orElse(""); - path = Optional.ofNullable(m.group(2)).orElse(""); - } - - @VisibleForTesting - static String simplifyPath(String path) { - String simplified = Files.simplifyPath(path); - if (CURRENT_PATH.equals(simplified)) { - return ""; - } - return simplified; - } - - public String getUrl() { - return url; - } - - public String getSimplified() { - return simplifiedUrl; - } - -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/core/filesystem/UrlResource.java ---------------------------------------------------------------------- diff --git a/server/container/core/src/main/java/org/apache/james/core/filesystem/UrlResource.java b/server/container/core/src/main/java/org/apache/james/core/filesystem/UrlResource.java deleted file mode 100644 index f1f190c..0000000 --- a/server/container/core/src/main/java/org/apache/james/core/filesystem/UrlResource.java +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you under the Apache License, Version 2.0 (the * - * "License"); you may not use this file except in compliance * - * with the License. You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ****************************************************************/ -package org.apache.james.core.filesystem; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLConnection; - -public class UrlResource implements Resource { - public static final String URL_PROTOCOL_FILE = "file"; - private final URL url; - - public UrlResource(URL url) { - this.url = url; - } - - @Override - public InputStream getInputStream() throws IOException { - URLConnection con = this.url.openConnection(); - useCachesIfNecessary(con); - try { - return con.getInputStream(); - } catch (IOException ex) { - // Close the HTTP connection (if applicable). - if (con instanceof HttpURLConnection) { - ((HttpURLConnection) con).disconnect(); - } - throw ex; - } - } - - public static void useCachesIfNecessary(URLConnection con) { - con.setUseCaches(con.getClass().getSimpleName().startsWith("JNLP")); - } - - @Override - public File getFile() throws IOException { - return ResourceUtils.getFile(url, "URL [" + this.url + "]"); - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/core/package.html ---------------------------------------------------------------------- diff --git a/server/container/core/src/main/java/org/apache/james/core/package.html b/server/container/core/src/main/java/org/apache/james/core/package.html deleted file mode 100644 index a9ce61d..0000000 --- a/server/container/core/src/main/java/org/apache/james/core/package.html +++ /dev/null @@ -1,21 +0,0 @@ -<!-- - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. ---> -<body> -<p>Implementations of core James services and concepts.</p> -</body> http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/server/core/InternetHeadersInputStream.java ---------------------------------------------------------------------- diff --git a/server/container/core/src/main/java/org/apache/james/server/core/InternetHeadersInputStream.java b/server/container/core/src/main/java/org/apache/james/server/core/InternetHeadersInputStream.java new file mode 100644 index 0000000..58bf8dd --- /dev/null +++ b/server/container/core/src/main/java/org/apache/james/server/core/InternetHeadersInputStream.java @@ -0,0 +1,93 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.server.core; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.util.Enumeration; + +import javax.mail.internet.InternetHeaders; + +/** + * Provide an {@link InputStream} over an {@link InternetHeaders} instance. When + * the end of {@link InternetHeaders} are reached a {@link #LINE_SEPERATOR} is + * append + */ +public class InternetHeadersInputStream extends InputStream { + + private final static String LINE_SEPERATOR = "\r\n"; + + private final Enumeration<String> headerLines; + private byte[] currLine; + private int pos = 0; + + @SuppressWarnings("unchecked") + public InternetHeadersInputStream(InternetHeaders headers) { + this(headers.getAllHeaderLines()); + } + + public InternetHeadersInputStream(Enumeration<String> headerLines) { + this.headerLines = headerLines; + } + + @Override + public int read() throws IOException { + if (currLine == null || pos == currLine.length) { + if (!readNextLine()) { + return -1; + } + } + return currLine[pos++]; + } + + /** + * Load the next header line if possible + * + * @return true if there was an headerline which could be read + * + * @throws IOException + */ + private boolean readNextLine() throws IOException { + if (headerLines.hasMoreElements()) { + try { + pos = 0; + String line = (headerLines.nextElement() + LINE_SEPERATOR); + // Add seperator to show that headers are complete + if (!headerLines.hasMoreElements()) { + line += LINE_SEPERATOR; + } + currLine = line.getBytes("US-ASCII"); + return true; + } catch (UnsupportedEncodingException e) { + // should never happen + throw new IOException("US-ASCII encoding not supported by this platform ?!"); + } + } else { + return false; + } + } + + @Override + public void close() throws IOException { + currLine = null; + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/server/core/JamesServerResourceLoader.java ---------------------------------------------------------------------- diff --git a/server/container/core/src/main/java/org/apache/james/server/core/JamesServerResourceLoader.java b/server/container/core/src/main/java/org/apache/james/server/core/JamesServerResourceLoader.java new file mode 100644 index 0000000..d64dc62 --- /dev/null +++ b/server/container/core/src/main/java/org/apache/james/server/core/JamesServerResourceLoader.java @@ -0,0 +1,72 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ +package org.apache.james.server.core; + +import org.apache.james.filesystem.api.JamesDirectoriesProvider; + +public class JamesServerResourceLoader implements JamesDirectoriesProvider { + + private final String rootDirectory; + + public JamesServerResourceLoader(String rootDirectory) { + this.rootDirectory = rootDirectory; + } + + /** + * @see org.apache.james.container.spring.resource.JamesResourceLoader#getAbsoluteDirectory() + */ + public String getAbsoluteDirectory() { + return "/"; + } + + /** + * @see + * org.apache.james.container.spring.resource.JamesResourceLoader#getConfDirectory() + */ + public String getConfDirectory() { + return getRootDirectory() + "/conf/"; + } + + /** + * @see + * org.apache.james.container.spring.resource.JamesResourceLoader#getVarDirectory() + */ + public String getVarDirectory() { + return getRootDirectory() + "/var/"; + } + + /** + * Return the directory where the external jar libraries must be placed + * by the administrator. The jars may contain mailets, jdbc drivers,... + * + * @return externalLibraryDirectory + */ + public String getExternalLibraryDirectory() { + return getRootDirectory() + "/conf/lib/"; + } + + /** + * @see + * org.apache.james.container.spring.resource.JamesResourceLoader#getRootDirectory() + */ + public String getRootDirectory() { + return rootDirectory; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/936746b9/server/container/core/src/main/java/org/apache/james/server/core/MailHeaders.java ---------------------------------------------------------------------- diff --git a/server/container/core/src/main/java/org/apache/james/server/core/MailHeaders.java b/server/container/core/src/main/java/org/apache/james/server/core/MailHeaders.java new file mode 100644 index 0000000..a98223c --- /dev/null +++ b/server/container/core/src/main/java/org/apache/james/server/core/MailHeaders.java @@ -0,0 +1,187 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.server.core; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Serializable; +import java.util.Enumeration; + +import javax.mail.MessagingException; +import javax.mail.internet.InternetHeaders; + +import org.apache.mailet.base.RFC2822Headers; + +/** + * This interface defines a container for mail headers. Each header must use + * MIME format: + * + * <pre> + * name: value + * </pre> + */ +public class MailHeaders extends InternetHeaders implements Serializable, Cloneable { + + private static final long serialVersionUID = 238748126601L; + private boolean modified = false; + private long size = -1; + + /** + * No argument constructor + * + * @throws MessagingException + * if the super class cannot be properly instantiated + */ + public MailHeaders() { + super(); + } + + /** + * Constructor that takes an InputStream containing the contents of the set + * of mail headers. + * + * @param in + * the InputStream containing the header data + * + * @throws MessagingException + * if the super class cannot be properly instantiated based on + * the stream + */ + public MailHeaders(InputStream in) throws MessagingException { + super(); + load(in); + } + + /** + * Write the headers to an output stream + * + * @param out + * the OutputStream to which to write the headers + */ + @SuppressWarnings("unchecked") + public void writeTo(OutputStream out) throws MessagingException { + MimeMessageUtil.writeHeadersTo(getAllHeaderLines(), out); + } + + /** + * Generate a representation of the headers as a series of bytes. + * + * @return the byte array containing the headers + */ + public byte[] toByteArray() throws MessagingException { + ByteArrayOutputStream headersBytes = new ByteArrayOutputStream(); + writeTo(headersBytes); + return headersBytes.toByteArray(); + } + + /** + * Check if a particular header is present. + * + * @return true if the header is present, false otherwise + */ + public boolean isSet(String name) { + String[] value = super.getHeader(name); + return (value != null && value.length != 0); + } + + /** + * If the new header is a Return-Path we get sure that we add it to the top + * Javamail, at least until 1.4.0 does the wrong thing if it loaded a stream + * with a return-path in the middle. + * + * @see javax.mail.internet.InternetHeaders#addHeader(java.lang.String, + * java.lang.String) + */ + @SuppressWarnings("unchecked") + public synchronized void addHeader(String arg0, String arg1) { + if (RFC2822Headers.RETURN_PATH.equalsIgnoreCase(arg0)) { + headers.add(0, new InternetHeader(arg0, arg1)); + } else { + super.addHeader(arg0, arg1); + } + modified(); + } + + /** + * If the new header is a Return-Path we get sure that we add it to the top + * Javamail, at least until 1.4.0 does the wrong thing if it loaded a stream + * with a return-path in the middle. + * + * @see javax.mail.internet.InternetHeaders#setHeader(java.lang.String, + * java.lang.String) + */ + public synchronized void setHeader(String arg0, String arg1) { + if (RFC2822Headers.RETURN_PATH.equalsIgnoreCase(arg0)) { + super.removeHeader(arg0); + } + super.setHeader(arg0, arg1); + + modified(); + } + + @Override + public synchronized void removeHeader(String name) { + super.removeHeader(name); + modified(); + } + + @Override + public synchronized void addHeaderLine(String line) { + super.addHeaderLine(line); + modified(); + } + + private void modified() { + modified = true; + size = -1; + } + + /** + * Check if all REQUIRED headers fields as specified in RFC 822 are present. + * + * @return true if the headers are present, false otherwise + */ + public boolean isValid() { + return (isSet(RFC2822Headers.DATE) && isSet(RFC2822Headers.TO) && isSet(RFC2822Headers.FROM)); + } + + /** + * Return the size of the headers + * + * @return size + */ + @SuppressWarnings("unchecked") + public synchronized long getSize() { + if (size == -1 || modified) { + long c = 0; + Enumeration<String> headerLines = getAllHeaderLines(); + while (headerLines.hasMoreElements()) { + c += headerLines.nextElement().length(); + // CRLF + c += 2; + } + size = c; + modified = false; + } + return size; + + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org