PageRenderTime 104ms CodeModel.GetById 26ms app.highlight 70ms RepoModel.GetById 2ms app.codeStats 0ms

/hazelcast/src/main/java/com/hazelcast/config/Config.java

https://bitbucket.org/gabral6_gmailcom/hazelcast
Java | 957 lines | 709 code | 124 blank | 124 comment | 116 complexity | 2947d3f14afef24ab96548e5c332bb44 MD5 | raw file
  1/*
  2 * Copyright (c) 2008-2013, Hazelcast, Inc. All Rights Reserved.
  3 *
  4 * Licensed under the Apache License, Version 2.0 (the "License");
  5 * you may not use this file except in compliance with the License.
  6 * You may obtain a copy of the License at
  7 *
  8 * http://www.apache.org/licenses/LICENSE-2.0
  9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed under the License is distributed on an "AS IS" BASIS,
 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 * See the License for the specific language governing permissions and
 14 * limitations under the License.
 15 */
 16
 17package com.hazelcast.config;
 18
 19import com.hazelcast.core.ManagedContext;
 20import com.hazelcast.merge.AddNewEntryMergePolicy;
 21import com.hazelcast.merge.HigherHitsMergePolicy;
 22import com.hazelcast.merge.LatestUpdateMergePolicy;
 23import com.hazelcast.merge.PassThroughMergePolicy;
 24import com.hazelcast.nio.DataSerializable;
 25import com.hazelcast.util.ByteUtil;
 26
 27import java.io.DataInput;
 28import java.io.DataOutput;
 29import java.io.File;
 30import java.io.IOException;
 31import java.net.URL;
 32import java.util.*;
 33import java.util.Map.Entry;
 34import java.util.concurrent.ConcurrentHashMap;
 35
 36import static java.text.MessageFormat.format;
 37
 38public class Config implements DataSerializable {
 39
 40    private String xmlConfig = null;
 41
 42    private URL configurationUrl;
 43
 44    private File configurationFile;
 45
 46    private ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
 47
 48    private Properties properties = new Properties();
 49
 50    private String instanceName = null;
 51
 52    private GroupConfig groupConfig = new GroupConfig();
 53
 54    private boolean liteMember = false;
 55
 56    private boolean checkCompatibility = true;
 57
 58    private NetworkConfig networkConfig = new NetworkConfig();
 59
 60    private Map<String, MapConfig> mapConfigs = new ConcurrentHashMap<String, MapConfig>();
 61
 62    private Map<String, TopicConfig> topicConfigs = new ConcurrentHashMap<String, TopicConfig>();
 63
 64    private Map<String, QueueConfig> queueConfigs = new ConcurrentHashMap<String, QueueConfig>();
 65
 66    private Map<String, MultiMapConfig> multiMapConfigs = new ConcurrentHashMap<String, MultiMapConfig>();
 67
 68    private ExecutorConfig executorConfig = new ExecutorConfig();
 69
 70    private Map<String, ExecutorConfig> executorConfigs = new ConcurrentHashMap<String, ExecutorConfig>();
 71
 72    private Map<String, SemaphoreConfig> semaphoreConfigs = new ConcurrentHashMap<String, SemaphoreConfig>();
 73
 74    private Map<String, MergePolicyConfig> mergePolicyConfigs = new ConcurrentHashMap<String, MergePolicyConfig>();
 75
 76    private Map<String, WanReplicationConfig> wanReplicationConfigs = new ConcurrentHashMap<String, WanReplicationConfig>();
 77
 78    private SecurityConfig securityConfig = new SecurityConfig();
 79
 80    private List<ListenerConfig> listenerConfigs;
 81
 82    private PartitionGroupConfig partitionGroupConfig = new PartitionGroupConfig();
 83
 84    private ManagementCenterConfig managementCenterConfig = new ManagementCenterConfig();
 85
 86    private ManagedContext managedContext;
 87
 88    private String licenseKey;
 89
 90
 91    public Config() {
 92        final String liteMemberProp = System.getProperty("hazelcast.lite.member");
 93        if ("true".equalsIgnoreCase(liteMemberProp)) {
 94            liteMember = true;
 95        }
 96        addMergePolicyConfig(new MergePolicyConfig(AddNewEntryMergePolicy.NAME, new AddNewEntryMergePolicy()));
 97        addMergePolicyConfig(new MergePolicyConfig(HigherHitsMergePolicy.NAME, new HigherHitsMergePolicy()));
 98        addMergePolicyConfig(new MergePolicyConfig(LatestUpdateMergePolicy.NAME, new LatestUpdateMergePolicy()));
 99        addMergePolicyConfig(new MergePolicyConfig(PassThroughMergePolicy.NAME, new PassThroughMergePolicy()));
100    }
101
102    public Config addMergePolicyConfig(MergePolicyConfig mergePolicyConfig) {
103        mergePolicyConfigs.put(mergePolicyConfig.getName(), mergePolicyConfig);
104        return this;
105    }
106
107    public MergePolicyConfig getMergePolicyConfig(String name) {
108        return mergePolicyConfigs.get(name);
109    }
110
111    public Map<String, MergePolicyConfig> getMergePolicyConfigs() {
112        return mergePolicyConfigs;
113    }
114
115    public Config setMergePolicyConfigs(Map<String, MergePolicyConfig> mapMergePolicyConfigs) {
116        this.mergePolicyConfigs = mapMergePolicyConfigs;
117        return this;
118    }
119
120    public WanReplicationConfig getWanReplicationConfig(String name) {
121        return wanReplicationConfigs.get(name);
122    }
123
124    public Config addWanReplicationConfig(WanReplicationConfig wanReplicationConfig) {
125        wanReplicationConfigs.put(wanReplicationConfig.getName(), wanReplicationConfig);
126        return this;
127    }
128
129    public Map<String, WanReplicationConfig> getWanReplicationConfigs() {
130        return wanReplicationConfigs;
131    }
132
133    public Config setWanReplicationConfigs(Map<String, WanReplicationConfig> wanReplicationConfigs) {
134        this.wanReplicationConfigs = wanReplicationConfigs;
135        for (final Entry<String, WanReplicationConfig> entry : this.wanReplicationConfigs.entrySet()) {
136            entry.getValue().setName(entry.getKey());
137        }
138        return this;
139    }
140
141    public ClassLoader getClassLoader() {
142        return classLoader;
143    }
144
145    public Config setClassLoader(ClassLoader classLoader) {
146        this.classLoader = classLoader;
147        return this;
148    }
149
150    public Config setProperty(String name, String value) {
151        properties.put(name, value);
152        return this;
153    }
154
155    public void setProperties(final Properties properties) {
156        this.properties = properties;
157    }
158
159    public Properties getProperties() {
160        return properties;
161    }
162
163    public String getProperty(String name) {
164        String value = properties.getProperty(name);
165        return value != null ? value : System.getProperty(name);
166    }
167
168    public QueueConfig findMatchingQueueConfig(final String name) {
169        QueueConfig config;
170        if ((config = lookupByPattern(queueConfigs, name)) != null) return config;
171        return getQueueConfig("default");
172    }
173
174    public QueueConfig getQueueConfig(final String name) {
175        QueueConfig config;
176        if ((config = lookupByPattern(queueConfigs, name)) != null) return config;
177        QueueConfig defConfig = queueConfigs.get("default");
178        if (defConfig == null) {
179            defConfig = new QueueConfig();
180            defConfig.setName("default");
181            addQueueConfig(defConfig);
182        }
183        config = new QueueConfig(defConfig);
184        config.setName(name);
185        addQueueConfig(config);
186        return config;
187    }
188
189    public MapConfig getMapConfig(final String name) {
190        MapConfig config;
191        if ((config = lookupByPattern(mapConfigs, name)) != null) return config;
192        MapConfig defConfig = mapConfigs.get("default");
193        if (defConfig == null) {
194            defConfig = new MapConfig();
195            defConfig.setName("default");
196            addMapConfig(defConfig);
197        }
198        config = new MapConfig(defConfig);
199        config.setName(name);
200        addMapConfig(config);
201        return config;
202    }
203
204    public MultiMapConfig getMultiMapConfig(final String name) {
205        MultiMapConfig config;
206        if ((config = lookupByPattern(multiMapConfigs, name)) != null) return config;
207        MultiMapConfig defConfig = multiMapConfigs.get("default");
208        if (defConfig == null) {
209            defConfig = new MultiMapConfig();
210            defConfig.setName("default");
211            addMultiMapConfig(defConfig);
212        }
213        config = new MultiMapConfig(defConfig);
214        config.setName(name);
215        addMultiMapConfig(config);
216        return config;
217    }
218
219    public MapConfig findMatchingMapConfig(String name) {
220        MapConfig config;
221        if ((config = lookupByPattern(mapConfigs, name)) != null) return config;
222        return getMapConfig("default");
223    }
224
225    public TopicConfig findMatchingTopicConfig(final String name) {
226        TopicConfig config;
227        if ((config = lookupByPattern(topicConfigs, name)) != null) {
228            return config;
229        }
230        return getTopicConfig("default");
231    }
232
233    public TopicConfig getTopicConfig(final String name) {
234        TopicConfig config;
235        if ((config = lookupByPattern(topicConfigs, name)) != null) {
236            return config;
237        }
238        TopicConfig defConfig = topicConfigs.get("default");
239        if (defConfig == null) {
240            defConfig = new TopicConfig();
241            defConfig.setName("default");
242            addTopicConfig(defConfig);
243        }
244        config = new TopicConfig(defConfig);
245        config.setName(name);
246        addTopicConfig(config);
247        return config;
248    }
249
250    private static <T> T lookupByPattern(Map<String, T> map, String name) {
251        T t = map.get(name);
252        if (t == null) {
253            final Set<String> tNames = map.keySet();
254            for (final String pattern : tNames) {
255                if (nameMatches(name, pattern)) {
256                    return map.get(pattern);
257                }
258            }
259        }
260        return t;
261    }
262
263    public static boolean nameMatches(final String name, final String pattern) {
264        final int index = pattern.indexOf('*');
265        if (index == -1) {
266            return name.equals(pattern);
267        } else {
268            final String firstPart = pattern.substring(0, index);
269            final int indexFirstPart = name.indexOf(firstPart, 0);
270            if (indexFirstPart == -1) {
271                return false;
272            }
273            final String secondPart = pattern.substring(index + 1);
274            final int indexSecondPart = name.indexOf(secondPart, index + 1);
275            return indexSecondPart != -1;
276        }
277    }
278
279    public NetworkConfig getNetworkConfig() {
280        return networkConfig;
281    }
282
283    public Config setNetworkConfig(NetworkConfig networkConfig) {
284        this.networkConfig = networkConfig;
285        return this;
286    }
287
288    /**
289     * @return the xmlConfig
290     */
291    public String getXmlConfig() {
292        return xmlConfig;
293    }
294
295    /**
296     * @param xmlConfig the xmlConfig to set
297     */
298    public Config setXmlConfig(String xmlConfig) {
299        this.xmlConfig = xmlConfig;
300        return this;
301    }
302
303    public GroupConfig getGroupConfig() {
304        return groupConfig;
305    }
306
307    public Config setGroupConfig(final GroupConfig groupConfig) {
308        this.groupConfig = groupConfig;
309        return this;
310    }
311
312    /**
313     * @return the port
314     * @deprecated instead use getNetworkConfig().getPort()
315     * @see NetworkConfig#getPort()
316     */
317    @Deprecated
318    public int getPort() {
319        return networkConfig.getPort();
320    }
321
322    /**
323     * @param port the port to set
324     * @deprecated instead use getNetworkConfig().setPort(int)
325     * @see NetworkConfig#setPort(int)
326     */
327    @Deprecated
328    public Config setPort(int port) {
329        networkConfig.setPort(port);
330        return this;
331    }
332
333    /**
334     * @return the portAutoIncrement
335     * @deprecated instead use getNetworkConfig().isPortAutoIncrement()
336     * @see NetworkConfig#isPortAutoIncrement()
337     */
338    @Deprecated
339    public boolean isPortAutoIncrement() {
340        return networkConfig.isPortAutoIncrement();
341    }
342
343    /**
344     * @param portAutoIncrement the portAutoIncrement to set
345     * @deprecated instead use getNetworkConfig().setPortAutoIncrement(boolean)
346     * @see NetworkConfig#setPortAutoIncrement(boolean)
347     */
348    @Deprecated
349    public Config setPortAutoIncrement(boolean portAutoIncrement) {
350        networkConfig.setPortAutoIncrement(portAutoIncrement);
351        return this;
352    }
353
354    @Deprecated
355    public boolean isReuseAddress() {
356        return networkConfig.isReuseAddress();
357    }
358
359    @Deprecated
360    public Config setReuseAddress(boolean reuseAddress) {
361        networkConfig.setReuseAddress(reuseAddress);
362        return this;
363    }
364
365    public boolean isCheckCompatibility() {
366        return this.checkCompatibility;
367    }
368
369    public Config setCheckCompatibility(boolean checkCompatibility) {
370        this.checkCompatibility = checkCompatibility;
371        return this;
372    }
373
374    /**
375     * @return the executorConfig
376     * @deprecated use getExecutorConfig (name) instead
377     */
378    public ExecutorConfig getExecutorConfig() {
379        return executorConfig;
380    }
381
382    /**
383     * @param executorConfig the executorConfig to set
384     * @deprecated use addExecutorConfig instead
385     */
386    public Config setExecutorConfig(ExecutorConfig executorConfig) {
387        addExecutorConfig(executorConfig);
388        return this;
389    }
390
391    /**
392     * Adds a new ExecutorConfig by name
393     *
394     * @param executorConfig executor config to add
395     * @return this config instance
396     */
397    public Config addExecutorConfig(ExecutorConfig executorConfig) {
398        this.executorConfigs.put(executorConfig.getName(), executorConfig);
399        return this;
400    }
401
402    /**
403     * Returns the ExecutorConfig for the given name
404     *
405     * @param name name of the executor config
406     * @return ExecutorConfig
407     */
408    public ExecutorConfig getExecutorConfig(String name) {
409        ExecutorConfig ec = lookupByPattern(executorConfigs, name);
410        if (ec != null) {
411            return ec;
412        }
413
414        ExecutorConfig defaultConfig = executorConfigs.get("default");
415        if (defaultConfig != null) {
416            ec = new ExecutorConfig(name,
417                defaultConfig.getCorePoolSize(),
418                defaultConfig.getMaxPoolSize(),
419                defaultConfig.getKeepAliveSeconds());
420        }
421        if (ec == null) {
422            ec = new ExecutorConfig(name);
423            executorConfigs.put(name, ec);
424        }
425        return ec;
426    }
427
428    /**
429     * Returns the collection of executor configs.
430     *
431     * @return collection of executor configs.
432     */
433    public Collection<ExecutorConfig> getExecutorConfigs() {
434        return executorConfigs.values();
435    }
436
437    public Map<String, ExecutorConfig> getExecutorConfigMap() {
438        return Collections.unmodifiableMap(executorConfigs);
439    }
440
441    public Config setExecutorConfigMap(Map<String, ExecutorConfig> mapExecutors) {
442        this.executorConfigs = mapExecutors;
443        for (final Entry<String, ExecutorConfig> entry : this.executorConfigs.entrySet()) {
444            entry.getValue().setName(entry.getKey());
445        }
446        return this;
447    }
448
449    public Config addTopicConfig(TopicConfig topicConfig) {
450        topicConfigs.put(topicConfig.getName(), topicConfig);
451        return this;
452    }
453
454    /**
455     * @return the topicConfigs
456     */
457    public Map<String, TopicConfig> getTopicConfigs() {
458        return Collections.unmodifiableMap(topicConfigs);
459    }
460
461    /**
462     * @param mapTopicConfigs the topicConfigs to set
463     */
464    public Config setTopicConfigs(Map<String, TopicConfig> mapTopicConfigs) {
465        this.topicConfigs = mapTopicConfigs;
466        for (final Entry<String, TopicConfig> entry : this.topicConfigs.entrySet()) {
467            entry.getValue().setName(entry.getKey());
468        }
469        return this;
470    }
471
472    /**
473     * @return the mapQConfigs
474     */
475    public Map<String, QueueConfig> getQConfigs() {
476        return Collections.unmodifiableMap(queueConfigs);
477    }
478
479    public Config addQueueConfig(QueueConfig queueConfig) {
480        queueConfigs.put(queueConfig.getName(), queueConfig);
481        return this;
482    }
483
484    /**
485     * @param mapQConfigs the mapQConfigs to set
486     */
487    public Config setQConfigs(Map<String, QueueConfig> mapQConfigs) {
488        this.queueConfigs = mapQConfigs;
489        for (final Entry<String, QueueConfig> entry : this.queueConfigs.entrySet()) {
490            entry.getValue().setName(entry.getKey());
491        }
492        return this;
493    }
494
495    /**
496     * @param mapQConfigs the mapQConfigs to set
497     */
498    public Config setMapQConfigs(Map<String, QueueConfig> mapQConfigs) {
499        this.queueConfigs = mapQConfigs;
500        for (final Entry<String, QueueConfig> entry : this.queueConfigs.entrySet()) {
501            entry.getValue().setName(entry.getKey());
502        }
503        return this;
504    }
505
506    public Config addMapConfig(MapConfig mapConfig) {
507        mapConfigs.put(mapConfig.getName(), mapConfig);
508        return this;
509    }
510
511    public Config addMultiMapConfig(MultiMapConfig multiMapConfig) {
512        multiMapConfigs.put(multiMapConfig.getName(), multiMapConfig);
513        return this;
514    }
515
516    /**
517     * @return the mapConfigs
518     */
519    public Map<String, MapConfig> getMapConfigs() {
520        return Collections.unmodifiableMap(mapConfigs);
521    }
522
523    public Map<String, MultiMapConfig> getMultiMapConfigs() {
524        return Collections.unmodifiableMap(multiMapConfigs);
525    }
526
527    /**
528     * @param mapConfigs the mapConfigs to set
529     */
530    public Config setMapConfigs(Map<String, MapConfig> mapConfigs) {
531        this.mapConfigs = mapConfigs;
532        for (final Entry<String, MapConfig> entry : this.mapConfigs.entrySet()) {
533            entry.getValue().setName(entry.getKey());
534        }
535        return this;
536    }
537
538    public Config setMultiMapConfigs(Map<String, MultiMapConfig> multiMapConfigs) {
539        this.multiMapConfigs = multiMapConfigs;
540        for (final Entry<String, MultiMapConfig> entry : this.multiMapConfigs.entrySet()) {
541            entry.getValue().setName(entry.getKey());
542        }
543        return this;
544    }
545
546    /**
547     * Adds a new SemaphoreConfig by name
548     *
549     * @param semaphoreConfig semaphore config to add
550     * @return this config instance
551     */
552    public Config addSemaphoreConfig(SemaphoreConfig semaphoreConfig) {
553        this.semaphoreConfigs.put(semaphoreConfig.getName(), semaphoreConfig);
554        return this;
555    }
556
557    /**
558     * Returns the SemaphoreConfig for the given name
559     *
560     * @param name name of the semaphore config
561     * @return SemaphoreConfig
562     */
563    public SemaphoreConfig getSemaphoreConfig(String name) {
564        SemaphoreConfig sc = lookupByPattern(semaphoreConfigs, name);
565        if (sc != null) {
566            return sc;
567        }
568
569        SemaphoreConfig defaultConfig = semaphoreConfigs.get("default");
570        if (defaultConfig != null) {
571           sc = new SemaphoreConfig(name, defaultConfig);
572        }
573        if (sc == null) {
574            sc = new SemaphoreConfig(name);
575            semaphoreConfigs.put(name, sc);
576        }
577        return sc;
578    }
579
580    /**
581     * Returns the collection of semaphore configs.
582     *
583     * @return collection of semaphore configs.
584     */
585    public Collection<SemaphoreConfig> getSemaphoreConfigs() {
586        return semaphoreConfigs.values();
587    }
588
589    public Map<String, SemaphoreConfig> getSemaphoreConfigMap() {
590        return Collections.unmodifiableMap(semaphoreConfigs);
591    }
592
593    public Config setSemaphoreConfigMap(Map<String, SemaphoreConfig> mapSemaphores) {
594        this.semaphoreConfigs = mapSemaphores;
595        for (final Entry<String, SemaphoreConfig> entry : this.semaphoreConfigs.entrySet()) {
596            entry.getValue().setName(entry.getKey());
597        }
598        return this;
599    }
600
601    /**
602     * @return the configurationUrl
603     */
604    public URL getConfigurationUrl() {
605        return configurationUrl;
606    }
607
608    /**
609     * @param configurationUrl the configurationUrl to set
610     */
611    public Config setConfigurationUrl(URL configurationUrl) {
612        this.configurationUrl = configurationUrl;
613        return this;
614    }
615
616    /**
617     * @return the configurationFile
618     */
619    public File getConfigurationFile() {
620        return configurationFile;
621    }
622
623    /**
624     * @param configurationFile the configurationFile to set
625     */
626    public Config setConfigurationFile(File configurationFile) {
627        this.configurationFile = configurationFile;
628        return this;
629    }
630
631    public boolean isLiteMember() {
632        return liteMember;
633    }
634
635    public Config setLiteMember(boolean liteMember) {
636        this.liteMember = liteMember;
637        return this;
638    }
639
640    public SecurityConfig getSecurityConfig() {
641        return securityConfig;
642    }
643
644    public Config setSecurityConfig(SecurityConfig securityConfig) {
645        this.securityConfig = securityConfig;
646        return this;
647    }
648
649    public Config addListenerConfig(ListenerConfig listenerConfig) {
650        getListenerConfigs().add(listenerConfig);
651        return this;
652    }
653
654    public List<ListenerConfig> getListenerConfigs() {
655        if (listenerConfigs == null) {
656            listenerConfigs = new ArrayList<ListenerConfig>();
657        }
658        return listenerConfigs;
659    }
660
661    public Config setListenerConfigs(List<ListenerConfig> listenerConfigs) {
662        this.listenerConfigs = listenerConfigs;
663        return this;
664    }
665
666    public PartitionGroupConfig getPartitionGroupConfig() {
667        return partitionGroupConfig;
668    }
669
670    public Config setPartitionGroupConfig(PartitionGroupConfig partitionGroupConfig) {
671        this.partitionGroupConfig = partitionGroupConfig;
672        return this;
673    }
674
675    public ManagedContext getManagedContext() {
676        return managedContext;
677    }
678
679    public Config setManagedContext(final ManagedContext managedContext) {
680        this.managedContext = managedContext;
681        return this;
682    }
683
684    /**
685     * @param config
686     * @return true if config is compatible with this one,
687     *         false if config belongs to another group
688     * @throws RuntimeException if map, queue, topic configs are incompatible
689     */
690    public boolean isCompatible(final Config config) {
691        if (config == null) {
692            throw new IllegalArgumentException("Expected not null config");
693        }
694        if (!this.groupConfig.getName().equals(config.getGroupConfig().getName())) {
695            return false;
696        }
697        if (!this.groupConfig.getPassword().equals(config.getGroupConfig().getPassword())) {
698            throw new RuntimeException("Incompatible group password");
699        }
700        if (checkCompatibility) {
701            checkMapConfigCompatible(config);
702            checkQueueConfigCompatible(config);
703            checkTopicConfigCompatible(config);
704        }
705        return true;
706    }
707
708    private void checkMapConfigCompatible(final Config config) {
709        Set<String> mapConfigNames = new HashSet<String>(mapConfigs.keySet());
710        mapConfigNames.addAll(config.mapConfigs.keySet());
711        for (final String name : mapConfigNames) {
712            final MapConfig thisMapConfig = lookupByPattern(mapConfigs, name);
713            final MapConfig thatMapConfig = lookupByPattern(config.mapConfigs, name);
714            if (thisMapConfig != null && thatMapConfig != null &&
715                    !thisMapConfig.isCompatible(thatMapConfig)) {
716                throw new RuntimeException(format("Incompatible map config this:\n{0}\nanother:\n{1}",
717                        thisMapConfig, thatMapConfig));
718            }
719        }
720    }
721
722    private void checkQueueConfigCompatible(final Config config) {
723        Set<String> queueConfigNames = new HashSet<String>(queueConfigs.keySet());
724        queueConfigNames.addAll(config.queueConfigs.keySet());
725        for (final String name : queueConfigNames) {
726            final QueueConfig thisQueueConfig = lookupByPattern(queueConfigs, name);
727            final QueueConfig thatQueueConfig = lookupByPattern(config.queueConfigs, name);
728            if (thisQueueConfig != null && thatQueueConfig != null &&
729                    !thisQueueConfig.isCompatible(thatQueueConfig)) {
730                throw new RuntimeException(format("Incompatible queue config this:\n{0}\nanother:\n{1}",
731                        thisQueueConfig, thatQueueConfig));
732            }
733        }
734    }
735
736    private void checkTopicConfigCompatible(final Config config) {
737        Set<String> topicConfigNames = new HashSet<String>(topicConfigs.keySet());
738        topicConfigNames.addAll(config.topicConfigs.keySet());
739        for (final String name : topicConfigNames) {
740            final TopicConfig thisTopicConfig = lookupByPattern(topicConfigs, name);
741            final TopicConfig thatTopicConfig = lookupByPattern(config.topicConfigs, name);
742            if (thisTopicConfig != null && thatTopicConfig != null &&
743                    !thisTopicConfig.equals(thatTopicConfig)) {
744                throw new RuntimeException(format("Incompatible topic config this:\n{0}\nanother:\n{1}",
745                        thisTopicConfig, thatTopicConfig));
746            }
747        }
748    }
749
750    public void readData(DataInput in) throws IOException {
751        groupConfig = new GroupConfig();
752        groupConfig.readData(in);
753        boolean[] b1 = ByteUtil.fromByte(in.readByte());
754        checkCompatibility = b1[0];
755        liteMember = b1[1];
756        boolean[] b2 = ByteUtil.fromByte(in.readByte());
757        boolean hasMapConfigs = b2[0];
758        boolean hasMapExecutors = b2[1];
759        boolean hasMapTopicConfigs = b2[2];
760        boolean hasMapQueueConfigs = b2[3];
761        boolean hasMapMergePolicyConfigs = b2[4];
762        boolean hasMapSemaphoreConfigs = b2[5];
763        boolean hasProperties = b2[6];
764        networkConfig = new NetworkConfig();
765        networkConfig.readData(in);
766        executorConfig = new ExecutorConfig();
767        executorConfig.readData(in);
768        if (hasMapConfigs) {
769            int size = in.readInt();
770            mapConfigs = new ConcurrentHashMap<String, MapConfig>(size);
771            for (int i = 0; i < size; i++) {
772                final MapConfig mapConfig = new MapConfig();
773                mapConfig.readData(in);
774                mapConfigs.put(mapConfig.getName(), mapConfig);
775            }
776        }
777        if (hasMapExecutors) {
778            int size = in.readInt();
779            executorConfigs = new ConcurrentHashMap<String, ExecutorConfig>(size);
780            for (int i = 0; i < size; i++) {
781                final ExecutorConfig executorConfig = new ExecutorConfig();
782                executorConfig.readData(in);
783                executorConfigs.put(executorConfig.getName(), executorConfig);
784            }
785        }
786        if (hasMapSemaphoreConfigs) {
787            int size = in.readInt();
788            semaphoreConfigs = new ConcurrentHashMap<String, SemaphoreConfig>(size);
789            for (int i = 0; i < size; i++) {
790                final SemaphoreConfig semaphoreConfig = new SemaphoreConfig();
791                semaphoreConfig.readData(in);
792                semaphoreConfigs.put(semaphoreConfig.getName(), semaphoreConfig);
793            }
794        }
795        if (hasMapTopicConfigs) {
796            int size = in.readInt();
797            topicConfigs = new ConcurrentHashMap<String, TopicConfig>(size);
798            for (int i = 0; i < size; i++) {
799                final TopicConfig topicConfig = new TopicConfig();
800                topicConfig.readData(in);
801                topicConfigs.put(topicConfig.getName(), topicConfig);
802            }
803        }
804        if (hasMapQueueConfigs) {
805            int size = in.readInt();
806            queueConfigs = new ConcurrentHashMap<String, QueueConfig>(size);
807            for (int i = 0; i < size; i++) {
808                final QueueConfig queueConfig = new QueueConfig();
809                queueConfig.readData(in);
810                queueConfigs.put(queueConfig.getName(), queueConfig);
811            }
812        }
813        if (hasMapMergePolicyConfigs) {
814            // TODO: Map<String, MergePolicyConfig> mergePolicyConfigs
815        }
816        if (hasProperties) {
817            int size = in.readInt();
818            properties = new Properties();
819            for (int i = 0; i < size; i++) {
820                final String name = in.readUTF();
821                final String value = in.readUTF();
822                properties.put(name, value);
823            }
824        }
825    }
826
827    public void writeData(DataOutput out) throws IOException {
828        getGroupConfig().writeData(out);
829        boolean hasMapConfigs = mapConfigs != null && !mapConfigs.isEmpty();
830        boolean hasMapExecutors = executorConfigs != null && !executorConfigs.isEmpty();
831        boolean hasMapTopicConfigs = topicConfigs != null && !topicConfigs.isEmpty();
832        boolean hasMapQueueConfigs = queueConfigs != null && !queueConfigs.isEmpty();
833        boolean hasMapMergePolicyConfigs = mergePolicyConfigs != null && !mergePolicyConfigs.isEmpty();
834        boolean hasMapSemaphoreConfigs = semaphoreConfigs != null && !semaphoreConfigs.isEmpty();
835        boolean hasProperties = properties != null && !properties.isEmpty();
836        out.writeByte(ByteUtil.toByte(checkCompatibility, liteMember));
837        out.writeByte(ByteUtil.toByte(
838                hasMapConfigs,
839                hasMapExecutors,
840                hasMapTopicConfigs,
841                hasMapQueueConfigs,
842                hasMapMergePolicyConfigs,
843                hasMapSemaphoreConfigs,
844                hasProperties));
845        networkConfig.writeData(out);
846        executorConfig.writeData(out);
847        if (hasMapConfigs) {
848            out.writeInt(mapConfigs.size());
849            for (final Entry<String, MapConfig> entry : mapConfigs.entrySet()) {
850                final String name = entry.getKey();
851                final MapConfig mapConfig = entry.getValue();
852                mapConfig.setName(name);
853                mapConfig.writeData(out);
854            }
855        }
856        if (hasMapExecutors) {
857            out.writeInt(executorConfigs.size());
858            for (final Entry<String, ExecutorConfig> entry : executorConfigs.entrySet()) {
859                final String name = entry.getKey();
860                final ExecutorConfig executorConfig = entry.getValue();
861                executorConfig.setName(name);
862                executorConfig.writeData(out);
863            }
864        }
865        if (hasMapSemaphoreConfigs) {
866            out.writeInt(semaphoreConfigs.size());
867            for (final Entry<String, SemaphoreConfig> entry : semaphoreConfigs.entrySet()) {
868                final String name = entry.getKey();
869                final SemaphoreConfig semaphoreConfig = entry.getValue();
870                semaphoreConfig.setName(name);
871                semaphoreConfig.writeData(out);
872            }
873        }
874        if (hasMapTopicConfigs) {
875            out.writeInt(topicConfigs.size());
876            for (final Entry<String, TopicConfig> entry : topicConfigs.entrySet()) {
877                final String name = entry.getKey();
878                final TopicConfig topicConfig = entry.getValue();
879                topicConfig.setName(name);
880                topicConfig.writeData(out);
881            }
882        }
883        if (hasMapQueueConfigs) {
884            out.writeInt(queueConfigs.size());
885            for (final Entry<String, QueueConfig> entry : queueConfigs.entrySet()) {
886                final String name = entry.getKey();
887                final QueueConfig queueConfig = entry.getValue();
888                queueConfig.setName(name);
889                queueConfig.writeData(out);
890            }
891        }
892        if (hasMapMergePolicyConfigs) {
893            // TODO: Map<String, MergePolicyConfig> mergePolicyConfigs
894        }
895        if (hasProperties) {
896            out.writeInt(properties.size());
897            for (final Entry<Object, Object> entry : properties.entrySet()) {
898                final String key = (String) entry.getKey();
899                final String value = (String) entry.getValue();
900                out.writeUTF(key);
901                out.writeUTF(value);
902            }
903        }
904    }
905
906    public String getInstanceName() {
907        return instanceName;
908    }
909
910    public Config setInstanceName(String instanceName) {
911        this.instanceName = instanceName;
912        return this;
913    }
914
915    public String getLicenseKey() {
916        return licenseKey;
917    }
918
919    public Config setLicenseKey(final String licenseKey) {
920        this.licenseKey = licenseKey;
921        return this;
922    }
923
924    public ManagementCenterConfig getManagementCenterConfig() {
925        return managementCenterConfig;
926    }
927
928    public Config setManagementCenterConfig(final ManagementCenterConfig managementCenterConfig) {
929        this.managementCenterConfig = managementCenterConfig;
930        return this;
931    }
932
933    @Override
934    public String toString() {
935        final StringBuilder sb = new StringBuilder();
936        sb.append("Config");
937        sb.append("{groupConfig=").append(groupConfig);
938        sb.append(", liteMember=").append(liteMember);
939        sb.append(", checkCompatibility=").append(checkCompatibility);
940        sb.append(", properties=").append(properties);
941        sb.append(", networkConfig=").append(networkConfig);
942        sb.append(", mapConfigs=").append(mapConfigs);
943        sb.append(", topicConfigs=").append(topicConfigs);
944        sb.append(", queueConfigs=").append(queueConfigs);
945        sb.append(", multiMapConfigs=").append(multiMapConfigs);
946        sb.append(", executorConfigs=").append(executorConfigs);
947        sb.append(", semaphoreConfigs=").append(semaphoreConfigs);
948        sb.append(", mergePolicyConfigs=").append(mergePolicyConfigs);
949        sb.append(", wanReplicationConfigs=").append(wanReplicationConfigs);
950        sb.append(", listenerConfigs=").append(listenerConfigs);
951        sb.append(", partitionGroupConfig=").append(partitionGroupConfig);
952        sb.append(", managementCenterConfig=").append(managementCenterConfig);
953        sb.append(", securityConfig=").append(securityConfig);
954        sb.append('}');
955        return sb.toString();
956    }
957}