[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