You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2017/03/02 11:30:55 UTC

[18/50] [abbrv] ignite git commit: IGNITE-4685 Propagate platform plugin configuration to Java

IGNITE-4685 Propagate platform plugin configuration to Java

This closes #1524


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

Branch: refs/heads/ignite-4565-ddl
Commit: bd988b71d995cc509349b278b52d60c90ccaba44
Parents: 80825f7
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Wed Feb 15 15:44:25 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Wed Feb 15 15:44:25 2017 +0300

----------------------------------------------------------------------
 .../utils/PlatformConfigurationUtils.java       | 68 +++++++++++++++++++-
 .../PlatformPluginConfigurationClosure.java     | 30 +++++++++
 ...atformPluginConfigurationClosureFactory.java | 37 +++++++++++
 ...rm.PlatformPluginConfigurationClosureFactory |  1 +
 .../plugin/PlatformTestPluginConfiguration.java | 63 ++++++++++++++++++
 ...rmTestPluginConfigurationClosureFactory.java | 61 ++++++++++++++++++
 .../plugin/PlatformTestPluginExtension.java     |  2 +-
 .../plugin/PlatformTestPluginProvider.java      |  8 +--
 .../plugin/PlatformTestPluginTarget.java        | 30 +++++++++
 .../Plugin/PluginTest.cs                        | 47 ++++++++++++--
 .../Plugin/TestIgnitePluginConfiguration.cs     | 20 ++++++
 .../Apache.Ignite.Core/IgniteConfiguration.cs   | 28 ++++++++
 .../IgniteConfigurationSection.xsd              |  5 ++
 .../Common/IgniteConfigurationXmlSerializer.cs  |  7 ++
 .../Plugin/IPluginConfiguration.cs              | 15 ++++-
 15 files changed, 406 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/bd988b71/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
index ea8f361..f295ff5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.processors.platform.utils;
 
+import org.apache.ignite.IgniteException;
 import org.apache.ignite.binary.BinaryArrayIdentityResolver;
 import org.apache.ignite.binary.BinaryFieldIdentityResolver;
 import org.apache.ignite.binary.BinaryIdentityResolver;
@@ -44,12 +45,19 @@ import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.configuration.NearCacheConfiguration;
 import org.apache.ignite.configuration.TransactionConfiguration;
-import org.apache.ignite.internal.binary.*;
+import org.apache.ignite.internal.binary.BinaryRawReaderEx;
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
 import org.apache.ignite.internal.processors.platform.cache.affinity.PlatformAffinityFunction;
 import org.apache.ignite.internal.processors.platform.cache.expiry.PlatformExpiryPolicyFactory;
 import org.apache.ignite.internal.processors.platform.plugin.cache.PlatformCachePluginConfiguration;
-import org.apache.ignite.platform.dotnet.*;
+import org.apache.ignite.platform.dotnet.PlatformDotNetAffinityFunction;
+import org.apache.ignite.platform.dotnet.PlatformDotNetBinaryConfiguration;
+import org.apache.ignite.platform.dotnet.PlatformDotNetBinaryTypeConfiguration;
+import org.apache.ignite.platform.dotnet.PlatformDotNetCacheStoreFactoryNative;
+import org.apache.ignite.platform.dotnet.PlatformDotNetConfiguration;
 import org.apache.ignite.plugin.CachePluginConfiguration;
+import org.apache.ignite.plugin.platform.PlatformPluginConfigurationClosure;
+import org.apache.ignite.plugin.platform.PlatformPluginConfigurationClosureFactory;
 import org.apache.ignite.spi.communication.CommunicationSpi;
 import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
 import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpiMBean;
@@ -68,14 +76,17 @@ import javax.cache.configuration.Factory;
 import javax.cache.expiry.ExpiryPolicy;
 import java.lang.management.ManagementFactory;
 import java.net.InetSocketAddress;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.ServiceLoader;
 import java.util.Set;
-import java.util.HashSet;
 
 /**
  * Configuration utils.
@@ -647,6 +658,8 @@ public class PlatformConfigurationUtils {
             default:
                 assert swapType == SWAP_TYP_NONE;
         }
+
+        readPluginConfiguration(cfg, in);
     }
 
     /**
@@ -1263,6 +1276,55 @@ public class PlatformConfigurationUtils {
     }
 
     /**
+     * Reads the plugin configuration.
+     *
+     * @param cfg Ignite configuration to update.
+     * @param in Reader.
+     */
+    private static void readPluginConfiguration(IgniteConfiguration cfg, BinaryRawReader in) {
+        int cnt = in.readInt();
+
+        if (cnt == 0)
+            return;
+
+        for (int i = 0; i < cnt; i++) {
+            int plugCfgFactoryId = in.readInt();
+
+            PlatformPluginConfigurationClosure plugCfg = pluginConfiguration(plugCfgFactoryId);
+
+            plugCfg.apply(cfg, in);
+        }
+    }
+
+    /**
+     * Create PlatformPluginConfigurationClosure for the given factory ID.
+     *
+     * @param factoryId Factory ID.
+     * @return PlatformPluginConfigurationClosure.
+     */
+    private static PlatformPluginConfigurationClosure pluginConfiguration(final int factoryId) {
+        PlatformPluginConfigurationClosureFactory factory = AccessController.doPrivileged(
+                new PrivilegedAction<PlatformPluginConfigurationClosureFactory>() {
+                    @Override public PlatformPluginConfigurationClosureFactory run() {
+                        for (PlatformPluginConfigurationClosureFactory factory :
+                                ServiceLoader.load(PlatformPluginConfigurationClosureFactory.class)) {
+                            if (factory.id() == factoryId)
+                                return factory;
+                        }
+
+                        return null;
+                    }
+                });
+
+        if (factory == null) {
+            throw new IgniteException("PlatformPluginConfigurationClosureFactory is not found " +
+                    "(did you put into the classpath?): " + factoryId);
+        }
+
+        return factory.create();
+    }
+
+    /**
      * Private constructor.
      */
     private PlatformConfigurationUtils() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd988b71/modules/core/src/main/java/org/apache/ignite/plugin/platform/PlatformPluginConfigurationClosure.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/plugin/platform/PlatformPluginConfigurationClosure.java b/modules/core/src/main/java/org/apache/ignite/plugin/platform/PlatformPluginConfigurationClosure.java
new file mode 100644
index 0000000..33770d9
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/plugin/platform/PlatformPluginConfigurationClosure.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.ignite.plugin.platform;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.lang.IgniteBiInClosure;
+
+/**
+ * Platform configuration handler:
+ * updates plugin configuration using data sent from platform code.
+ */
+public interface PlatformPluginConfigurationClosure extends IgniteBiInClosure<IgniteConfiguration, BinaryRawReader> {
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd988b71/modules/core/src/main/java/org/apache/ignite/plugin/platform/PlatformPluginConfigurationClosureFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/plugin/platform/PlatformPluginConfigurationClosureFactory.java b/modules/core/src/main/java/org/apache/ignite/plugin/platform/PlatformPluginConfigurationClosureFactory.java
new file mode 100644
index 0000000..7ec5adc
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/plugin/platform/PlatformPluginConfigurationClosureFactory.java
@@ -0,0 +1,37 @@
+/*
+ * 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.ignite.plugin.platform;
+
+/**
+ * Factory for @{@link PlatformPluginConfigurationClosure} with a unique id.
+ */
+public interface PlatformPluginConfigurationClosureFactory {
+    /**
+     * Gets the factory id.
+     *
+     * @return Factory id.
+     */
+    int id();
+
+    /**
+     * Creates configuration instance.
+     *
+     * @return Configuration instance.
+     */
+    PlatformPluginConfigurationClosure create();
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd988b71/modules/core/src/test/java/META-INF/services/org.apache.ignite.plugin.platform.PlatformPluginConfigurationClosureFactory
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/META-INF/services/org.apache.ignite.plugin.platform.PlatformPluginConfigurationClosureFactory b/modules/core/src/test/java/META-INF/services/org.apache.ignite.plugin.platform.PlatformPluginConfigurationClosureFactory
new file mode 100644
index 0000000..ef79fbe
--- /dev/null
+++ b/modules/core/src/test/java/META-INF/services/org.apache.ignite.plugin.platform.PlatformPluginConfigurationClosureFactory
@@ -0,0 +1 @@
+org.apache.ignite.platform.plugin.PlatformTestPluginConfigurationClosureFactory
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd988b71/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginConfiguration.java b/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginConfiguration.java
new file mode 100644
index 0000000..b7fb36d
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginConfiguration.java
@@ -0,0 +1,63 @@
+/*
+ * 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.ignite.platform.plugin;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.plugin.PluginConfiguration;
+
+/**
+ * Test plugin configuration.
+ */
+public class PlatformTestPluginConfiguration implements PluginConfiguration {
+    /** */
+    private String pluginProperty;
+
+    /**
+     * Initializes a new instance of PlatformTestPluginConfiguration.
+     */
+    public PlatformTestPluginConfiguration() {
+        // No-op.
+    }
+
+    /**
+     * Initializes a new instance of PlatformTestPluginConfiguration.
+     *
+     * @param reader Reader.
+     */
+    public PlatformTestPluginConfiguration(BinaryRawReader reader) {
+        pluginProperty = reader.readString();
+    }
+
+    /**
+     * Gets the plugin property.
+     *
+     * @return Plugin property.
+     */
+    public String pluginProperty() {
+        return pluginProperty;
+    }
+
+    /**
+     * Sets the plugin property.
+     *
+     * @param pluginProperty Value.
+     */
+    public void setPluginProperty(String pluginProperty) {
+        this.pluginProperty = pluginProperty;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd988b71/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginConfigurationClosureFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginConfigurationClosureFactory.java b/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginConfigurationClosureFactory.java
new file mode 100644
index 0000000..e851384
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginConfigurationClosureFactory.java
@@ -0,0 +1,61 @@
+/*
+ * 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.ignite.platform.plugin;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.plugin.PluginConfiguration;
+import org.apache.ignite.plugin.platform.PlatformPluginConfigurationClosure;
+import org.apache.ignite.plugin.platform.PlatformPluginConfigurationClosureFactory;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ * Test config factory.
+ */
+public class PlatformTestPluginConfigurationClosureFactory implements PlatformPluginConfigurationClosureFactory,
+        PlatformPluginConfigurationClosure {
+    /** {@inheritDoc} */
+    @Override public int id() {
+        return 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public PlatformPluginConfigurationClosure create() {
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void apply(@NotNull IgniteConfiguration cfg, @NotNull BinaryRawReader reader) {
+        ArrayList<PluginConfiguration> cfgs = new ArrayList<>();
+
+        if (cfg.getPluginConfigurations() != null) {
+            Collections.addAll(cfgs, cfg.getPluginConfigurations());
+        }
+
+        PlatformTestPluginConfiguration plugCfg = new PlatformTestPluginConfiguration();
+
+        plugCfg.setPluginProperty(reader.readString());
+
+        cfgs.add(plugCfg);
+
+        cfg.setPluginConfigurations(cfgs.toArray(new PluginConfiguration[cfgs.size()]));
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd988b71/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginExtension.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginExtension.java b/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginExtension.java
index 18d1595..597e9bc 100644
--- a/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginExtension.java
+++ b/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginExtension.java
@@ -46,6 +46,6 @@ public class PlatformTestPluginExtension implements PlatformPluginExtension {
 
     /** {@inheritDoc} */
     @Override public PlatformTarget createTarget() {
-        return new PlatformTestPluginTarget(ignite.context().platform().context(), "");
+        return new PlatformTestPluginTarget(ignite.context().platform().context(), null);
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd988b71/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginProvider.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginProvider.java b/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginProvider.java
index 298fa20..c8de1a3 100644
--- a/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginProvider.java
+++ b/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginProvider.java
@@ -30,7 +30,7 @@ import java.util.UUID;
 /**
  * Plugin provider for platform tests.
  */
-public class PlatformTestPluginProvider implements PluginProvider {
+public class PlatformTestPluginProvider implements PluginProvider<PlatformTestPluginConfiguration> {
     /** {@inheritDoc} */
     @Override public String name() {
         return "TestPlatformPlugin";
@@ -86,12 +86,12 @@ public class PlatformTestPluginProvider implements PluginProvider {
     }
 
     /** {@inheritDoc} */
-    @Nullable @Override public Object createComponent(PluginContext ctx, Class cls) {
+    @Nullable @Override public <T> T createComponent(PluginContext ctx, Class<T> cls) {
         return null;
     }
 
     /** {@inheritDoc} */
-    @Override public IgnitePlugin plugin() {
-        return new PlatformTestPlugin();
+    @Override public <T extends IgnitePlugin> T plugin() {
+        return (T)new PlatformTestPlugin();
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd988b71/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginTarget.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginTarget.java b/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginTarget.java
index 42d8739..b893395 100644
--- a/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginTarget.java
+++ b/modules/core/src/test/java/org/apache/ignite/platform/plugin/PlatformTestPluginTarget.java
@@ -18,11 +18,13 @@
 package org.apache.ignite.platform.plugin;
 
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.binary.BinaryRawReaderEx;
 import org.apache.ignite.internal.binary.BinaryRawWriterEx;
 import org.apache.ignite.internal.processors.platform.PlatformAbstractTarget;
 import org.apache.ignite.internal.processors.platform.PlatformContext;
 import org.apache.ignite.internal.processors.platform.PlatformTarget;
+import org.apache.ignite.plugin.PluginConfiguration;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -40,6 +42,15 @@ class PlatformTestPluginTarget extends PlatformAbstractTarget {
     PlatformTestPluginTarget(PlatformContext platformCtx, String name) {
         super(platformCtx);
 
+        if (name == null) {
+            // Initialize from configuration.
+            PlatformTestPluginConfiguration cfg = configuration(platformCtx.kernalContext().config());
+
+            assert cfg != null;
+
+            name = cfg.pluginProperty();
+        }
+
         this.name = name;
     }
 
@@ -87,4 +98,23 @@ class PlatformTestPluginTarget extends PlatformAbstractTarget {
     @Override public PlatformTarget processOutObject(int type) throws IgniteCheckedException {
         return new PlatformTestPluginTarget(platformCtx, name);
     }
+
+    /**
+     * Gets the plugin config.
+     *
+     * @param igniteCfg Ignite config.
+     *
+     * @return Plugin config.
+     */
+    private PlatformTestPluginConfiguration configuration(IgniteConfiguration igniteCfg) {
+        if (igniteCfg.getPluginConfigurations() != null) {
+            for (PluginConfiguration pluginCfg : igniteCfg.getPluginConfigurations()) {
+                if (pluginCfg instanceof PlatformTestPluginConfiguration) {
+                    return (PlatformTestPluginConfiguration) pluginCfg;
+                }
+            }
+        }
+
+        return null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd988b71/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Plugin/PluginTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Plugin/PluginTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Plugin/PluginTest.cs
index 25efce0..6fca03a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Plugin/PluginTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Plugin/PluginTest.cs
@@ -20,6 +20,7 @@ namespace Apache.Ignite.Core.Tests.Plugin
     using System;
     using System.Collections.Generic;
     using System.IO;
+    using Apache.Ignite.Core.Binary;
     using Apache.Ignite.Core.Common;
     using Apache.Ignite.Core.Interop;
     using Apache.Ignite.Core.Plugin;
@@ -72,7 +73,7 @@ namespace Apache.Ignite.Core.Tests.Plugin
                 var extension = plugin.Provider.Context.GetExtension(0);
                 Assert.IsNotNull(extension);
 
-                CheckPluginTarget(extension);
+                CheckPluginTarget(extension, "barbaz");
             }
 
             Assert.AreEqual(true, plugin.Provider.Stopped);
@@ -82,10 +83,10 @@ namespace Apache.Ignite.Core.Tests.Plugin
         /// <summary>
         /// Checks the plugin target operations.
         /// </summary>
-        private static void CheckPluginTarget(IPlatformTarget target)
+        private static void CheckPluginTarget(IPlatformTarget target, string expectedName)
         {
             // Returns name.
-            Assert.AreEqual(string.Empty, target.OutStream(1, r => r.ReadString()));
+            Assert.AreEqual(expectedName, target.OutStream(1, r => r.ReadString()));
 
             // Increments arg by one.
             Assert.AreEqual(3, target.InLongOutLong(1, 2));
@@ -164,13 +165,29 @@ namespace Apache.Ignite.Core.Tests.Plugin
 
         private class NoAttributeConfig : IPluginConfiguration
         {
-            // No-op.
+            public int? PluginConfigurationClosureFactoryId
+            {
+                get { return null; }
+            }
+
+            public void WriteBinary(IBinaryRawWriter writer)
+            {
+                throw new NotImplementedException();
+            }
         }
 
         [PluginProviderType(typeof(EmptyNamePluginProvider))]
         private class EmptyNameConfig : IPluginConfiguration
         {
-            // No-op.
+            public int? PluginConfigurationClosureFactoryId
+            {
+                get { return null; }
+            }
+
+            public void WriteBinary(IBinaryRawWriter writer)
+            {
+                throw new NotImplementedException();
+            }
         }
 
         private class EmptyNamePluginProvider : IPluginProvider<EmptyNameConfig>
@@ -187,7 +204,15 @@ namespace Apache.Ignite.Core.Tests.Plugin
         [PluginProviderType(typeof(ExceptionPluginProvider))]
         private class ExceptionConfig : IPluginConfiguration
         {
-            // No-op.
+            public int? PluginConfigurationClosureFactoryId
+            {
+                get { return null; }
+            }
+
+            public void WriteBinary(IBinaryRawWriter writer)
+            {
+                throw new NotImplementedException();
+            }
         }
 
         private class ExceptionPluginProvider : IPluginProvider<ExceptionConfig>
@@ -221,7 +246,15 @@ namespace Apache.Ignite.Core.Tests.Plugin
         [PluginProviderType(typeof(NormalPluginProvider))]
         private class NormalConfig : IPluginConfiguration
         {
-            // No-op.
+            public int? PluginConfigurationClosureFactoryId
+            {
+                get { return null; }
+            }
+
+            public void WriteBinary(IBinaryRawWriter writer)
+            {
+                throw new NotImplementedException();
+            }
         }
 
         private class NormalPluginProvider : IPluginProvider<NormalConfig>

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd988b71/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Plugin/TestIgnitePluginConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Plugin/TestIgnitePluginConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Plugin/TestIgnitePluginConfiguration.cs
index 4856ccb..fdf4a73 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Plugin/TestIgnitePluginConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Plugin/TestIgnitePluginConfiguration.cs
@@ -17,6 +17,7 @@
 
  namespace Apache.Ignite.Core.Tests.Plugin
 {
+    using Apache.Ignite.Core.Binary;
     using Apache.Ignite.Core.Plugin;
 
     /// <summary>
@@ -29,5 +30,24 @@
         /// Custom plugin property.
         /// </summary>
         public string PluginProperty { get; set; }
+
+        /** <inheritdoc /> */
+        public int? PluginConfigurationClosureFactoryId
+        {
+            get { return 0; }
+            // ReSharper disable once ValueParameterNotUsed
+            // ReSharper disable once UnusedMember.Global
+            set
+            {
+                // No-op.
+                // Needed to test configuration serialization.
+            }
+        }
+
+        /** <inheritdoc /> */
+        public void WriteBinary(IBinaryRawWriter writer)
+        {
+            writer.WriteString(PluginProperty);
+        }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd988b71/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
index 0676608..563eea0 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
@@ -336,6 +336,34 @@
 
             // Swap space
             SwapSpaceSerializer.Write(writer, SwapSpaceSpi);
+
+            // Plugins
+            if (PluginConfigurations != null)
+            {
+                var pos = writer.Stream.Position;
+
+                writer.WriteInt(0); // reserve count
+
+                var cnt = 0;
+
+                foreach (var cfg in PluginConfigurations)
+                {
+                    if (cfg.PluginConfigurationClosureFactoryId != null)
+                    {
+                        writer.WriteInt(cfg.PluginConfigurationClosureFactoryId.Value);
+
+                        cfg.WriteBinary(writer);
+
+                        cnt++;
+                    }
+                }
+
+                writer.Stream.WriteInt(pos, cnt);
+            }
+            else
+            {
+                writer.WriteInt(0);
+            }
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd988b71/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
index 2962951..5a49790 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
@@ -1217,6 +1217,11 @@
                                             <xs:documentation>Assembly-qualified type name.</xs:documentation>
                                         </xs:annotation>
                                     </xs:attribute>
+                                    <xs:attribute name="pluginConfigurationClosureFactoryId" type="xs:int">
+                                        <xs:annotation>
+                                            <xs:documentation>Id to locate PlatformPluginConfigurationClosureFactory on Java side.</xs:documentation>
+                                        </xs:annotation>
+                                    </xs:attribute>
                                 </xs:complexType>
                             </xs:element>
                         </xs:sequence>

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd988b71/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs
index 7ca654f..a87ff18 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs
@@ -344,6 +344,13 @@ namespace Apache.Ignite.Core.Impl.Common
             var type = target.GetType();
             var property = GetPropertyOrThrow(propName, propVal, type);
 
+            if (!property.CanWrite)
+            {
+                throw new ConfigurationErrorsException(string.Format(
+                        "Invalid IgniteConfiguration attribute '{0}={1}', property '{2}.{3}' is not writeable",
+                        propName, propVal, type, property.Name));
+            }
+
             var converter = GetConverter(property, property.PropertyType);
 
             var convertedVal = converter.ConvertFromInvariantString(propVal);

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd988b71/modules/platforms/dotnet/Apache.Ignite.Core/Plugin/IPluginConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Plugin/IPluginConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Plugin/IPluginConfiguration.cs
index 09f3f4a..4d594f4 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Plugin/IPluginConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Plugin/IPluginConfiguration.cs
@@ -18,6 +18,7 @@
 namespace Apache.Ignite.Core.Plugin
 {
     using System.Diagnostics.CodeAnalysis;
+    using Apache.Ignite.Core.Binary;
 
     /// <summary>
     /// Plugin configuration marker interface.
@@ -43,6 +44,18 @@ namespace Apache.Ignite.Core.Plugin
     [SuppressMessage("Microsoft.Design", "CA1040:AvoidEmptyInterfaces")]
     public interface IPluginConfiguration
     {
-        // No-op.
+        /// <summary>
+        /// Gets the id to locate PlatformPluginConfigurationClosureFactory on Java side
+        /// and read the data written by <see cref="WriteBinary"/> method.
+        /// </summary>
+        int? PluginConfigurationClosureFactoryId { get; }
+
+        /// <summary>
+        /// Writes this instance to a raw writer.
+        /// This method will be called when <see cref="PluginConfigurationClosureFactoryId"/> is not null to propagate
+        /// configuration to the Java side.
+        /// </summary>
+        /// <param name="writer">The writer.</param>
+        void WriteBinary(IBinaryRawWriter writer);
     }
 }
\ No newline at end of file