You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by se...@apache.org on 2017/02/13 21:41:10 UTC

[1/2] camel git commit: [CAMEL-10786] Initial implementation of Camel Azure Component starting from Blob Service

Repository: camel
Updated Branches:
  refs/heads/master 0548f87de -> a3b9b0f38


http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/resources/META-INF/services/org/apache/camel/TypeConverter b/components/camel-azure/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
new file mode 100644
index 0000000..ded98e1
--- /dev/null
+++ b/components/camel-azure/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/resources/META-INF/services/org/apache/camel/component/azure-blob
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/resources/META-INF/services/org/apache/camel/component/azure-blob b/components/camel-azure/src/main/resources/META-INF/services/org/apache/camel/component/azure-blob
new file mode 100644
index 0000000..285f97d
--- /dev/null
+++ b/components/camel-azure/src/main/resources/META-INF/services/org/apache/camel/component/azure-blob
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+class=org.apache.camel.component.azure.blob.BlobServiceComponent

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceAppendConsumerTest.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceAppendConsumerTest.java b/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceAppendConsumerTest.java
new file mode 100644
index 0000000..34fef1c
--- /dev/null
+++ b/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceAppendConsumerTest.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.camel.component.azure.blob;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+
+import com.microsoft.azure.storage.StorageCredentialsAccountAndKey;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.JndiRegistry;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.camel.util.IOHelper;
+import org.junit.Ignore;
+import org.junit.Test;
+
+
+public class BlobServiceAppendConsumerTest extends CamelTestSupport {
+    @EndpointInject(uri = "direct:start")
+    ProducerTemplate templateStart;
+    
+    @Test
+    @Ignore
+    public void testGetAppendBlob() throws Exception {
+        templateStart.send("direct:start", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("Append Blob");
+            }
+        });
+        
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        
+        assertMockEndpointsSatisfied();
+        File f = mock.getExchanges().get(0).getIn().getBody(File.class);
+        assertNotNull("File must be set", f);
+        try {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
+            IOHelper.copy(new FileInputStream(f), bos);
+            String data = bos.toString("UTF-8");
+            assertEquals("Append Blob", data);
+        } finally {
+            if (f != null) {
+                f.delete();
+            }
+        }
+    }
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        JndiRegistry registry = super.createRegistry();
+        
+        registry.bind("creds", 
+                      new StorageCredentialsAccountAndKey("camelazure",
+                                                          "base64EncodedValue"));
+        
+        return registry;
+    }
+    
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                    .to("azure-blob://camelazure/container1/blobAppend?credentials=#creds&operation=updateAppendBlob");
+                
+                from("azure-blob://camelazure/container1/blobAppend?credentials=#creds&blobType=appendblob"
+                    + "&fileDir=" + System.getProperty("java.io.tmpdir"))
+                    .to("mock:result");
+            }
+        };
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceBlockConsumerTest.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceBlockConsumerTest.java b/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceBlockConsumerTest.java
new file mode 100644
index 0000000..19b9920
--- /dev/null
+++ b/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceBlockConsumerTest.java
@@ -0,0 +1,91 @@
+/**
+ * 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.camel.component.azure.blob;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+
+import com.microsoft.azure.storage.StorageCredentialsAccountAndKey;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.JndiRegistry;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.camel.util.IOHelper;
+import org.junit.Ignore;
+import org.junit.Test;
+
+
+public class BlobServiceBlockConsumerTest extends CamelTestSupport {
+    @EndpointInject(uri = "direct:start")
+    ProducerTemplate templateStart;
+    
+    @Test
+    @Ignore
+    public void testGetBlockBlob() throws Exception {
+        templateStart.send("direct:start", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("Block Blob");
+            }
+        });
+        
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        
+        assertMockEndpointsSatisfied();
+        File f = mock.getExchanges().get(0).getIn().getBody(File.class);
+        assertNotNull("File must be set", f);
+        try {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
+            IOHelper.copy(new FileInputStream(f), bos);
+            assertEquals("Block Blob", bos.toString("UTF-8"));
+        } finally {
+            if (f != null) {
+                f.delete();
+            }
+        }
+    }
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        JndiRegistry registry = super.createRegistry();
+        
+        registry.bind("creds", 
+                      new StorageCredentialsAccountAndKey("camelazure",
+                                                          "base64EncodedValue"));
+        
+        return registry;
+    }
+    
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                    .to("azure-blob://camelazure/container1/blobBlock?credentials=#creds&operation=updateBlockBlob");
+                
+                from("azure-blob://camelazure/container1/blobBlock?credentials=#creds&fileDir="
+                    + System.getProperty("java.io.tmpdir")).to("mock:result");
+            }
+        };
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceComponentConfigurationTest.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceComponentConfigurationTest.java b/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceComponentConfigurationTest.java
new file mode 100644
index 0000000..ab23553
--- /dev/null
+++ b/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceComponentConfigurationTest.java
@@ -0,0 +1,203 @@
+/**
+ * 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.camel.component.azure.blob;
+
+import java.net.URI;
+import java.util.Collections;
+
+import com.microsoft.azure.storage.StorageCredentials;
+import com.microsoft.azure.storage.StorageCredentialsAccountAndKey;
+import com.microsoft.azure.storage.blob.CloudBlockBlob;
+import com.microsoft.azure.storage.core.Base64;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.impl.JndiRegistry;
+import org.apache.camel.impl.PropertyPlaceholderDelegateRegistry;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class BlobServiceComponentConfigurationTest extends CamelTestSupport {
+    
+    @Test
+    public void testCreateEndpointWithMinConfigForClientOnly() throws Exception {
+        CloudBlockBlob client = 
+            new CloudBlockBlob(URI.create("https://camelazure.blob.core.windows.net/container/blob"));
+        
+        JndiRegistry registry = (JndiRegistry) ((PropertyPlaceholderDelegateRegistry) context.getRegistry()).getRegistry();
+        registry.bind("azureBlobClient", client);
+        
+        BlobServiceComponent component = new BlobServiceComponent(context);
+        BlobServiceEndpoint endpoint = 
+            (BlobServiceEndpoint) component.createEndpoint("azure-blob://camelazure/container/blob?azureBlobClient=#azureBlobClient");
+        
+        doTestCreateEndpointWithMinConfig(endpoint, true);
+    }
+    
+    @Test
+    public void testCreateEndpointWithMinConfigForCredsOnly() throws Exception {
+        registerCredentials();
+        
+        BlobServiceComponent component = new BlobServiceComponent(context);
+        BlobServiceEndpoint endpoint = 
+            (BlobServiceEndpoint) component.createEndpoint("azure-blob://camelazure/container/blob?credentials=#creds");
+        
+        doTestCreateEndpointWithMinConfig(endpoint, false);
+    }
+    
+    private void doTestCreateEndpointWithMinConfig(BlobServiceEndpoint endpoint, boolean clientExpected)
+        throws Exception {
+        assertEquals("camelazure", endpoint.getConfiguration().getAccountName());
+        assertEquals("container", endpoint.getConfiguration().getContainerName());
+        assertEquals("blob", endpoint.getConfiguration().getBlobName());
+        if (clientExpected) {
+            assertNotNull(endpoint.getConfiguration().getAzureBlobClient());
+            assertNull(endpoint.getConfiguration().getCredentials());
+        } else {
+            assertNull(endpoint.getConfiguration().getAzureBlobClient());
+            assertNotNull(endpoint.getConfiguration().getCredentials());
+        }
+        
+        assertEquals(BlobType.blockblob, endpoint.getConfiguration().getBlobType());
+        assertNull(endpoint.getConfiguration().getBlobPrefix());
+        assertNull(endpoint.getConfiguration().getFileDir());
+        assertEquals(Long.valueOf(0L), endpoint.getConfiguration().getBlobOffset());
+        assertNull(endpoint.getConfiguration().getBlobMetadata());
+        assertNull(endpoint.getConfiguration().getDataLength());
+        assertEquals(BlobServiceOperations.listBlobs, endpoint.getConfiguration().getOperation());
+        assertEquals(0, endpoint.getConfiguration().getStreamWriteSize());
+        assertEquals(0, endpoint.getConfiguration().getStreamReadSize());
+        assertTrue(endpoint.getConfiguration().isCloseStreamAfterRead());
+        assertTrue(endpoint.getConfiguration().isCloseStreamAfterWrite());
+        assertFalse(endpoint.getConfiguration().isPublicForRead());
+        assertTrue(endpoint.getConfiguration().isUseFlatListing());
+        
+        createConsumer(endpoint);
+    }
+    
+    @Test
+    public void testCreateEndpointWithMaxConfig() throws Exception {
+        registerCredentials();
+        ((JndiRegistry) ((PropertyPlaceholderDelegateRegistry) context.getRegistry()).getRegistry())
+            .bind("metadata", Collections.emptyMap());
+        
+        BlobServiceComponent component = new BlobServiceComponent(context);
+        BlobServiceEndpoint endpoint = 
+            (BlobServiceEndpoint) component.createEndpoint(
+            "azure-blob://camelazure/container/blob?credentials=#creds&blobType=pageblob"
+            + "&blobPrefix=blob1&fileDir=/tmp&blobOffset=512&operation=clearPageBlob&dataLength=1024"
+            + "&streamWriteSize=512&streamReadSize=1024&closeStreamAfterRead=false&closeStreamAfterWrite=false"
+            + "&publicForRead=true&useFlatListing=false&blobMetadata=#metadata");
+        
+        assertEquals("camelazure", endpoint.getConfiguration().getAccountName());
+        assertEquals("container", endpoint.getConfiguration().getContainerName());
+        assertEquals("blob", endpoint.getConfiguration().getBlobName());
+        assertNull(endpoint.getConfiguration().getAzureBlobClient());
+        assertNotNull(endpoint.getConfiguration().getCredentials());
+        
+        assertEquals(BlobType.pageblob, endpoint.getConfiguration().getBlobType());
+        assertEquals("blob1", endpoint.getConfiguration().getBlobPrefix());
+        assertEquals("/tmp", endpoint.getConfiguration().getFileDir());
+        assertEquals(Long.valueOf(512L), endpoint.getConfiguration().getBlobOffset());
+        assertNotNull(endpoint.getConfiguration().getBlobMetadata());
+        assertEquals(Long.valueOf(1024L), endpoint.getConfiguration().getDataLength());
+        assertEquals(BlobServiceOperations.clearPageBlob, endpoint.getConfiguration().getOperation());
+        assertEquals(512, endpoint.getConfiguration().getStreamWriteSize());
+        assertEquals(1024, endpoint.getConfiguration().getStreamReadSize());
+        assertFalse(endpoint.getConfiguration().isCloseStreamAfterRead());
+        assertFalse(endpoint.getConfiguration().isCloseStreamAfterWrite());
+        assertTrue(endpoint.getConfiguration().isPublicForRead());
+        assertFalse(endpoint.getConfiguration().isUseFlatListing());
+    }
+    
+    @Test
+    public void testNoClientAndCredentials() throws Exception {
+        BlobServiceComponent component = new BlobServiceComponent(context);
+        try {
+            component.createEndpoint("azure-blob://camelazure/container/blob");
+            fail();
+        } catch (IllegalArgumentException ex) {
+            assertEquals("Credentials must be specified.", ex.getMessage());
+        }
+    }
+    @Test
+    public void testNoClientAndCredentialsPublicForRead() throws Exception {
+        BlobServiceComponent component = new BlobServiceComponent(context);
+        BlobServiceEndpoint endpoint = 
+            (BlobServiceEndpoint) component.createEndpoint("azure-blob://camelazure/container/blob?publicForRead=true");
+        assertTrue(endpoint.getConfiguration().isPublicForRead());
+    }
+    
+    
+    @Test
+    public void testNoBlobNameProducerWithOp() throws Exception {
+        registerCredentials();
+        BlobServiceComponent component = new BlobServiceComponent(context);
+        BlobServiceEndpoint endpointWithOp = 
+            (BlobServiceEndpoint) component.createEndpoint(
+            "azure-blob://camelazure/container?operation=deleteBlob&credentials=#creds");
+        try {
+            endpointWithOp.createProducer();
+            fail();
+        } catch (IllegalArgumentException ex) {
+            assertEquals("Blob name must be specified.", ex.getMessage());
+        }
+    }
+    @Test
+    public void testNoBlobNameProducerDefaultOp() throws Exception {
+        registerCredentials();
+        BlobServiceComponent component = new BlobServiceComponent(context);
+        BlobServiceEndpoint endpoint = 
+            (BlobServiceEndpoint) component.createEndpoint(
+            "azure-blob://camelazure/container?credentials=#creds");
+        endpoint.createProducer();
+        assertEquals(BlobServiceOperations.listBlobs, endpoint.getConfiguration().getOperation());
+    }
+    
+    @Test
+    public void testNoBlobNameConsumer() throws Exception {
+        registerCredentials();
+        BlobServiceComponent component = new BlobServiceComponent(context);
+        BlobServiceEndpoint endpoint = 
+            (BlobServiceEndpoint) component.createEndpoint(
+            "azure-blob://camelazure/container?credentials=#creds");
+        try {
+            createConsumer(endpoint);
+            fail();
+        } catch (IllegalArgumentException ex) {
+            assertEquals("Blob name must be specified.", ex.getMessage());
+        }
+    }
+    
+    private static void createConsumer(Endpoint endpoint) throws Exception {
+        endpoint.createConsumer(new Processor() {
+
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                // TODO Auto-generated method stub
+                    
+            }
+        });
+    }
+    
+    private void registerCredentials() {
+        StorageCredentials creds = new StorageCredentialsAccountAndKey("camelazure", 
+                                                                       Base64.encode("key".getBytes()));
+        JndiRegistry registry = (JndiRegistry) ((PropertyPlaceholderDelegateRegistry) context.getRegistry()).getRegistry();
+        registry.bind("creds", creds);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceProducerSpringTest.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceProducerSpringTest.java b/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceProducerSpringTest.java
new file mode 100644
index 0000000..05265a4
--- /dev/null
+++ b/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceProducerSpringTest.java
@@ -0,0 +1,136 @@
+/**
+ * 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.camel.component.azure.blob;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.spring.CamelSpringTestSupport;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class BlobServiceProducerSpringTest extends CamelSpringTestSupport {
+    
+    @EndpointInject(uri = "direct:start")
+    private ProducerTemplate template;
+    
+    @EndpointInject(uri = "mock:result")
+    private MockEndpoint result;
+    
+    @Test
+    @Ignore
+    public void testUpdateBlockBlob() throws Exception {
+        result.expectedMessageCount(1);
+        
+        template.send("direct:updateBlockBlob", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("Block Blob");
+            }
+        });
+        
+        assertMockEndpointsSatisfied();
+        
+        assertResultExchange(result.getExchanges().get(0));
+        
+    }
+    
+    @Test
+    @Ignore
+    public void testUploadBlobBlocks() throws Exception {
+        result.expectedMessageCount(1);
+        final BlobBlock st = new BlobBlock(new ByteArrayInputStream("Block Blob List".getBytes()));
+        template.send("direct:uploadBlobBlocks", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody(st);
+            }
+        });
+        
+        assertMockEndpointsSatisfied();
+        
+        assertResultExchange(result.getExchanges().get(0));
+        
+    }
+    @Test
+    @Ignore
+    public void testGetBlockBlob() throws Exception {
+        result.expectedMessageCount(1);
+        OutputStream os = new ByteArrayOutputStream();
+        template.send("direct:getBlockBlob", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody(os);
+            }
+        });
+        
+        assertMockEndpointsSatisfied();
+        
+        assertResultExchange(result.getExchanges().get(0));
+        
+    }
+    
+    @Test
+    @Ignore
+    public void testUpdateAppendBlob() throws Exception {
+        result.expectedMessageCount(1);
+        
+        template.send("direct:updateAppendBlob", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("Append Blob");
+            }
+        });
+        
+        assertMockEndpointsSatisfied();
+        
+        assertResultExchange(result.getExchanges().get(0));
+        
+    }
+    
+    @Test
+    @Ignore
+    public void testUpdatePageBlob() throws Exception {
+        result.expectedMessageCount(1);
+        final byte[] data = new byte[512];
+        Arrays.fill(data, (byte)1);
+        template.send("direct:updatePageBlob", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody(new ByteArrayInputStream(data));
+            }
+        });
+        
+        assertMockEndpointsSatisfied();
+        
+        assertResultExchange(result.getExchanges().get(0));
+        
+    }
+    
+    private void assertResultExchange(Exchange resultExchange) {
+    }
+    
+    @Override
+    protected ClassPathXmlApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/component/azure/blob/BlobServiceProducerSpringTest-context.xml");
+    }
+    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceUtilTest.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceUtilTest.java b/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceUtilTest.java
new file mode 100644
index 0000000..404daff
--- /dev/null
+++ b/components/camel-azure/src/test/java/org/apache/camel/component/azure/blob/BlobServiceUtilTest.java
@@ -0,0 +1,48 @@
+/**
+ * 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.camel.component.azure.blob;
+
+import java.net.URI;
+
+import com.microsoft.azure.storage.StorageCredentials;
+import com.microsoft.azure.storage.StorageCredentialsAccountAndKey;
+import com.microsoft.azure.storage.core.Base64;
+import org.apache.camel.impl.JndiRegistry;
+import org.apache.camel.impl.PropertyPlaceholderDelegateRegistry;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+
+public class BlobServiceUtilTest extends CamelTestSupport {
+    @Test
+    public void testPrepareUri() throws Exception {
+        registerCredentials();
+        
+        BlobServiceComponent component = new BlobServiceComponent(context);
+        BlobServiceEndpoint endpoint = 
+            (BlobServiceEndpoint) component.createEndpoint("azure-blob://camelazure/container/blob?credentials=#creds");
+        URI uri = 
+            BlobServiceUtil.prepareStorageBlobUri(endpoint.getConfiguration());
+        assertEquals("https://camelazure.blob.core.windows.net/container/blob", uri.toString());
+    }
+    private void registerCredentials() {
+        StorageCredentials creds = new StorageCredentialsAccountAndKey("camelazure", 
+                                                                       Base64.encode("key".getBytes()));
+        JndiRegistry registry = (JndiRegistry) ((PropertyPlaceholderDelegateRegistry) context.getRegistry()).getRegistry();
+        registry.bind("creds", creds);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/test/resources/log4j2.properties
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/test/resources/log4j2.properties b/components/camel-azure/src/test/resources/log4j2.properties
new file mode 100644
index 0000000..07111be
--- /dev/null
+++ b/components/camel-azure/src/test/resources/log4j2.properties
@@ -0,0 +1,28 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-aws-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/test/resources/org/apache/camel/component/azure/blob/BlobServiceProducerSpringTest-context.xml
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/test/resources/org/apache/camel/component/azure/blob/BlobServiceProducerSpringTest-context.xml b/components/camel-azure/src/test/resources/org/apache/camel/component/azure/blob/BlobServiceProducerSpringTest-context.xml
new file mode 100644
index 0000000..fe31fda
--- /dev/null
+++ b/components/camel-azure/src/test/resources/org/apache/camel/component/azure/blob/BlobServiceProducerSpringTest-context.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+    http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
+
+    <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
+        <route>
+            <from uri="direct:updateBlockBlob"/>
+            <to uri="azure-blob://camelazure/container1/blob1?credentials=#credentials&amp;operation=updateBlockBlob"/>
+            <to uri="mock:result"/>
+        </route>
+        <route>
+            <from uri="direct:getBlockBlob"/>
+            <to uri="azure-blob://camelazure/container1/blob1?credentials=#credentials&amp;operation=getBlockBlob"/>
+            <to uri="mock:result"/>
+        </route>
+        <route>
+            <from uri="direct:uploadBlobBlocks"/>
+            <to uri="azure-blob://camelazure/container1/blob1?credentials=#credentials&amp;operation=uploadBlobBlocks"/>
+            <to uri="mock:result"/>
+        </route>
+        <route>
+            <from uri="direct:updateAppendBlob"/>
+            <to uri="azure-blob://camelazure/container1/blob1?credentials=#credentials&amp;operation=updateAppendBlob"/>
+            <to uri="mock:result"/>
+        </route>
+        <route>
+            <from uri="direct:updatePageBlob"/>
+            <to uri="azure-blob://camelazure/container1/blob1?credentials=#credentials&amp;operation=updatePageBlob"/>
+            <to uri="mock:result"/>
+        </route>
+        
+    </camelContext>
+
+    <bean id="credentials" class="com.microsoft.azure.storage.StorageCredentialsAccountAndKey">
+      <constructor-arg value="camelazure"/>
+      <constructor-arg value="base64EncodedValue"/>
+    </bean>
+</beans>

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/pom.xml
----------------------------------------------------------------------
diff --git a/components/pom.xml b/components/pom.xml
index def344c..b265d79 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -72,6 +72,7 @@
     <module>camel-atom</module>
     <module>camel-avro</module>
     <module>camel-aws</module>
+    <module>camel-azure</module>
     <module>camel-base64</module>
     <module>camel-beanio</module>
     <module>camel-beanstalk</module>

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/platforms/spring-boot/components-starter/camel-azure-starter/pom.xml
----------------------------------------------------------------------
diff --git a/platforms/spring-boot/components-starter/camel-azure-starter/pom.xml b/platforms/spring-boot/components-starter/camel-azure-starter/pom.xml
new file mode 100644
index 0000000..ed2c702
--- /dev/null
+++ b/platforms/spring-boot/components-starter/camel-azure-starter/pom.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>components-starter</artifactId>
+    <version>2.19.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>camel-azure-starter</artifactId>
+  <packaging>jar</packaging>
+  <name>Spring-Boot Starter :: Camel :: Azure</name>
+  <description>Spring-Boot Starter for Camel Microsoft Azure Components</description>
+  <dependencies>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter</artifactId>
+      <version>${spring-boot-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-azure</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <!--START OF GENERATED CODE-->
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-core-starter</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-spring-boot-starter</artifactId>
+    </dependency>
+    <!--END OF GENERATED CODE-->
+  </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/platforms/spring-boot/components-starter/camel-azure-starter/src/main/java/org/apache/camel/component/azure/blob/springboot/BlobServiceComponentAutoConfiguration.java
----------------------------------------------------------------------
diff --git a/platforms/spring-boot/components-starter/camel-azure-starter/src/main/java/org/apache/camel/component/azure/blob/springboot/BlobServiceComponentAutoConfiguration.java b/platforms/spring-boot/components-starter/camel-azure-starter/src/main/java/org/apache/camel/component/azure/blob/springboot/BlobServiceComponentAutoConfiguration.java
new file mode 100644
index 0000000..fdb4dfc
--- /dev/null
+++ b/platforms/spring-boot/components-starter/camel-azure-starter/src/main/java/org/apache/camel/component/azure/blob/springboot/BlobServiceComponentAutoConfiguration.java
@@ -0,0 +1,80 @@
+/**
+ * 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.camel.component.azure.blob.springboot;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.azure.blob.BlobServiceComponent;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionMessage;
+import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
+import org.springframework.boot.bind.RelaxedPropertyResolver;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ConditionContext;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.core.type.AnnotatedTypeMetadata;
+
+/**
+ * Generated by camel-package-maven-plugin - do not edit this file!
+ */
+@Configuration
+@ConditionalOnBean(type = "org.apache.camel.spring.boot.CamelAutoConfiguration")
+@Conditional(BlobServiceComponentAutoConfiguration.Condition.class)
+@AutoConfigureAfter(name = "org.apache.camel.spring.boot.CamelAutoConfiguration")
+public class BlobServiceComponentAutoConfiguration {
+
+    @Lazy
+    @Bean(name = "azure-blob-component")
+    @ConditionalOnClass(CamelContext.class)
+    @ConditionalOnMissingBean(BlobServiceComponent.class)
+    public BlobServiceComponent configureBlobServiceComponent(
+            CamelContext camelContext) throws Exception {
+        BlobServiceComponent component = new BlobServiceComponent();
+        component.setCamelContext(camelContext);
+        return component;
+    }
+
+    public static class Condition extends SpringBootCondition {
+        @Override
+        public ConditionOutcome getMatchOutcome(
+                ConditionContext conditionContext,
+                AnnotatedTypeMetadata annotatedTypeMetadata) {
+            boolean groupEnabled = isEnabled(conditionContext,
+                    "camel.component.", true);
+            ConditionMessage.Builder message = ConditionMessage
+                    .forCondition("camel.component.azure-blob");
+            if (isEnabled(conditionContext, "camel.component.azure-blob.",
+                    groupEnabled)) {
+                return ConditionOutcome.match(message.because("enabled"));
+            }
+            return ConditionOutcome.noMatch(message.because("not enabled"));
+        }
+
+        private boolean isEnabled(
+                org.springframework.context.annotation.ConditionContext context,
+                java.lang.String prefix, boolean defaultValue) {
+            RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
+                    context.getEnvironment(), prefix);
+            return resolver.getProperty("enabled", Boolean.class, defaultValue);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/LICENSE.txt
----------------------------------------------------------------------
diff --git a/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/LICENSE.txt b/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/LICENSE.txt
new file mode 100644
index 0000000..6b0b127
--- /dev/null
+++ b/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/LICENSE.txt
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/NOTICE.txt
----------------------------------------------------------------------
diff --git a/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/NOTICE.txt b/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/NOTICE.txt
new file mode 100644
index 0000000..2e215bf
--- /dev/null
+++ b/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/NOTICE.txt
@@ -0,0 +1,11 @@
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Apache Camel distribution.                    ==
+   =========================================================================
+
+   This product includes software developed by
+   The Apache Software Foundation (http://www.apache.org/).
+
+   Please read the different LICENSE files present in the licenses directory of
+   this distribution.

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json
----------------------------------------------------------------------
diff --git a/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json
new file mode 100644
index 0000000..b9abe08
--- /dev/null
+++ b/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -0,0 +1,10 @@
+{
+  "properties": [
+    {
+      "defaultValue": true,
+      "name": "camel.component.azure-blob.enabled",
+      "description": "Enable azure-blob component",
+      "type": "java.lang.Boolean"
+    }
+  ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/spring.factories
----------------------------------------------------------------------
diff --git a/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/spring.factories b/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..7ecd61b
--- /dev/null
+++ b/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+org.apache.camel.component.azure.blob.springboot.BlobServiceComponentAutoConfiguration

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/spring.provides
----------------------------------------------------------------------
diff --git a/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/spring.provides b/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/spring.provides
new file mode 100644
index 0000000..f69c8d2
--- /dev/null
+++ b/platforms/spring-boot/components-starter/camel-azure-starter/src/main/resources/META-INF/spring.provides
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+provides: camel-azure
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/platforms/spring-boot/components-starter/pom.xml
----------------------------------------------------------------------
diff --git a/platforms/spring-boot/components-starter/pom.xml b/platforms/spring-boot/components-starter/pom.xml
index 052e3d8..d2ca7fa 100644
--- a/platforms/spring-boot/components-starter/pom.xml
+++ b/platforms/spring-boot/components-starter/pom.xml
@@ -83,6 +83,7 @@
     <module>camel-atom-starter</module>
     <module>camel-avro-starter</module>
     <module>camel-aws-starter</module>
+    <module>camel-azure-starter</module>
     <module>camel-bam-starter</module>
     <module>camel-barcode-starter</module>
     <module>camel-base64-starter</module>


[2/2] camel git commit: [CAMEL-10786] Initial implementation of Camel Azure Component starting from Blob Service

Posted by se...@apache.org.
[CAMEL-10786] Initial implementation of Camel Azure Component starting from Blob Service


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/a3b9b0f3
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/a3b9b0f3
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/a3b9b0f3

Branch: refs/heads/master
Commit: a3b9b0f38397b8245f3774a20cc60782b2d94dd8
Parents: 0548f87
Author: Sergey Beryozkin <sb...@gmail.com>
Authored: Mon Feb 13 21:40:52 2017 +0000
Committer: Sergey Beryozkin <sb...@gmail.com>
Committed: Mon Feb 13 21:40:52 2017 +0000

----------------------------------------------------------------------
 components/camel-azure/pom.xml                  |  69 +++
 .../camel/component/azure/blob/BlobBlock.java   |  51 ++
 .../azure/blob/BlobServiceComponent.java        |  76 +++
 .../azure/blob/BlobServiceConfiguration.java    | 252 ++++++++++
 .../azure/blob/BlobServiceConstants.java        |  36 ++
 .../azure/blob/BlobServiceConsumer.java         |  69 +++
 .../azure/blob/BlobServiceEndpoint.java         |  95 ++++
 .../azure/blob/BlobServiceOperations.java       |  83 ++++
 .../azure/blob/BlobServiceProducer.java         | 481 +++++++++++++++++++
 .../azure/blob/BlobServiceRequestOptions.java   |  45 ++
 .../component/azure/blob/BlobServiceUtil.java   | 231 +++++++++
 .../camel/component/azure/blob/BlobType.java    |  30 ++
 .../azure/common/AbstractConfiguration.java     |  52 ++
 .../component/azure/common/ExchangeUtil.java    |  35 ++
 .../src/main/resources/META-INF/LICENSE.txt     | 203 ++++++++
 .../src/main/resources/META-INF/NOTICE.txt      |  11 +
 .../services/org/apache/camel/TypeConverter     |  17 +
 .../org/apache/camel/component/azure-blob       |  18 +
 .../blob/BlobServiceAppendConsumerTest.java     |  93 ++++
 .../blob/BlobServiceBlockConsumerTest.java      |  91 ++++
 .../BlobServiceComponentConfigurationTest.java  | 203 ++++++++
 .../blob/BlobServiceProducerSpringTest.java     | 136 ++++++
 .../azure/blob/BlobServiceUtilTest.java         |  48 ++
 .../src/test/resources/log4j2.properties        |  28 ++
 .../BlobServiceProducerSpringTest-context.xml   |  56 +++
 components/pom.xml                              |   1 +
 .../camel-azure-starter/pom.xml                 |  51 ++
 .../BlobServiceComponentAutoConfiguration.java  |  80 +++
 .../src/main/resources/META-INF/LICENSE.txt     | 203 ++++++++
 .../src/main/resources/META-INF/NOTICE.txt      |  11 +
 ...dditional-spring-configuration-metadata.json |  10 +
 .../main/resources/META-INF/spring.factories    |  19 +
 .../src/main/resources/META-INF/spring.provides |  18 +
 .../spring-boot/components-starter/pom.xml      |   1 +
 34 files changed, 2903 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-azure/pom.xml b/components/camel-azure/pom.xml
new file mode 100644
index 0000000..f36c875
--- /dev/null
+++ b/components/camel-azure/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>components</artifactId>
+        <version>2.19.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-azure</artifactId>
+    <packaging>jar</packaging>
+
+    <name>Camel :: Azure</name>
+    <description>Camel Microsoft Azure Components</description>
+
+    <properties>
+        <azure-storage-java-sdk-version>5.0.0</azure-storage-java-sdk-version>
+        <powermock-easymock-version>1.6.6</powermock-easymock-version>
+        <camel.osgi.export.pkg>org.apache.camel.component.azure.*</camel.osgi.export.pkg>
+        <camel.osgi.export.service>
+        </camel.osgi.export.service>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.microsoft.azure</groupId>
+            <artifactId>azure-storage</artifactId>
+            <version>${azure-storage-java-sdk-version}</version>
+        </dependency>
+        
+        <!-- for testing -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-spring</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <scope>test</scope>
+        </dependency>
+     </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobBlock.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobBlock.java b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobBlock.java
new file mode 100644
index 0000000..87946ae
--- /dev/null
+++ b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobBlock.java
@@ -0,0 +1,51 @@
+/**
+ * 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.camel.component.azure.blob;
+
+import java.io.InputStream;
+import java.util.UUID;
+
+import com.microsoft.azure.storage.blob.BlockEntry;
+import com.microsoft.azure.storage.blob.BlockSearchMode;
+import com.microsoft.azure.storage.core.Base64;
+
+public class BlobBlock {
+    private InputStream blockStream;
+    private BlockEntry blockEntry;
+    public BlobBlock(InputStream blockStream) {
+        this(Base64.encode(UUID.randomUUID().toString().getBytes()),
+             blockStream);
+    }
+    public BlobBlock(String blockId, InputStream blockStream) {
+        this(blockId, BlockSearchMode.LATEST, blockStream);
+    }
+    public BlobBlock(String blockId, BlockSearchMode searchMode, InputStream blockStream) {
+        this(new BlockEntry(blockId, searchMode), blockStream);
+    }
+    public BlobBlock(BlockEntry blockEntry, InputStream blockStream) {
+        this.blockStream = blockStream;
+        this.blockEntry = blockEntry;
+    }
+    public InputStream getBlockStream() {
+        return blockStream;
+    }
+    public BlockEntry getBlockEntry() {
+        return blockEntry;
+    }
+    
+    
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceComponent.java b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceComponent.java
new file mode 100644
index 0000000..33539a7
--- /dev/null
+++ b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceComponent.java
@@ -0,0 +1,76 @@
+/**
+ * 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.camel.component.azure.blob;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.impl.UriEndpointComponent;
+
+public class BlobServiceComponent extends UriEndpointComponent {
+    
+    public BlobServiceComponent() {
+        super(BlobServiceEndpoint.class);
+    }
+
+    public BlobServiceComponent(CamelContext context) {
+        super(context, BlobServiceEndpoint.class);
+    }
+
+    protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
+        BlobServiceConfiguration configuration = new BlobServiceConfiguration();
+        setProperties(configuration, parameters);
+
+        String[] parts = null;
+        if (remaining != null) {
+            parts = remaining.split("/"); 
+        }
+        if (parts == null || parts.length < 2) {
+            throw new IllegalArgumentException("At least account and container names must be specified.");
+        }
+        
+        configuration.setAccountName(parts[0]);
+        configuration.setContainerName(parts[1]);
+        
+        if (parts.length > 2) {
+            // Blob names can contain forward slashes
+            StringBuilder sb = new StringBuilder();
+            for (int i = 2; i < parts.length; i++) {
+                sb.append(parts[i]);
+                if (i + 1 < parts.length) {
+                    sb.append('/');
+                }
+            }
+            configuration.setBlobName(sb.toString());
+        }
+        
+        checkCredentials(configuration);
+        
+        BlobServiceEndpoint endpoint = new BlobServiceEndpoint(uri, this, configuration);
+        setProperties(endpoint, parameters);
+        return endpoint;
+    }
+    
+    private void checkCredentials(BlobServiceConfiguration configuration) {
+        if (configuration.getAzureBlobClient() == null
+            && configuration.getCredentials() == null
+            && !configuration.isPublicForRead()) {
+            throw new IllegalArgumentException("Credentials must be specified.");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceConfiguration.java b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceConfiguration.java
new file mode 100644
index 0000000..ea155c4
--- /dev/null
+++ b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceConfiguration.java
@@ -0,0 +1,252 @@
+/**
+ * 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.camel.component.azure.blob;
+
+import java.util.Map;
+
+import com.microsoft.azure.storage.blob.CloudBlob;
+import org.apache.camel.component.azure.common.AbstractConfiguration;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriParams;
+
+@UriParams
+public class BlobServiceConfiguration extends AbstractConfiguration {
+
+    private String containerName;
+    
+    private String blobName;
+    
+    @UriParam
+    private CloudBlob azureBlobClient;
+    
+    @UriParam(defaultValue = "blockblob")
+    private BlobType blobType = BlobType.blockblob;
+    
+    @UriParam(label = "producer", defaultValue = "listBlobs")
+    private BlobServiceOperations operation = BlobServiceOperations.listBlobs;
+    
+    @UriParam(label = "producer")
+    private int streamWriteSize;
+    
+    @UriParam
+    private int streamReadSize;
+    
+    @UriParam(label = "producer")
+    private Map<String, String> blobMetadata;
+    
+    @UriParam(defaultValue = "true")
+    private boolean closeStreamAfterRead = true;
+    
+    @UriParam(label = "producer", defaultValue = "true")
+    private boolean closeStreamAfterWrite = true;
+    
+    @UriParam
+    private String fileDir;
+    
+    @UriParam(defaultValue = "0")
+    private Long blobOffset = 0L;
+    
+    @UriParam
+    private Long dataLength;
+    
+    @UriParam
+    private boolean publicForRead;
+    
+    @UriParam(label = "producer")
+    private String blobPrefix;
+    
+    @UriParam(label = "producer", defaultValue = "true")
+    private boolean useFlatListing = true;
+    
+    public BlobServiceOperations getOperation() {
+        return operation;
+    }
+
+    /**
+     * Required blob service operation hint to the producer 
+     */
+    public void setOperation(BlobServiceOperations operation) {
+        this.operation = operation;
+    }
+
+    public String getContainerName() {
+        return containerName;
+    }
+
+    /**
+     * Set the blob service container name 
+     */
+    public void setContainerName(String containerName) {
+        this.containerName = containerName;
+    }
+    
+    public String getBlobName() {
+        return blobName;
+    }
+
+    /**
+     * Blob name, required for most operations
+     */
+    public void setBlobName(String blobName) {
+        this.blobName = blobName;
+    }
+
+    public BlobType getBlobType() {
+        return blobType;
+    }
+
+    /**
+     * Set a blob type, 'blockblob' is default
+     */
+    public void setBlobType(BlobType blobType) {
+        this.blobType = blobType;
+    }
+    
+    public int getStreamWriteSize() {
+        return streamWriteSize;
+    }
+
+    /**
+     * Set the size of the buffer for writing block and page blocks 
+     */
+    public void setStreamWriteSize(int streamWriteSize) {
+        this.streamWriteSize = streamWriteSize;
+    }
+
+    public int getStreamReadSize() {
+        return streamReadSize;
+    }
+
+    /**
+     * Set the minimum read size in bytes when reading the blob content 
+     */
+    public void setStreamReadSize(int streamReadSize) {
+        this.streamReadSize = streamReadSize;
+    }
+
+    public Map<String, String> getBlobMetadata() {
+        return blobMetadata;
+    }
+
+    /**
+     * Set the blob meta-data 
+     */
+    public void setBlobMetadata(Map<String, String> blobMetadata) {
+        this.blobMetadata = blobMetadata;
+    }
+    
+    public CloudBlob getAzureBlobClient() {
+        return azureBlobClient;
+    }
+
+    /**
+     * The blob service client 
+     */
+    public void setAzureBlobClient(CloudBlob azureBlobClient) {
+        this.azureBlobClient = azureBlobClient;
+    }
+
+    public boolean isCloseStreamAfterWrite() {
+        return closeStreamAfterWrite;
+    }
+
+    /**
+     * Close the stream after write or keep it open, default is true
+     */
+    public void setCloseStreamAfterWrite(boolean closeStreamAfterWrite) {
+        this.closeStreamAfterWrite = closeStreamAfterWrite;
+    }
+
+    public boolean isCloseStreamAfterRead() {
+        return closeStreamAfterRead;
+    }
+
+    /**
+     * Close the stream after read or keep it open, default is true
+     */
+    public void setCloseStreamAfterRead(boolean closeStreamAfterRead) {
+        this.closeStreamAfterRead = closeStreamAfterRead;
+    }
+
+    public String getFileDir() {
+        return fileDir;
+    }
+
+    /**
+     * Set the file directory where the downloaded blobs will be saved to 
+     */
+    public void setFileDir(String fileDir) {
+        this.fileDir = fileDir;
+    }
+
+    public Long getBlobOffset() {
+        return blobOffset;
+    }
+
+    /**
+     *  Set the blob offset for the upload or download operations, default is 0 
+     */
+    public void setBlobOffset(Long dataOffset) {
+        this.blobOffset = dataOffset;
+    }
+    
+    public Long getDataLength() {
+        return dataLength;
+    }
+
+    /**
+     * Set the data length for the download or page blob upload operations 
+     */
+    public void setDataLength(Long dataLength) {
+        this.dataLength = dataLength;
+    }
+
+    public boolean isPublicForRead() {
+        return publicForRead;
+    }
+
+    /**
+     * Blobs can be public for reading their content, if this property is enabled
+     * then the credentials do not have to be set
+     */
+    
+    public void setPublicForRead(boolean publicForRead) {
+        this.publicForRead = publicForRead;
+    }
+
+    public String getBlobPrefix() {
+        return blobPrefix;
+    }
+    
+    /**
+     * Set a prefix which can be used for listing the blobs 
+     */
+    public void setBlobPrefix(String blobPrefix) {
+        this.blobPrefix = blobPrefix;
+    }
+
+    public boolean isUseFlatListing() {
+        return useFlatListing;
+    }
+
+    /**
+     * Specify if the flat or hierarchical blob listing should be used 
+     */
+    public void setUseFlatListing(boolean useFlatListing) {
+        this.useFlatListing = useFlatListing;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceConstants.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceConstants.java b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceConstants.java
new file mode 100644
index 0000000..f8f644a
--- /dev/null
+++ b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceConstants.java
@@ -0,0 +1,36 @@
+/**
+ * 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.camel.component.azure.blob;
+
+public interface BlobServiceConstants {
+
+    String OPERATION = "operation";
+    String BLOB_CLIENT = "AzureBlobClient";
+    
+    String SERVICE_URI_SEGMENT = ".blob.core.windows.net";
+    String ACCESS_CONDITION = "BlobAccessCondition";
+    String BLOB_REQUEST_OPTIONS = "BlobRequestOptions";
+    String OPERATION_CONTEXT = "BlobOperationContext";
+    
+    String BLOB_LISTING_DETAILS = "BlobListingDetails";
+    
+    String COMMIT_BLOCK_LIST_LATER = "CommitBlobBlockListLater";
+    String APPEND_BLOCK_CREATED = "AppendBlobCreated";
+    String PAGE_BLOCK_CREATED = "PageBlobCreated";
+    String PAGE_BLOB_RANGE = "PageBlobRange";
+    String PAGE_BLOB_SIZE = "PageBlobSize";
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceConsumer.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceConsumer.java b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceConsumer.java
new file mode 100644
index 0000000..d91c02c
--- /dev/null
+++ b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceConsumer.java
@@ -0,0 +1,69 @@
+/**
+ * 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.camel.component.azure.blob;
+
+import com.microsoft.azure.storage.StorageException;
+import org.apache.camel.Exchange;
+import org.apache.camel.NoFactoryAvailableException;
+import org.apache.camel.Processor;
+import org.apache.camel.impl.ScheduledPollConsumer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A Consumer of the blob content from the Azure Blob Service
+ */
+// Extending DefaultConsumer is simpler if the blob must exist before this consumer is started,
+// polling makes it easier to get the consumer working if no blob exists yet.
+public class BlobServiceConsumer extends ScheduledPollConsumer {
+    private static final Logger LOG = LoggerFactory.getLogger(BlobServiceConsumer.class);
+    
+    public BlobServiceConsumer(BlobServiceEndpoint endpoint, Processor processor) throws NoFactoryAvailableException {
+        super(endpoint, processor);
+    }
+    
+    @Override
+    protected int poll() throws Exception {
+        Exchange exchange = super.getEndpoint().createExchange();
+        try {
+            LOG.trace("Getting the blob content");
+            getBlob(exchange);
+            super.getAsyncProcessor().process(exchange);
+            return 1;
+        } catch (StorageException ex) {
+            if (404 == ex.getHttpStatusCode()) {
+                return 0;
+            } else {
+                throw ex;
+            }
+        }
+    }
+    
+    private void getBlob(Exchange exchange) throws Exception {
+        BlobServiceUtil.getBlob(exchange, getConfiguration());
+    }
+        
+    protected BlobServiceConfiguration getConfiguration() {
+        return getEndpoint().getConfiguration();
+    }
+    @Override
+    public BlobServiceEndpoint getEndpoint() {
+        return (BlobServiceEndpoint) super.getEndpoint();
+    }
+
+    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceEndpoint.java b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceEndpoint.java
new file mode 100644
index 0000000..d2aaa8c
--- /dev/null
+++ b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceEndpoint.java
@@ -0,0 +1,95 @@
+/**
+ * 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.camel.component.azure.blob;
+
+import org.apache.camel.Component;
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.impl.DefaultEndpoint;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriPath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The azure-blob component is used for storing and retrieving blobs from Azure Storage Blob Service.
+ */
+@UriEndpoint(scheme = "azure-blob", 
+             title = "Azure Storage Blob Service", 
+             syntax = "azure-blob:containerOrBlobUri", 
+             consumerClass = BlobServiceConsumer.class,
+             label = "cloud, blob")
+public class BlobServiceEndpoint extends DefaultEndpoint {
+
+    private static final Logger LOG = LoggerFactory.getLogger(BlobServiceEndpoint.class);
+    
+    @UriPath(description = "Container or Blob compact Uri")
+    @Metadata(required = "true")
+    private String containerOrBlobUri; // to support component docs
+    @UriParam
+    private BlobServiceConfiguration configuration;
+    
+
+    public BlobServiceEndpoint(String uri, Component comp, BlobServiceConfiguration configuration) {
+        super(uri, comp);
+        this.configuration = configuration;
+    }
+
+    public Consumer createConsumer(Processor processor) throws Exception {
+        LOG.trace("Creating a consumer");
+        if (getConfiguration().getBlobName() == null) {
+            throw new IllegalArgumentException("Blob name must be specified.");
+        }
+        BlobServiceConsumer consumer = new BlobServiceConsumer(this, processor);
+        configureConsumer(consumer);
+        return consumer;
+    }
+
+    public Producer createProducer() throws Exception {
+        LOG.trace("Creating a producer");
+        if (getConfiguration().getBlobName() == null
+            && getConfiguration().getOperation() != null 
+            && BlobServiceOperations.listBlobs != configuration.getOperation()) {
+            // Omitting a blob name is only possible it is a (default) listBlobs producer operation
+            throw new IllegalArgumentException("Blob name must be specified.");
+        }
+        return new BlobServiceProducer(this);
+    }
+
+    public boolean isSingleton() {
+        return true;
+    }
+
+    @Override
+    public void doStart() throws Exception {
+        super.doStart();
+    }
+
+    public BlobServiceConfiguration getConfiguration() {
+        return configuration;
+    }
+
+    public void setConfiguration(BlobServiceConfiguration configuration) {
+        this.configuration = configuration;
+    }
+    
+
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceOperations.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceOperations.java b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceOperations.java
new file mode 100644
index 0000000..2e12d0f
--- /dev/null
+++ b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceOperations.java
@@ -0,0 +1,83 @@
+/**
+ * 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.camel.component.azure.blob;
+
+public enum BlobServiceOperations {
+    /**
+     * Common to all block types
+     */
+    // Get the content of the blob, can be restricted to a blob range
+    getBlob,
+    // Delete the blob
+    deleteBlob,
+    // List the blobs
+    listBlobs,
+    /*
+     * Bloc blob operations
+     */
+    // Put a block blob content which either creates a new block blob 
+    // or overwrites the existing block blob content
+    updateBlockBlob,
+    
+    // Upload a block blob content as a sequence of blob blocks first and then 
+    // commit them to a blob. The commit can be executed later with the 
+    // commitBlobBlockList operation if a message "CommitBlockListLater" 
+    // property is enabled. Individual block blobs can be updated later.
+    uploadBlobBlocks,
+    
+    // Commit a sequence of blob blocks to the block list which was previously
+    // uploaded to the blob service with the putBlockBlob operation with the commit
+    // being delayed
+    commitBlobBlockList,
+    
+    // Get the block blob list,
+    getBlobBlockList,
+    
+    /*
+     * Append blob operations
+     */
+    // Create an append block. By default if the block already exists then it is not reset.
+    // Note the updateAppendBlob will also try to create an append blob first unless
+    // a message "AppendBlobCreated" property is enabled
+    createAppendBlob,
+    
+    // Create an append block unless a message "AppendBlobCreated" property is enabled and no 
+    // the identically named block already exists and append the new content to this blob.
+    updateAppendBlob,
+    
+    /**
+     * Page Block operations
+     */
+    // Create a page block. By default if the block already exists then it is not reset.
+    // Note the updatePageBlob will also try to create a page blob first unless
+    // a message "PageBlobCreated" property is enabled
+    createPageBlob,
+    
+    // Create a page block unless a message "PageBlobCreated" property is enabled and no 
+    // the identically named block already exists and set the content of this blob.
+    updatePageBlob,
+    
+    // Resize the page blob
+    resizePageBlob,
+    
+    // Clear the page blob
+    clearPageBlob,
+    
+    // Get the page blob page ranges
+    getPageBlobRanges
+    
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceProducer.java b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceProducer.java
new file mode 100644
index 0000000..f50c115
--- /dev/null
+++ b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceProducer.java
@@ -0,0 +1,481 @@
+/**
+ * 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.camel.component.azure.blob;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.microsoft.azure.storage.AccessCondition;
+import com.microsoft.azure.storage.StorageException;
+import com.microsoft.azure.storage.blob.BlobListingDetails;
+import com.microsoft.azure.storage.blob.BlockEntry;
+import com.microsoft.azure.storage.blob.BlockListingFilter;
+import com.microsoft.azure.storage.blob.CloudAppendBlob;
+import com.microsoft.azure.storage.blob.CloudBlob;
+import com.microsoft.azure.storage.blob.CloudBlobContainer;
+import com.microsoft.azure.storage.blob.CloudBlockBlob;
+import com.microsoft.azure.storage.blob.CloudPageBlob;
+import com.microsoft.azure.storage.blob.ListBlobItem;
+import com.microsoft.azure.storage.blob.PageRange;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.azure.common.ExchangeUtil;
+import org.apache.camel.impl.DefaultProducer;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.URISupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A Producer which sends messages to the Azure Storage Blob Service
+ */
+public class BlobServiceProducer extends DefaultProducer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(BlobServiceProducer.class);
+
+    public BlobServiceProducer(final Endpoint endpoint) {
+        super(endpoint);
+    }
+
+
+    @Override
+    public void process(final Exchange exchange) throws Exception {
+        BlobServiceOperations operation = determineOperation(exchange);
+        if (ObjectHelper.isEmpty(operation)) {
+            operation = BlobServiceOperations.listBlobs;
+        } else {
+            switch (operation) {
+            case getBlob:
+                getBlob(exchange);
+                break;
+            case deleteBlob:
+                deleteBlob(exchange);
+                break;    
+            case listBlobs:
+                listBlobs(exchange);
+                break;
+            case updateBlockBlob:
+                updateBlockBlob(exchange);
+                break;
+            case uploadBlobBlocks:
+                uploadBlobBlocks(exchange);
+                break;
+            case commitBlobBlockList:
+                commitBlobBlockList(exchange);
+                break;
+            case getBlobBlockList:
+                getBlobBlockList(exchange);
+                break;    
+            case createAppendBlob:
+                createAppendBlob(exchange);
+                break;    
+            case updateAppendBlob:
+                updateAppendBlob(exchange);
+                break;
+            case createPageBlob:
+                createPageBlob(exchange);
+                break;
+            case updatePageBlob:
+                uploadPageBlob(exchange);
+                break;
+            case resizePageBlob:
+                resizePageBlob(exchange);
+                break;
+            case clearPageBlob:
+                clearPageBlob(exchange);
+                break;
+            case getPageBlobRanges:
+                getPageBlobRanges(exchange);
+                break;    
+            default:
+                throw new IllegalArgumentException("Unsupported operation");
+            }
+        }     
+    }
+    
+    private void listBlobs(Exchange exchange) throws Exception {
+        CloudBlobContainer client = BlobServiceUtil.createBlobContainerClient(getConfiguration());
+        BlobServiceRequestOptions opts = BlobServiceUtil.getRequestOptions(exchange);
+        LOG.trace("Getting the blob list from the container [{}] from exchange [{}]...", 
+                  getConfiguration().getContainerName(), exchange);
+        BlobServiceConfiguration cfg = getConfiguration();
+        @SuppressWarnings("unchecked")
+        EnumSet<BlobListingDetails> details = 
+            (EnumSet<BlobListingDetails>)exchange.getIn().getHeader(BlobServiceConstants.BLOB_LISTING_DETAILS); 
+        Iterable<ListBlobItem> items = 
+            client.listBlobs(cfg.getBlobPrefix(), cfg.isUseFlatListing(), 
+                             details, opts.getRequestOpts(), opts.getOpContext());
+        ExchangeUtil.getMessageForResponse(exchange).setBody(items);
+    }
+    
+    private void updateBlockBlob(Exchange exchange) throws Exception {
+        CloudBlockBlob client = BlobServiceUtil.createBlockBlobClient(getConfiguration(), true);
+        configureCloudBlobForWrite(client);
+        BlobServiceRequestOptions opts = BlobServiceUtil.getRequestOptions(exchange);
+        
+        InputStream inputStream = getInputStreamFromExchange(exchange);
+        
+        LOG.trace("Putting a block blob [{}] from exchange [{}]...", getConfiguration().getBlobName(), exchange);
+        try {
+            client.upload(inputStream, -1,
+                          opts.getAccessCond(), opts.getRequestOpts(), opts.getOpContext());
+        } finally {
+            closeInputStreamIfNeeded(inputStream);
+        }
+    }
+    
+    private void uploadBlobBlocks(Exchange exchange) throws Exception {
+        Object object = exchange.getIn().getMandatoryBody();
+        
+        List<BlobBlock> blobBlocks = null;
+        if (object instanceof List) {
+            blobBlocks = (List<BlobBlock>)blobBlocks;
+        } else if (object instanceof BlobBlock) {
+            blobBlocks = Collections.singletonList((BlobBlock)object);
+        } 
+        if (blobBlocks == null || blobBlocks.isEmpty()) {
+            throw new IllegalArgumentException("Illegal storageBlocks payload");
+        }
+        
+        CloudBlockBlob client = BlobServiceUtil.createBlockBlobClient(getConfiguration(), true);
+        configureCloudBlobForWrite(client);
+        BlobServiceRequestOptions opts = BlobServiceUtil.getRequestOptions(exchange);
+        
+        LOG.trace("Putting a blob [{}] from blocks from exchange [{}]...", getConfiguration().getBlobName(), exchange);
+        List<BlockEntry> blockEntries = new LinkedList<BlockEntry>();
+        for (BlobBlock blobBlock : blobBlocks) {
+            blockEntries.add(blobBlock.getBlockEntry());
+            client.uploadBlock(blobBlock.getBlockEntry().getId(), blobBlock.getBlockStream(), -1, 
+                               opts.getAccessCond(), opts.getRequestOpts(), opts.getOpContext());
+        }
+        Boolean commitBlockListLater = exchange.getIn().getHeader(BlobServiceConstants.COMMIT_BLOCK_LIST_LATER, 
+                                                                  Boolean.class);
+        if (Boolean.TRUE != commitBlockListLater) {
+            client.commitBlockList(blockEntries, 
+                                   opts.getAccessCond(), opts.getRequestOpts(), opts.getOpContext());
+        }
+    }
+    
+    private void commitBlobBlockList(Exchange exchange) throws Exception {
+        Object object = exchange.getIn().getMandatoryBody();
+        
+        List<BlockEntry> blockEntries = null;
+        if (object instanceof List) {
+            blockEntries = (List<BlockEntry>)blockEntries;
+        } else if (object instanceof BlockEntry) {
+            blockEntries = Collections.singletonList((BlockEntry)object);
+        } 
+        if (blockEntries == null || blockEntries.isEmpty()) {
+            throw new IllegalArgumentException("Illegal commit block list payload");
+        }
+        
+        CloudBlockBlob client = BlobServiceUtil.createBlockBlobClient(getConfiguration(), true);
+        BlobServiceRequestOptions opts = BlobServiceUtil.getRequestOptions(exchange);
+        
+        LOG.trace("Putting a blob [{}] block list from exchange [{}]...", getConfiguration().getBlobName(), exchange);
+        client.commitBlockList(blockEntries, 
+                               opts.getAccessCond(), opts.getRequestOpts(), opts.getOpContext());
+    }
+    
+    private void getBlob(Exchange exchange) throws Exception {
+        BlobServiceUtil.getBlob(exchange, getConfiguration());
+    }
+    
+    private void deleteBlob(Exchange exchange) throws Exception {
+        switch (getConfiguration().getBlobType()) {
+        case blockblob:
+            deleteBlockBlob(exchange);
+            break;
+        case appendblob:
+            deleteAppendBlob(exchange);
+            break;
+        case pageblob:
+            deletePageBlob(exchange);
+            break;    
+        default:
+            throw new IllegalArgumentException("Unsupported blob type");
+        }
+    }
+    
+    private void getBlobBlockList(Exchange exchange) throws Exception {
+        CloudBlockBlob client = BlobServiceUtil.createBlockBlobClient(getConfiguration(), false);
+        BlobServiceRequestOptions opts = BlobServiceUtil.getRequestOptions(exchange);
+        LOG.trace("Getting the blob block list [{}] from exchange [{}]...", getConfiguration().getBlobName(), exchange);
+        BlockListingFilter filter = exchange.getIn().getBody(BlockListingFilter.class);
+        if (filter == null) {
+            filter = BlockListingFilter.COMMITTED;
+        }
+        List<BlockEntry> blockEntries =
+            client.downloadBlockList(filter, opts.getAccessCond(), opts.getRequestOpts(), opts.getOpContext());
+        ExchangeUtil.getMessageForResponse(exchange).setBody(blockEntries);
+    }
+    
+    private void deleteBlockBlob(Exchange exchange) throws Exception {
+        CloudBlockBlob client = BlobServiceUtil.createBlockBlobClient(getConfiguration(), true);
+        doDeleteBlock(client, exchange);
+    }
+    
+    private void createAppendBlob(Exchange exchange) throws Exception {
+        CloudAppendBlob client = BlobServiceUtil.createAppendBlobClient(getConfiguration(), true);
+        BlobServiceRequestOptions opts = BlobServiceUtil.getRequestOptions(exchange);
+        if (opts.getAccessCond() == null) {
+            // Default: do not reset the blob content if the blob already exists
+            opts.setAccessCond(AccessCondition.generateIfNotExistsCondition());
+        }
+        doCreateAppendBlob(client, opts, exchange);
+    }
+    
+    private void doCreateAppendBlob(CloudAppendBlob client, BlobServiceRequestOptions opts, Exchange exchange) 
+        throws Exception {
+        LOG.trace("Creating an append blob [{}] from exchange [{}]...", getConfiguration().getBlobName(), exchange);
+        try {
+            client.createOrReplace(opts.getAccessCond(), opts.getRequestOpts(), opts.getOpContext());
+        } catch (StorageException ex) {
+            if (ex.getHttpStatusCode() != 409) {
+                throw ex;
+            }
+        }
+        ExchangeUtil.getMessageForResponse(exchange)
+            .setHeader(BlobServiceConstants.APPEND_BLOCK_CREATED, Boolean.TRUE);
+    }
+
+    private void updateAppendBlob(Exchange exchange) throws Exception {
+        CloudAppendBlob client = BlobServiceUtil.createAppendBlobClient(getConfiguration(), true);
+        configureCloudBlobForWrite(client);
+        BlobServiceRequestOptions opts = BlobServiceUtil.getRequestOptions(exchange);
+        if (opts.getAccessCond() == null) {
+            // Default: do not reset the blob content if the blob already exists
+            opts.setAccessCond(AccessCondition.generateIfNotExistsCondition());
+        }
+        
+        Boolean appendBlobCreated = exchange.getIn().getHeader(BlobServiceConstants.APPEND_BLOCK_CREATED, 
+                                                                  Boolean.class);
+        if (Boolean.TRUE != appendBlobCreated) {
+            doCreateAppendBlob(client, opts, exchange);
+        }
+        
+        InputStream inputStream = getInputStreamFromExchange(exchange);
+        try {
+            client.appendBlock(inputStream, -1,
+                               opts.getAccessCond(), opts.getRequestOpts(), opts.getOpContext());
+        } finally {
+            closeInputStreamIfNeeded(inputStream);
+        }
+    }    
+    
+    private void deleteAppendBlob(Exchange exchange) throws Exception {
+        CloudAppendBlob client = BlobServiceUtil.createAppendBlobClient(getConfiguration(), true);
+        doDeleteBlock(client, exchange);
+    }
+    
+    
+    private void createPageBlob(Exchange exchange) throws Exception {
+        CloudPageBlob client = BlobServiceUtil.createPageBlobClient(getConfiguration(), true);
+        BlobServiceRequestOptions opts = BlobServiceUtil.getRequestOptions(exchange);
+        if (opts.getAccessCond() == null) {
+            // Default: do not reset the blob content if the blob already exists
+            opts.setAccessCond(AccessCondition.generateIfNotExistsCondition());
+        }
+        doCreatePageBlob(client, opts, exchange);
+    }
+    
+    private void doCreatePageBlob(CloudPageBlob client, BlobServiceRequestOptions opts, Exchange exchange) 
+        throws Exception {
+        LOG.trace("Creating a page blob [{}] from exchange [{}]...", getConfiguration().getBlobName(), exchange);
+        Long pageSize = getPageBlobSize(exchange);
+        try {
+            client.create(pageSize,
+                          opts.getAccessCond(), opts.getRequestOpts(), opts.getOpContext());
+        } catch (StorageException ex) {
+            if (ex.getHttpStatusCode() != 409) {
+                throw ex;
+            }
+        }
+        ExchangeUtil.getMessageForResponse(exchange)
+            .setHeader(BlobServiceConstants.PAGE_BLOCK_CREATED, Boolean.TRUE);
+        
+    }
+    
+    private void uploadPageBlob(Exchange exchange) throws Exception {
+        LOG.trace("Updating a page blob [{}] from exchange [{}]...", getConfiguration().getBlobName(), exchange);
+        
+        CloudPageBlob client = BlobServiceUtil.createPageBlobClient(getConfiguration(), true);
+        configureCloudBlobForWrite(client);
+        BlobServiceRequestOptions opts = BlobServiceUtil.getRequestOptions(exchange);
+        if (opts.getAccessCond() == null) {
+            // Default: do not reset the blob content if the blob already exists
+            opts.setAccessCond(AccessCondition.generateIfNotExistsCondition());
+        }
+        
+        Boolean pageBlobCreated = exchange.getIn().getHeader(BlobServiceConstants.PAGE_BLOCK_CREATED, 
+                                                                  Boolean.class);
+        if (Boolean.TRUE != pageBlobCreated) {
+            doCreatePageBlob(client, opts, exchange);
+        }
+        InputStream inputStream = getInputStreamFromExchange(exchange);
+        doUpdatePageBlob(client, inputStream, opts, exchange);
+        
+    }
+    
+    private void resizePageBlob(Exchange exchange) throws Exception {
+        LOG.trace("Resizing a page blob [{}] from exchange [{}]...", getConfiguration().getBlobName(), exchange);
+        
+        CloudPageBlob client = BlobServiceUtil.createPageBlobClient(getConfiguration(), true);
+        BlobServiceRequestOptions opts = BlobServiceUtil.getRequestOptions(exchange);
+        Long pageSize = getPageBlobSize(exchange);
+        client.resize(pageSize, opts.getAccessCond(), opts.getRequestOpts(), opts.getOpContext());
+    }
+    
+    private void clearPageBlob(Exchange exchange) throws Exception {
+        LOG.trace("Clearing a page blob [{}] from exchange [{}]...", getConfiguration().getBlobName(), exchange);
+                
+        CloudPageBlob client = BlobServiceUtil.createPageBlobClient(getConfiguration(), true);
+        BlobServiceRequestOptions opts = BlobServiceUtil.getRequestOptions(exchange);
+        
+        Long blobOffset = getConfiguration().getBlobOffset();
+        Long blobDataLength = getConfiguration().getDataLength();
+        PageRange range = exchange.getIn().getHeader(BlobServiceConstants.PAGE_BLOB_RANGE, PageRange.class);
+        if (range != null) {
+            blobOffset = range.getStartOffset();
+            blobDataLength = range.getEndOffset() - range.getStartOffset();
+        }
+        if (blobDataLength == null) {        
+            blobDataLength = blobOffset == 0 ? getPageBlobSize(exchange) : 512L; 
+        }
+        client.clearPages(blobOffset, blobDataLength,
+                          opts.getAccessCond(), opts.getRequestOpts(), opts.getOpContext());
+    }
+    
+    private void doUpdatePageBlob(CloudPageBlob client, InputStream is, BlobServiceRequestOptions opts, Exchange exchange) 
+        throws Exception {
+        
+        Long blobOffset = getConfiguration().getBlobOffset();
+        Long blobDataLength = getConfiguration().getDataLength();
+        PageRange range = exchange.getIn().getHeader(BlobServiceConstants.PAGE_BLOB_RANGE, PageRange.class);
+        if (range != null) {
+            blobOffset = range.getStartOffset();
+            blobDataLength = range.getEndOffset() - range.getStartOffset();
+        }
+        if (blobDataLength == null) {        
+            blobDataLength = (long)is.available(); 
+        }
+        try {
+            client.uploadPages(is, blobOffset, blobDataLength,
+                           opts.getAccessCond(), opts.getRequestOpts(), opts.getOpContext());
+        } finally {
+            closeInputStreamIfNeeded(is);    
+        }
+        
+    }
+    
+    private void getPageBlobRanges(Exchange exchange) throws Exception {
+        CloudPageBlob client = BlobServiceUtil.createPageBlobClient(getConfiguration(), false);
+        BlobServiceUtil.configureCloudBlobForRead(client, getConfiguration());
+        BlobServiceRequestOptions opts = BlobServiceUtil.getRequestOptions(exchange);
+        LOG.trace("Getting the page blob ranges [{}] from exchange [{}]...", getConfiguration().getBlobName(), exchange);
+        List<PageRange> ranges = 
+            client.downloadPageRanges(opts.getAccessCond(), opts.getRequestOpts(), opts.getOpContext());
+        ExchangeUtil.getMessageForResponse(exchange).setBody(ranges);
+    }
+    
+    private void deletePageBlob(Exchange exchange) throws Exception {
+        CloudPageBlob client = BlobServiceUtil.createPageBlobClient(getConfiguration(), true);
+        doDeleteBlock(client, exchange);
+    }
+    
+    private Long getPageBlobSize(Exchange exchange) {
+        Long pageSize = exchange.getIn().getHeader(BlobServiceConstants.PAGE_BLOB_SIZE, Long.class);
+        if (pageSize == null) {
+            pageSize = 512L;
+        }
+        return pageSize;
+    }
+
+    
+    private void doDeleteBlock(CloudBlob client, Exchange exchange) throws Exception {
+        LOG.trace("Deleting a blob [{}] from exchange [{}]...", getConfiguration().getBlobName(), exchange);
+        client.delete();
+    }
+
+    private String getCharsetName(Exchange exchange) {
+        String charset = exchange.getIn().getHeader(Exchange.CHARSET_NAME, String.class);
+        return charset == null ? "UTF-8" : charset;
+    }
+    
+    private void configureCloudBlobForWrite(CloudBlob client) {
+        if (getConfiguration().getStreamWriteSize() > 0) {
+            client.setStreamWriteSizeInBytes(getConfiguration().getStreamWriteSize());
+        }
+        if (getConfiguration().getBlobMetadata() != null) {
+            client.setMetadata(new HashMap<String, String>(getConfiguration().getBlobMetadata()));
+        }
+    }
+
+
+    private BlobServiceOperations determineOperation(Exchange exchange) {
+        BlobServiceOperations operation = exchange.getIn().getHeader(BlobServiceConstants.OPERATION, BlobServiceOperations.class);
+        if (operation == null) {
+            operation = getConfiguration().getOperation();
+        }
+        return operation;
+    }
+
+    protected BlobServiceConfiguration getConfiguration() {
+        return getEndpoint().getConfiguration();
+    }
+
+    @Override
+    public String toString() {
+        return "StorageBlobProducer[" + URISupport.sanitizeUri(getEndpoint().getEndpointUri()) + "]";
+    }
+
+    @Override
+    public BlobServiceEndpoint getEndpoint() {
+        return (BlobServiceEndpoint) super.getEndpoint();
+    }
+    
+    private InputStream getInputStreamFromExchange(Exchange exchange) throws Exception {
+        Object blobObject = exchange.getIn().getMandatoryBody();
+        InputStream inputStream = null;
+        if (blobObject instanceof String) {
+            String charset = getCharsetName(exchange);
+            inputStream = new ByteArrayInputStream(((String)blobObject).getBytes(charset));
+        } else if (blobObject instanceof InputStream) {
+            inputStream = (InputStream)blobObject;
+        } else if (blobObject instanceof File) {
+            inputStream = new FileInputStream((File)blobObject);
+        } else {
+            throw new IllegalArgumentException("Unsupported blob type:" + blobObject.getClass().getName());
+        }
+        return inputStream;
+    }
+    
+    private void closeInputStreamIfNeeded(InputStream inputStream) throws IOException {
+        if (getConfiguration().isCloseStreamAfterWrite()) {
+            inputStream.close();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceRequestOptions.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceRequestOptions.java b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceRequestOptions.java
new file mode 100644
index 0000000..6e0b237
--- /dev/null
+++ b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceRequestOptions.java
@@ -0,0 +1,45 @@
+/**
+ * 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.camel.component.azure.blob;
+
+import com.microsoft.azure.storage.AccessCondition;
+import com.microsoft.azure.storage.OperationContext;
+import com.microsoft.azure.storage.blob.BlobRequestOptions;
+
+public class BlobServiceRequestOptions {
+    private AccessCondition accessCond;
+    private BlobRequestOptions requestOpts;
+    private OperationContext opContext;
+    public AccessCondition getAccessCond() {
+        return accessCond;
+    }
+    public void setAccessCond(AccessCondition accessCond) {
+        this.accessCond = accessCond;
+    }
+    public BlobRequestOptions getRequestOpts() {
+        return requestOpts;
+    }
+    public void setRequestOpts(BlobRequestOptions requestOpts) {
+        this.requestOpts = requestOpts;
+    }
+    public OperationContext getOpContext() {
+        return opContext;
+    }
+    public void setOpContext(OperationContext opContext) {
+        this.opContext = opContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceUtil.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceUtil.java b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceUtil.java
new file mode 100644
index 0000000..274bffa
--- /dev/null
+++ b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobServiceUtil.java
@@ -0,0 +1,231 @@
+/**
+ * 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.camel.component.azure.blob;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.net.URI;
+
+import com.microsoft.azure.storage.AccessCondition;
+import com.microsoft.azure.storage.OperationContext;
+import com.microsoft.azure.storage.StorageCredentials;
+import com.microsoft.azure.storage.blob.BlobRequestOptions;
+import com.microsoft.azure.storage.blob.CloudAppendBlob;
+import com.microsoft.azure.storage.blob.CloudBlob;
+import com.microsoft.azure.storage.blob.CloudBlobContainer;
+import com.microsoft.azure.storage.blob.CloudBlockBlob;
+import com.microsoft.azure.storage.blob.CloudPageBlob;
+import com.microsoft.azure.storage.blob.PageRange;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.azure.common.ExchangeUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class BlobServiceUtil {
+    private static final Logger LOG = LoggerFactory.getLogger(BlobServiceUtil.class);
+    
+    private BlobServiceUtil() {
+    }
+    public static void getBlob(Exchange exchange, BlobServiceConfiguration cfg) 
+        throws Exception {
+        switch (cfg.getBlobType()) {
+        case blockblob:
+            getBlockBlob(exchange, cfg);
+            break;
+        case appendblob:
+            getAppendBlob(exchange, cfg);
+            break;
+        case pageblob:
+            getPageBlob(exchange, cfg);
+            break;    
+        default:
+            throw new IllegalArgumentException("Unsupported blob type");
+        }
+    }
+    
+    private static void getBlockBlob(Exchange exchange, BlobServiceConfiguration cfg) 
+        throws Exception {
+        CloudBlockBlob client = createBlockBlobClient(cfg, false);
+        doGetBlob(client, exchange, cfg);
+    }
+    private static void getAppendBlob(Exchange exchange, BlobServiceConfiguration cfg) throws Exception {
+        CloudAppendBlob client = createAppendBlobClient(cfg, false);
+        doGetBlob(client, exchange, cfg);
+    }
+    private static void getPageBlob(Exchange exchange, BlobServiceConfiguration cfg) throws Exception {
+        CloudPageBlob client = createPageBlobClient(cfg, false);
+        doGetBlob(client, exchange, cfg);
+    }
+    
+    private static void doGetBlob(CloudBlob client, Exchange exchange, BlobServiceConfiguration cfg) 
+        throws Exception {
+        BlobServiceUtil.configureCloudBlobForRead(client, cfg);
+        BlobServiceRequestOptions opts = getRequestOptions(exchange);
+        LOG.trace("Getting a blob [{}] from exchange [{}]...", cfg.getBlobName(), exchange);
+        Long blobOffset = cfg.getBlobOffset();
+        Long blobDataLength = cfg.getDataLength();
+        if (client instanceof CloudPageBlob) {
+            PageRange range = exchange.getIn().getHeader(BlobServiceConstants.PAGE_BLOB_RANGE, PageRange.class);
+            if (range != null) {
+                blobOffset = range.getStartOffset();
+                blobDataLength = range.getEndOffset() - range.getStartOffset();
+            }
+        }
+        OutputStream os = exchange.getIn().getBody(OutputStream.class);
+        if (os == null) {
+            String fileDir = cfg.getFileDir();
+            if (fileDir != null) {
+                // Should the range if it is set be reflected in the file name ?
+                String name = cfg.getBlobName();
+                File file = new File(fileDir, name + ".blob");
+                ExchangeUtil.getMessageForResponse(exchange).setBody(file);
+                os = new FileOutputStream(file);  
+            }
+        }
+        if (os == null) {
+            throw new IllegalArgumentException("OutputStream is not available");
+        }
+        try {
+            client.downloadRange(blobOffset, blobDataLength, os,
+                                 opts.getAccessCond(), opts.getRequestOpts(), opts.getOpContext());
+        } finally {
+            if (cfg.isCloseStreamAfterRead()) {
+                os.close();
+            }
+        }
+    }
+    public static CloudBlobContainer createBlobContainerClient(BlobServiceConfiguration cfg) 
+        throws Exception {
+        URI uri = prepareStorageBlobUri(cfg, false);
+        StorageCredentials creds = getAccountCredentials(cfg, false);
+        return new CloudBlobContainer(uri, creds);
+    }
+    public static CloudBlockBlob createBlockBlobClient(BlobServiceConfiguration cfg, boolean isWrite) 
+        throws Exception {
+        CloudBlockBlob client = (CloudBlockBlob)getConfiguredClient(cfg, BlobType.blockblob, isWrite);
+        if (client == null) {
+            URI uri = prepareStorageBlobUri(cfg);
+            StorageCredentials creds = getAccountCredentials(cfg, isWrite);
+            client = new CloudBlockBlob(uri, creds);
+        }
+        return client;
+    }
+    public static CloudAppendBlob createAppendBlobClient(BlobServiceConfiguration cfg, boolean isWrite)
+        throws Exception {
+        CloudAppendBlob client = (CloudAppendBlob)getConfiguredClient(cfg, BlobType.appendblob, isWrite);
+        if (client == null) {
+            URI uri = prepareStorageBlobUri(cfg);
+            StorageCredentials creds = getAccountCredentials(cfg, isWrite);
+            client = new CloudAppendBlob(uri, creds);
+        }
+        return client;
+    }
+    
+    public static CloudPageBlob createPageBlobClient(BlobServiceConfiguration cfg, boolean isWrite)
+        throws Exception {
+        CloudPageBlob client = (CloudPageBlob)getConfiguredClient(cfg, BlobType.pageblob, isWrite);
+        if (client == null) {
+            URI uri = prepareStorageBlobUri(cfg);
+            StorageCredentials creds = getAccountCredentials(cfg, isWrite);
+            client = new CloudPageBlob(uri, creds);
+        }
+        return client;
+    }
+    
+    public static CloudBlob getConfiguredClient(BlobServiceConfiguration cfg,
+                                                BlobType blobType,
+                                                boolean isWrite) {
+        CloudBlob client = cfg.getAzureBlobClient();
+        if (client != null) {
+            Class<?> expectedCls = null;
+            if (blobType == BlobType.blockblob) {
+                expectedCls = CloudBlockBlob.class; 
+            } else if (blobType == BlobType.appendblob) {
+                expectedCls = CloudAppendBlob.class; 
+            } else if (blobType == BlobType.pageblob) {
+                expectedCls = CloudPageBlob.class; 
+            }
+            if (client.getClass() != expectedCls) {
+                throw new IllegalArgumentException("Invalid Blob Client Type");
+            }
+            if (!client.getUri().equals(prepareStorageBlobUri(cfg))) {
+                throw new IllegalArgumentException("Invalid Client Uri");
+            }
+            if (client.getServiceClient().getCredentials() == null && (isWrite || !cfg.isPublicForRead())) {
+                throw new IllegalArgumentException("Storage credentials must be specified");
+            }
+        }
+        return client;
+    }
+    
+    public static StorageCredentials getAccountCredentials(BlobServiceConfiguration cfg,
+                                                             boolean isWrite) {
+        if (cfg.getCredentials() == null && (isWrite || !cfg.isPublicForRead())) {
+            throw new IllegalArgumentException("Storage credentials must be specified");
+        }
+        return cfg.getCredentials();
+    }
+
+    public static void configureCloudBlobForRead(CloudBlob client, BlobServiceConfiguration cfg) {
+        if (cfg.getStreamReadSize() > 0) {
+            client.setStreamMinimumReadSizeInBytes(cfg.getStreamReadSize());
+        }
+    }
+    
+    public static URI prepareStorageBlobUri(BlobServiceConfiguration cfg) {
+        return prepareStorageBlobUri(cfg, true);
+    }
+    
+    public static URI prepareStorageBlobUri(BlobServiceConfiguration cfg, boolean blobNameRequired) {
+        if (blobNameRequired && cfg.getBlobName() == null) {
+            throw new IllegalArgumentException("Blob name must be specified");
+        }
+        
+        StringBuilder uriBuilder = new StringBuilder();
+        uriBuilder.append("https://")
+                  .append(cfg.getAccountName())
+                  .append(BlobServiceConstants.SERVICE_URI_SEGMENT)
+                  .append("/")
+                  .append(cfg.getContainerName());
+        if (cfg.getBlobName() != null) {
+            uriBuilder.append("/")
+                      .append(cfg.getBlobName());
+        }
+        return URI.create(uriBuilder.toString());
+    }
+
+    
+    public static BlobServiceRequestOptions getRequestOptions(Exchange exchange) {
+        BlobServiceRequestOptions opts = exchange.getIn().getBody(BlobServiceRequestOptions.class);
+        if (opts != null) {
+            return opts;    
+        } else {
+            opts = new BlobServiceRequestOptions();
+        }
+        AccessCondition accessCond = 
+            exchange.getIn().getHeader(BlobServiceConstants.ACCESS_CONDITION, AccessCondition.class);
+        BlobRequestOptions requestOpts = 
+            exchange.getIn().getHeader(BlobServiceConstants.BLOB_REQUEST_OPTIONS, BlobRequestOptions.class);
+        OperationContext opContext = 
+            exchange.getIn().getHeader(BlobServiceConstants.OPERATION_CONTEXT, OperationContext.class);
+        opts.setAccessCond(accessCond);
+        opts.setOpContext(opContext);
+        opts.setRequestOpts(requestOpts);
+        return opts;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobType.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobType.java b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobType.java
new file mode 100644
index 0000000..ee2f5ed
--- /dev/null
+++ b/components/camel-azure/src/main/java/org/apache/camel/component/azure/blob/BlobType.java
@@ -0,0 +1,30 @@
+/**
+ * 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.camel.component.azure.blob;
+
+/**
+ * Blob Type
+ */
+// The lower case naming is done to make component URI look better
+// when a type needs to be set and make it consistent with the values
+// used by Azure SDK BlobType parse implementation which is currently not
+// directly accessible
+public enum BlobType {
+    blockblob,
+    appendblob,
+    pageblob
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/java/org/apache/camel/component/azure/common/AbstractConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/java/org/apache/camel/component/azure/common/AbstractConfiguration.java b/components/camel-azure/src/main/java/org/apache/camel/component/azure/common/AbstractConfiguration.java
new file mode 100644
index 0000000..c230044
--- /dev/null
+++ b/components/camel-azure/src/main/java/org/apache/camel/component/azure/common/AbstractConfiguration.java
@@ -0,0 +1,52 @@
+/**
+ * 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.camel.component.azure.common;
+
+import com.microsoft.azure.storage.StorageCredentials;
+import org.apache.camel.spi.UriParam;
+
+public abstract class AbstractConfiguration implements Cloneable {
+
+    @UriParam
+    private StorageCredentials credentials;
+    
+    private String accountName;
+    
+    public String getAccountName() {
+        return accountName;
+    }
+
+    /**
+     * Set the Azure account name
+     */
+    public void setAccountName(String accountName) {
+        this.accountName = accountName;
+    }
+
+    
+    public StorageCredentials getCredentials() {
+        return credentials;
+    }
+
+    /**
+     * Set the storage credentials, required in most cases
+     */
+    public void setCredentials(StorageCredentials credentials) {
+        this.credentials = credentials;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/java/org/apache/camel/component/azure/common/ExchangeUtil.java
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/java/org/apache/camel/component/azure/common/ExchangeUtil.java b/components/camel-azure/src/main/java/org/apache/camel/component/azure/common/ExchangeUtil.java
new file mode 100644
index 0000000..5bc979e
--- /dev/null
+++ b/components/camel-azure/src/main/java/org/apache/camel/component/azure/common/ExchangeUtil.java
@@ -0,0 +1,35 @@
+/**
+ * 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.camel.component.azure.common;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+
+public final class ExchangeUtil {
+
+    private ExchangeUtil() {
+    }
+
+    public static Message getMessageForResponse(final Exchange exchange) {
+        if (exchange.getPattern().isOutCapable()) {
+            Message out = exchange.getOut();
+            out.copyFrom(exchange.getIn());
+            return out;
+        }
+        return exchange.getIn();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/resources/META-INF/LICENSE.txt
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/resources/META-INF/LICENSE.txt b/components/camel-azure/src/main/resources/META-INF/LICENSE.txt
new file mode 100755
index 0000000..6b0b127
--- /dev/null
+++ b/components/camel-azure/src/main/resources/META-INF/LICENSE.txt
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+

http://git-wip-us.apache.org/repos/asf/camel/blob/a3b9b0f3/components/camel-azure/src/main/resources/META-INF/NOTICE.txt
----------------------------------------------------------------------
diff --git a/components/camel-azure/src/main/resources/META-INF/NOTICE.txt b/components/camel-azure/src/main/resources/META-INF/NOTICE.txt
new file mode 100755
index 0000000..2e215bf
--- /dev/null
+++ b/components/camel-azure/src/main/resources/META-INF/NOTICE.txt
@@ -0,0 +1,11 @@
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Apache Camel distribution.                    ==
+   =========================================================================
+
+   This product includes software developed by
+   The Apache Software Foundation (http://www.apache.org/).
+
+   Please read the different LICENSE files present in the licenses directory of
+   this distribution.