[jboss-svn-commits] JBL Code SVN: r37466 - in labs/jbossesb/branches/JBESB_4_10_CP/product: rosetta/src/org/jboss/soa/esb/actions/converters and 3 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Sep 15 11:02:47 EDT 2011


Author: tfennelly
Date: 2011-09-15 11:02:46 -0400 (Thu, 15 Sep 2011)
New Revision: 37466

Added:
   labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/src/org/jboss/soa/esb/actions/converters/BOMFilter.java
   labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/converters/BOMFilterTest-config01.xml
   labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/converters/BOMFilterUnitTest.java
Modified:
   labs/jbossesb/branches/JBESB_4_10_CP/product/ivysettings.xml
   labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/src/org/jboss/soa/esb/listeners/gateway/http/HttpGatewayServlet.java
   labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/src/org/jboss/soa/esb/listeners/message/ActionProcessingConstants.java
Log:
JBESB-3649: Add a Byte Order Mark (BOM) filtering action

https://issues.jboss.org/browse/JBESB-3649

Modified: labs/jbossesb/branches/JBESB_4_10_CP/product/ivysettings.xml
===================================================================
--- labs/jbossesb/branches/JBESB_4_10_CP/product/ivysettings.xml	2011-09-13 19:33:49 UTC (rev 37465)
+++ labs/jbossesb/branches/JBESB_4_10_CP/product/ivysettings.xml	2011-09-15 15:02:46 UTC (rev 37466)
@@ -1,6 +1,6 @@
 <ivysettings>
 
-    <property name="smooks.version" value="1.4"/>
+    <property name="smooks.version" value="1.4.2"/>
 
     <settings defaultResolver="chained"/>
     <resolvers>

Added: labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/src/org/jboss/soa/esb/actions/converters/BOMFilter.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/src/org/jboss/soa/esb/actions/converters/BOMFilter.java	                        (rev 0)
+++ labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/src/org/jboss/soa/esb/actions/converters/BOMFilter.java	2011-09-15 15:02:46 UTC (rev 37466)
@@ -0,0 +1,229 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.soa.esb.actions.converters;
+
+import java.io.BufferedInputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.jboss.soa.esb.actions.AbstractActionPipelineProcessor;
+import org.jboss.soa.esb.actions.ActionProcessingException;
+import org.jboss.soa.esb.helpers.ConfigTree;
+import org.jboss.soa.esb.listeners.message.ActionProcessingConstants;
+import org.jboss.soa.esb.listeners.message.MessageDeliverException;
+import org.jboss.soa.esb.message.Message;
+import org.jboss.soa.esb.message.MessagePayloadProxy;
+
+/**
+ * Byte Order Mark (BOM) Filtering Action.
+ * <p/>
+ * Only works on {@link byte} arrays and {@link InputStream InputStreams}.
+ * 
+ * @author <a href="mailto:tom.fennelly at gmail.com">tom.fennelly at gmail.com</a>
+ */
+public class BOMFilter extends AbstractActionPipelineProcessor {
+
+	private static final Logger logger = Logger.getLogger(BOMFilter.class);
+
+    private MessagePayloadProxy payloadProxy;
+	private final String contentEncoding;
+	
+	private static final Map<String, byte[]> bomMap;
+	
+	static {
+		bomMap = new HashMap<String, byte[]>();
+		bomMap.put("UTF8", new byte[] {(byte)0xEF, (byte)0xBB, (byte)0xBF});
+		bomMap.put("UTF16BE", new byte[] {(byte)0xFE, (byte)0xFF});
+		bomMap.put("UTF16LE", new byte[] {(byte)0xFF, (byte)0xFE});
+		bomMap.put("UTF32BE", new byte[] {(byte)0x00, (byte)0x00, (byte)0xFE, (byte)0xFF});
+		bomMap.put("UTF32LE", new byte[] {(byte)0xFF, (byte)0xFE, (byte)0x00, (byte)0x00});
+	}
+
+	/**
+	 * Public constructor.
+	 * @param config Config.
+	 */
+	public BOMFilter(ConfigTree config) {
+		contentEncoding = config.getAttribute("contentEncoding");
+		payloadProxy = new MessagePayloadProxy(config);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.jboss.soa.esb.actions.ActionPipelineProcessor#process(org.jboss.soa.esb.message.Message)
+	 */
+	public Message process(Message message) throws ActionProcessingException {
+		final String bomEncoding;
+		
+		if (contentEncoding != null) {
+			bomEncoding = contentEncoding;
+		} else {
+			bomEncoding = (String) message.getProperties().getProperty(ActionProcessingConstants.PROPERTY_PAYLOAD_CONTENT_ENCODING);
+		}
+		
+		if (bomEncoding != null) {
+			Object payload;
+			
+			try {
+				payload = payloadProxy.getPayload(message);
+			} catch (MessageDeliverException e) {
+				throw new ActionProcessingException("Error getting payload from Message instance.", e);
+			}
+
+			try {
+				if (payload instanceof byte[]) {
+					payloadProxy.setPayload(message, filterBOM((byte[])payload, bomEncoding));
+				} else if (payload instanceof InputStream) {
+					payloadProxy.setPayload(message, filterBOM((InputStream)payload, bomEncoding));
+				} else {
+					logger.debug("BOMFilter not applied to message.  Only supports byte[] and InputStream payload types.");
+				}
+			} catch (MessageDeliverException e) {
+				throw new ActionProcessingException("Error setting payload on Message instance.", e);
+			}
+		} else {
+			logger.debug("BOMFilter not applied to message.  No 'contentEncoding' was specified on the Action configuration, or on the incoming message properties (\"" + ActionProcessingConstants.PROPERTY_PAYLOAD_CONTENT_ENCODING + "\").");
+		}		
+		
+		return message;
+	}
+
+	private byte[] filterBOM(byte[] payload, String bomEncoding) throws ActionProcessingException {
+		byte[] bom = getBOM(bomEncoding);
+		
+		if (bom == null) {
+			return payload;
+		}
+		if (payload.length < bom.length) {			
+			return payload;
+		}
+		
+		// Check payload for a BOM...
+		if (!hasBOM(payload, bom)) {
+			// No BOM on payload... return unchanged...
+			return payload;
+		}
+
+		// Payload has a BOM... remove it...
+		byte[]  newPayload = new byte[payload.length - bom.length];
+		System.arraycopy(payload, bom.length, newPayload, 0, newPayload.length);
+		
+		return newPayload;
+	}
+
+	private InputStream filterBOM(InputStream payload, String bomEncoding) throws ActionProcessingException {
+		byte[] bom = getBOM(bomEncoding);		
+
+		if (bom == null) {
+			return payload;
+		}
+		
+		return new BOMFilterInputStream(new BufferedInputStream(payload), bom);
+	}
+
+	protected static byte[] getBOM(String bomEncoding) {
+		if (bomEncoding == null) {
+			return null;
+		}
+		
+		return bomMap.get(bomEncoding.replace("-", "").toUpperCase());
+	}
+
+	protected static boolean hasBOM(byte[] dataBuffer, byte[] bom) {
+		for (int i = 0; i < bom.length; i++) {
+			if (dataBuffer[i] != bom[i]) {
+				// No BOM on payload...
+				return false;
+			}
+		}
+		
+		return true;
+	}
+
+	private static class BOMFilterInputStream extends FilterInputStream {
+
+		private byte[] bom;
+		private boolean bomFilteringComplete = false;
+
+		protected BOMFilterInputStream(BufferedInputStream in, byte[] bom) {
+			super(in);
+			this.bom = bom;
+			in.mark(bom.length);
+ 		}
+
+		/* (non-Javadoc)
+		 * @see java.io.FilterInputStream#read()
+		 */
+		@Override
+		public int read() throws IOException {
+			if (!bomFilteringComplete) {
+				filterBOM();
+			}
+			return super.read();
+		}
+
+		/* (non-Javadoc)
+		 * @see java.io.FilterInputStream#read(byte[])
+		 */
+		@Override
+		public int read(byte[] b) throws IOException {
+			if (!bomFilteringComplete) {
+				filterBOM();
+			}
+			return super.read(b);
+		}
+
+		/* (non-Javadoc)
+		 * @see java.io.FilterInputStream#read(byte[], int, int)
+		 */
+		@Override
+		public int read(byte[] b, int off, int len) throws IOException {
+			if (!bomFilteringComplete) {
+				filterBOM();
+			}
+			return super.read(b, off, len);
+		}
+
+		protected void filterBOM() throws IOException {
+			try {
+				byte[] bomBuffer = new byte[bom.length];
+				int readCount = in.read(bomBuffer);
+				
+				if (readCount < bom.length) {
+					// There's no BOM... reset back to the start of the stream...
+					in.reset();
+				} else if (!hasBOM(bomBuffer, bom)) {
+					// There's no BOM... reset back to the start of the stream...
+					in.reset();
+				} else {
+					// It has a BOM... don't reset.  This filters the BOM...
+				}
+			} finally {
+				bomFilteringComplete = true;
+			}
+		}
+	}
+}


Property changes on: labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/src/org/jboss/soa/esb/actions/converters/BOMFilter.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Id Revision
Added: svn:eol-style
   + LF

Modified: labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/src/org/jboss/soa/esb/listeners/gateway/http/HttpGatewayServlet.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/src/org/jboss/soa/esb/listeners/gateway/http/HttpGatewayServlet.java	2011-09-13 19:33:49 UTC (rev 37465)
+++ labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/src/org/jboss/soa/esb/listeners/gateway/http/HttpGatewayServlet.java	2011-09-15 15:02:46 UTC (rev 37466)
@@ -49,6 +49,7 @@
 import org.jboss.soa.esb.lifecycle.LifecycleResourceManager;
 import org.jboss.soa.esb.listeners.ListenerTagNames;
 import org.jboss.soa.esb.listeners.config.mappers120.HttpGatewayMapper;
+import org.jboss.soa.esb.listeners.message.ActionProcessingConstants;
 import org.jboss.soa.esb.listeners.message.MessageComposer;
 import org.jboss.soa.esb.listeners.message.MessageDeliverException;
 import org.jboss.soa.esb.message.Message;
@@ -216,6 +217,11 @@
         } catch (MessageDeliverException e) {
             throw new ServletException("Failed to create message.", e);
         }
+        
+        String contentEncoding = req.getCharacterEncoding();
+        if (contentEncoding != null && contentEncoding.trim().length() > 0) {
+        	inMessage.getProperties().setProperty(ActionProcessingConstants.PROPERTY_PAYLOAD_CONTENT_ENCODING, contentEncoding);
+        }
 
         // Add any servlet authentication details to the message if there were non
         // presented in the message payload e.g. on a SOAP message...

Modified: labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/src/org/jboss/soa/esb/listeners/message/ActionProcessingConstants.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/src/org/jboss/soa/esb/listeners/message/ActionProcessingConstants.java	2011-09-13 19:33:49 UTC (rev 37465)
+++ labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/src/org/jboss/soa/esb/listeners/message/ActionProcessingConstants.java	2011-09-15 15:02:46 UTC (rev 37466)
@@ -35,4 +35,8 @@
 	 * Used to store the response type when the response cannot be sent. 
 	 */
 	public static final String PROPERTY_FAILURE_RESPONSE_TYPE = "org.jboss.soa.esb.failure.responseType" ;
+	/**
+	 * Payload content encoding.  Only relevant for byte[] or InputStream payload types.
+	 */
+	public static final String PROPERTY_PAYLOAD_CONTENT_ENCODING = "org.jboss.soa.esb.payload.contentEncoding" ;
 }

Added: labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/converters/BOMFilterTest-config01.xml
===================================================================
--- labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/converters/BOMFilterTest-config01.xml	                        (rev 0)
+++ labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/converters/BOMFilterTest-config01.xml	2011-09-15 15:02:46 UTC (rev 37466)
@@ -0,0 +1,16 @@
+<?xml version = "1.0" encoding = "UTF-8"?>
+<jbossesb xmlns="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd">
+
+    <services>
+
+        <service category="Services" name="ServiceA" description="ServiceA" invmScope="GLOBAL">
+            <actions mep="RequestResponse">
+                <action name="action" class="org.jboss.soa.esb.actions.converters.BOMFilter">
+                    <property name="contentEncoding" value="UTF-8" />
+                </action>
+            </actions>			
+        </service>
+
+    </services>
+
+</jbossesb>
\ No newline at end of file


Property changes on: labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/converters/BOMFilterTest-config01.xml
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Id Revision
Added: svn:eol-style
   + LF

Added: labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/converters/BOMFilterUnitTest.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/converters/BOMFilterUnitTest.java	                        (rev 0)
+++ labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/converters/BOMFilterUnitTest.java	2011-09-15 15:02:46 UTC (rev 37466)
@@ -0,0 +1,141 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.soa.esb.actions.converters;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.jboss.internal.soa.esb.util.StreamUtils;
+import org.jboss.soa.esb.actions.ActionProcessingException;
+import org.jboss.soa.esb.client.ServiceInvoker;
+import org.jboss.soa.esb.helpers.ConfigTree;
+import org.jboss.soa.esb.listeners.message.ActionProcessingConstants;
+import org.jboss.soa.esb.message.Message;
+import org.jboss.soa.esb.message.format.MessageFactory;
+import org.jboss.soa.esb.testutils.AbstractTestRunner;
+
+import junit.framework.TestCase;
+
+/**
+ * @author <a href="mailto:tom.fennelly at gmail.com">tom.fennelly at gmail.com</a>
+ */
+public class BOMFilterUnitTest extends TestCase {
+
+	public void test_bytearray_with_BOM() throws ActionProcessingException, IOException {
+		BOMFilter bomFilter = createBOMFilter("UTF-8");
+		Message message = MessageFactory.getInstance().getMessage();
+		byte[] byteArray = createBuffer("<x/>", "UTF-8");
+		
+		message.getBody().add(byteArray);
+		assertNotSame("<x/>", new String((byte[])message.getBody().get(), "UTF-8"));
+		message = bomFilter.process(message);
+		assertEquals("<x/>", new String((byte[])message.getBody().get(), "UTF-8"));
+	}
+
+	public void test_bytearray_without_BOM() throws ActionProcessingException, IOException {
+		BOMFilter bomFilter = createBOMFilter("UTF-8");
+		Message message = MessageFactory.getInstance().getMessage();
+		byte[] byteArray = "<x/>".getBytes("UTF-8");
+		
+		message.getBody().add(byteArray);
+		assertEquals("<x/>", new String((byte[])message.getBody().get(), "UTF-8"));
+		message = bomFilter.process(message);
+		assertEquals("<x/>", new String((byte[])message.getBody().get(), "UTF-8"));
+	}
+
+	public void test_bytearray_with_BOM_message_defined_encoding() throws ActionProcessingException, IOException {
+		BOMFilter bomFilter = createBOMFilter(null);
+		Message message = MessageFactory.getInstance().getMessage();
+		byte[] byteArray = createBuffer("<x/>", "UTF-8");
+		
+		message.getBody().add(byteArray);
+		message.getProperties().setProperty(ActionProcessingConstants.PROPERTY_PAYLOAD_CONTENT_ENCODING, "UTF-8");
+		
+		assertNotSame("<x/>", new String((byte[])message.getBody().get(), "UTF-8"));
+		message = bomFilter.process(message);
+		assertEquals("<x/>", new String((byte[])message.getBody().get(), "UTF-8"));
+	}
+
+	public void test_InputStream_with_BOM() throws ActionProcessingException, IOException {
+		BOMFilter bomFilter = createBOMFilter("UTF-8");
+		Message message = MessageFactory.getInstance().getMessage();
+		byte[] byteArray = createBuffer("<x/>", "UTF-8");
+		
+		message.getBody().add(new ByteArrayInputStream(byteArray));
+		message = bomFilter.process(message);
+		InputStream bomFilteredInputStream = (InputStream) message.getBody().get();
+		
+		String dataString = StreamUtils.readStreamString(bomFilteredInputStream, "UTF-8");
+		
+		assertEquals("<x/>", dataString);
+	}
+
+	public void test_InputStream_without_BOM() throws ActionProcessingException, IOException {
+		BOMFilter bomFilter = createBOMFilter("utf8");
+		Message message = MessageFactory.getInstance().getMessage();
+		byte[] byteArray = "<x/>".getBytes("UTF-8");
+		
+		message.getBody().add(new ByteArrayInputStream(byteArray));
+		message = bomFilter.process(message);
+		InputStream bomFilteredInputStream = (InputStream) message.getBody().get();
+		
+		String dataString = StreamUtils.readStreamString(bomFilteredInputStream, "UTF-8");
+		
+		assertEquals("<x/>", dataString);
+	}
+	
+    public void test_in_container() throws Exception {
+        AbstractTestRunner testRunner = new AbstractTestRunner() {
+            public void test() throws Exception {
+                ServiceInvoker invoker = new ServiceInvoker("Services", "ServiceA");
+        		Message message = MessageFactory.getInstance().getMessage();
+        		byte[] byteArray = createBuffer("<x/>", "UTF-8");
+
+        		message.getBody().add(byteArray);
+        		assertNotSame("<x/>", new String((byte[])message.getBody().get(), "UTF-8"));
+                message = invoker.deliverSync(message, 10000);
+        		assertEquals("<x/>", new String((byte[])message.getBody().get(), "UTF-8"));
+            }
+        }.setServiceConfig("BOMFilterTest-config01.xml");
+
+        testRunner.run();
+    }	
+
+	private BOMFilter createBOMFilter(String contentEncoding) {
+		ConfigTree config = new ConfigTree("x");
+		
+		if (contentEncoding != null) {
+			config.setAttribute("contentEncoding", contentEncoding);
+		}
+		
+		return new BOMFilter(config);
+	}
+
+	private byte[] createBuffer(String data, String encoding) throws ActionProcessingException, IOException {
+		ByteArrayOutputStream os = new ByteArrayOutputStream();
+		os.write(BOMFilter.getBOM(encoding));
+		os.write(data.getBytes(encoding));
+		return os.toByteArray();
+	}
+}


Property changes on: labs/jbossesb/branches/JBESB_4_10_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/converters/BOMFilterUnitTest.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Id Revision
Added: svn:eol-style
   + LF



More information about the jboss-svn-commits mailing list