You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by no...@apache.org on 2011/12/31 20:14:12 UTC
svn commit: r1226180 - in
/james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core:
AbstractAddHeadersFilter.java ReceivedDataLineFilter.java
SeparatingDataLineFilter.java
Author: norman
Date: Sat Dec 31 19:14:11 2011
New Revision: 1226180
URL: http://svn.apache.org/viewvc?rev=1226180&view=rev
Log:
Add abstract base classes for header and body filtering / modification. See PROTOCOLS-77
Added:
james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractAddHeadersFilter.java (with props)
james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/SeparatingDataLineFilter.java (with props)
Modified:
james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/ReceivedDataLineFilter.java
Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractAddHeadersFilter.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractAddHeadersFilter.java?rev=1226180&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractAddHeadersFilter.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractAddHeadersFilter.java Sat Dec 31 19:14:11 2011
@@ -0,0 +1,126 @@
+/****************************************************************
+ * 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.protocols.smtp.core;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.james.protocols.api.ProtocolSession.State;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.protocols.api.handler.LineHandler;
+import org.apache.james.protocols.smtp.SMTPSession;
+
+public abstract class AbstractAddHeadersFilter extends SeparatingDataLineFilter{
+
+ private static final AtomicInteger COUNTER = new AtomicInteger(0);
+
+ private final String headersPrefixAdded = "HEADERS_PREFIX_ADDED" + COUNTER.incrementAndGet();
+
+ enum Location{
+ Prefix,
+ Suffix
+ }
+
+ /**
+ * Return the {@link Location} to add the headers in
+ *
+ * @return location
+ */
+ protected abstract Location getLocation();
+
+
+ @Override
+ protected Response onSeparatorLine(SMTPSession session, ByteBuffer line, LineHandler<SMTPSession> next) {
+ if (getLocation() == Location.Suffix && session.getAttachment(headersPrefixAdded, State.Transaction) == null) {
+ session.setAttachment(headersPrefixAdded, Boolean.TRUE, State.Transaction);
+ return addHeaders(session, line, next);
+ }
+ return super.onSeparatorLine(session, line, next);
+ }
+
+ @Override
+ protected Response onHeadersLine(SMTPSession session, ByteBuffer line, LineHandler<SMTPSession> next) {
+ if (getLocation() == Location.Prefix) {
+ return addHeaders(session, line, next);
+ }
+ return super.onHeadersLine(session, line, next);
+ }
+
+ private Response addHeaders(SMTPSession session, ByteBuffer line, LineHandler<SMTPSession> next) {
+ Response response;
+ for (Header header: headers(session)) {
+ response = header.transferTo(session, next);
+ if (response != null) {
+ return response;
+ }
+ }
+ return next.onLine(session, line);
+ }
+
+ /**
+ * Return the {@link Header}'s to operate on
+ *
+ * @return headers
+ */
+ protected abstract Collection<Header> headers(SMTPSession session);
+
+ public final static class Header {
+ public final String name;
+ public final String value;
+
+ public Header(String name, String value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public String toString() {
+ return name + ": " + value + "\r\n";
+ }
+
+ /**
+ * Transfer the content of the {@link Header} to the given {@link LineHandler}.
+ *
+ * This is done for each line of the {@link Header} until the end is reached or the {@link LineHandler#onLine(org.apache.james.protocols.api.ProtocolSession, ByteBuffer)}
+ * return <code>non-null</code>
+ *
+ * @param session
+ * @param handler
+ * @return response
+ */
+ public Response transferTo(SMTPSession session, LineHandler<SMTPSession> handler) {
+ try {
+ String[] lines = toString().split("\r\n");
+ Response response = null;
+ for (int i = 0; i < lines.length; i++) {
+ response = handler.onLine(session, ByteBuffer.wrap((lines[i] + "\r\n").getBytes("US-ASCII")));
+ if (response != null) {
+ break;
+ }
+ }
+ return response;
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("NO US-ASCII ?", e);
+ }
+ }
+ }
+
+
+}
Propchange: james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractAddHeadersFilter.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/ReceivedDataLineFilter.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/ReceivedDataLineFilter.java?rev=1226180&r1=1226179&r2=1226180&view=diff
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/ReceivedDataLineFilter.java (original)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/ReceivedDataLineFilter.java Sat Dec 31 19:14:11 2011
@@ -18,24 +18,19 @@
****************************************************************/
package org.apache.james.protocols.smtp.core;
-import java.io.UnsupportedEncodingException;
-import java.nio.ByteBuffer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import org.apache.james.protocols.api.ProtocolSession.State;
-import org.apache.james.protocols.api.Response;
-import org.apache.james.protocols.api.handler.LineHandler;
import org.apache.james.protocols.smtp.MailAddress;
import org.apache.james.protocols.smtp.SMTPSession;
-public class ReceivedDataLineFilter implements DataLineFilter {
-
- private final static String CHARSET = "US-ASCII";
+public class ReceivedDataLineFilter extends AbstractAddHeadersFilter {
private static final ThreadLocal<DateFormat> DATEFORMAT = new ThreadLocal<DateFormat>() {
@@ -47,91 +42,6 @@ public class ReceivedDataLineFilter impl
};
- private final static String HEADERS_WRITTEN = "HEADERS_WRITTEN";
-
-
-
- /*
- * (non-Javadoc)
- * @see org.apache.james.protocols.smtp.core.DataLineFilter#onLine(org.apache.james.protocols.smtp.SMTPSession, java.nio.ByteBuffer, org.apache.james.protocols.api.handler.LineHandler)
- */
- public Response onLine(SMTPSession session, ByteBuffer line, LineHandler<SMTPSession> next) {
- if (session.getAttachment(HEADERS_WRITTEN, State.Transaction) == null) {
- Response response = addNewReceivedMailHeaders(session, next);
-
- session.setAttachment(HEADERS_WRITTEN, true, State.Transaction);
-
- if (response != null) {
- return response;
- }
- }
- Response resp = next.onLine(session, line);
- return resp;
- }
-
- @SuppressWarnings("unchecked")
- private Response addNewReceivedMailHeaders(SMTPSession session, LineHandler<SMTPSession> next) {
- try {
- StringBuilder headerLineBuffer = new StringBuilder();
-
- String heloMode = (String) session.getAttachment(SMTPSession.CURRENT_HELO_MODE, State.Connection);
- String heloName = (String) session.getAttachment(SMTPSession.CURRENT_HELO_NAME, State.Connection);
-
- // Put our Received header first
- headerLineBuffer.append("Received: from ").append(session.getRemoteAddress().getHostName());
-
- if (heloName != null) {
- headerLineBuffer.append(" (").append(heloMode).append(" ").append(heloName).append(") ");
- }
-
- headerLineBuffer.append(" ([").append(session.getRemoteAddress().getAddress().getHostAddress()).append("])").append("\r\n");
-
- Response response = next.onLine(session, ByteBuffer.wrap(headerLineBuffer.toString().getBytes(CHARSET)));
- if (response != null) {
- return response;
- }
- headerLineBuffer.delete(0, headerLineBuffer.length());
-
- headerLineBuffer.append(" by ").append(session.getConfiguration().getHelloName()).append(" (").append(session.getConfiguration().getSoftwareName()).append(") with ").append(getServiceType(session, heloMode));
-
-
- headerLineBuffer.append(" ID ").append(session.getSessionID());
-
- if (((Collection<?>) session.getAttachment(SMTPSession.RCPT_LIST, State.Transaction)).size() == 1) {
- // Only indicate a recipient if they're the only recipient
- // (prevents email address harvesting and large headers in
- // bulk email)
- headerLineBuffer.append("\r\n");
- next.onLine(session, ByteBuffer.wrap(headerLineBuffer.toString().getBytes(CHARSET)));
- headerLineBuffer.delete(0, headerLineBuffer.length());
-
- headerLineBuffer.delete(0, headerLineBuffer.length());
- headerLineBuffer.append(" for <").append(((List<MailAddress>) session.getAttachment(SMTPSession.RCPT_LIST, State.Transaction)).get(0).toString()).append(">;").append("\r\n");
- response = next.onLine(session, ByteBuffer.wrap(headerLineBuffer.toString().getBytes(CHARSET)));
-
- if (response != null) {
- return response;
- }
- headerLineBuffer.delete(0, headerLineBuffer.length());
- headerLineBuffer.delete(0, headerLineBuffer.length());
-
- } else {
- // Put the ; on the end of the 'by' line
- headerLineBuffer.append(";");
- headerLineBuffer.append("\r\n");
-
- response = next.onLine(session, ByteBuffer.wrap(headerLineBuffer.toString().getBytes(CHARSET)));
- if (response != null) {
- return response;
- }
- headerLineBuffer.delete(0, headerLineBuffer.length());
- }
- headerLineBuffer = null;
- return next.onLine(session, ByteBuffer.wrap((" " + DATEFORMAT.get().format(new Date()) + "\r\n").getBytes(CHARSET)));
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException("No US-ASCII support ?");
- }
- }
/**
@@ -161,4 +71,44 @@ public class ReceivedDataLineFilter impl
return "SMTP";
}
}
+
+ @Override
+ protected Location getLocation() {
+ return Location.Prefix;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected Collection<Header> headers(SMTPSession session) {
+ StringBuilder headerLineBuffer = new StringBuilder();
+
+ String heloMode = (String) session.getAttachment(SMTPSession.CURRENT_HELO_MODE, State.Connection);
+ String heloName = (String) session.getAttachment(SMTPSession.CURRENT_HELO_NAME, State.Connection);
+
+ // Put our Received header first
+ headerLineBuffer.append("from ").append(session.getRemoteAddress().getHostName());
+
+ if (heloName != null) {
+ headerLineBuffer.append(" (").append(heloMode).append(" ").append(heloName).append(") ");
+ }
+ headerLineBuffer.append(" ([").append(session.getRemoteAddress().getAddress().getHostAddress()).append("])").append("\r\n");
+ headerLineBuffer.delete(0, headerLineBuffer.length());
+
+ headerLineBuffer.append(" by ").append(session.getConfiguration().getHelloName()).append(" (").append(session.getConfiguration().getSoftwareName()).append(") with ").append(getServiceType(session, heloMode));
+ headerLineBuffer.append(" ID ").append(session.getSessionID());
+
+ if (((Collection<?>) session.getAttachment(SMTPSession.RCPT_LIST, State.Transaction)).size() == 1) {
+ // Only indicate a recipient if they're the only recipient
+ // (prevents email address harvesting and large headers in
+ // bulk email)
+ headerLineBuffer.append("\r\n");
+ headerLineBuffer.append(" for <").append(((List<MailAddress>) session.getAttachment(SMTPSession.RCPT_LIST, State.Transaction)).get(0).toString()).append(">;");
+ } else {
+ // Put the ; on the end of the 'by' line
+ headerLineBuffer.append(";");
+ }
+ headerLineBuffer.append(" " + DATEFORMAT.get().format(new Date()));
+
+ return Arrays.asList(new Header("Received", headerLineBuffer.toString()));
+ }
}
Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/SeparatingDataLineFilter.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/SeparatingDataLineFilter.java?rev=1226180&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/SeparatingDataLineFilter.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/SeparatingDataLineFilter.java Sat Dec 31 19:14:11 2011
@@ -0,0 +1,113 @@
+/****************************************************************
+ * 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.protocols.smtp.core;
+
+import java.nio.ByteBuffer;
+
+import org.apache.james.protocols.api.Response;
+import org.apache.james.protocols.api.ProtocolSession.State;
+import org.apache.james.protocols.api.handler.LineHandler;
+import org.apache.james.protocols.smtp.SMTPSession;
+
+/**
+ * Abstract base class which makes it easier to handles lines be providing one method per message part.
+ * </br>
+ * </br>
+ * This is:
+ * </br>
+ * <strong>headers</strong></br>
+ * <strong>separator</strong></br>
+ * <strong>body</strong></br>
+ * </br>
+ *
+ * Subclasses should override at least one of these methods:
+ * </br>
+ * {@link #onHeadersLine(SMTPSession, ByteBuffer, LineHandler)}</br>
+ * {@link #onSeparatorLine(SMTPSession, ByteBuffer, LineHandler)}</br>
+ * {@link #onBodyLine(SMTPSession, ByteBuffer, LineHandler)}</br>
+ *
+ *
+ */
+public abstract class SeparatingDataLineFilter implements DataLineFilter{
+
+ private static final String HEADERS_COMPLETE = "HEADERS_COMPLETE";
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.protocols.smtp.core.DataLineFilter#onLine(org.apache.james.protocols.smtp.SMTPSession, java.nio.ByteBuffer, org.apache.james.protocols.api.handler.LineHandler)
+ */
+ public final Response onLine(SMTPSession session, ByteBuffer line, LineHandler<SMTPSession> next) {
+ if (session.getAttachment(HEADERS_COMPLETE, State.Transaction) == null) {
+ if (line.remaining() == 2 ) {
+ if (line.get() == '\r' && line.get() == '\n') {
+ line.rewind();
+ Response response = onSeparatorLine(session, line, next);
+ session.setAttachment(HEADERS_COMPLETE, Boolean.TRUE, State.Transaction);
+ return response;
+ }
+ line.rewind();
+ }
+ return onHeadersLine(session, line, next);
+ }
+
+ return onBodyLine(session, line, next);
+ }
+
+ /**
+ * Gets called when the separating line is received. This is the CLRF sequence.
+ *
+ * This implementation just calls {@link LineHandler#onLine(org.apache.james.protocols.api.ProtocolSession, ByteBuffer)} but subclasses should override it if needed.
+ *
+ * @param session
+ * @param line
+ * @param next
+ * @return response
+ */
+ protected Response onSeparatorLine(SMTPSession session, ByteBuffer line, LineHandler<SMTPSession> next) {
+ return next.onLine(session, line);
+ }
+
+ /**
+ * Gets called for each received line until the CRLF sequence was received.
+ *
+ * This implementation just calls {@link LineHandler#onLine(org.apache.james.protocols.api.ProtocolSession, ByteBuffer)} but subclasses should override it if needed.
+ *
+ * @param session
+ * @param line
+ * @param next
+ * @return response
+ */
+ protected Response onHeadersLine(SMTPSession session, ByteBuffer line, LineHandler<SMTPSession> next) {
+ return next.onLine(session, line);
+ }
+
+ /**
+ * Gets called for each received line after the CRLF sequence was received.
+ *
+ * This implementation just calls {@link LineHandler#onLine(org.apache.james.protocols.api.ProtocolSession, ByteBuffer)} but subclasses should override it if needed.
+ *
+ * @param session
+ * @param line
+ * @param next
+ * @return response
+ */
+ protected Response onBodyLine(SMTPSession session, ByteBuffer line, LineHandler<SMTPSession> next) {
+ return next.onLine(session, line);
+ }
+}
Propchange: james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/SeparatingDataLineFilter.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org