001    /******************************************************************************
002     * Copyright (C) MActor Developers. All rights reserved.                        *
003     * ---------------------------------------------------------------------------*
004     * This file is part of MActor.                                               *
005     *                                                                            *
006     * MActor is free software; you can redistribute it and/or modify             *
007     * it under the terms of the GNU General Public License as published by       *
008     * the Free Software Foundation; either version 2 of the License, or          *
009     * (at your option) any later version.                                        *
010     *                                                                            *
011     * MActor is distributed in the hope that it will be useful,                  *
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
014     * GNU General Public License for more details.                               *
015     *                                                                            *
016     * You should have received a copy of the GNU General Public License          *
017     * along with MActor; if not, write to the Free Software                      *
018     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA *
019     ******************************************************************************/
020    package org.mactor.framework.spec;
021    
022    import java.util.Collections;
023    import java.util.HashMap;
024    import java.util.Iterator;
025    import java.util.LinkedList;
026    import java.util.List;
027    import java.util.Map;
028    import java.util.Map.Entry;
029    
030    import org.dom4j.Document;
031    import org.dom4j.DocumentHelper;
032    import org.dom4j.Element;
033    import org.mactor.framework.MactorException;
034    import org.mactor.framework.ParseUtil;
035    
036    public class MessageBrokersConfig {
037            private List<MessageBrokerConfig> brokers = new LinkedList<MessageBrokerConfig>();
038            private Document doc;
039            public String asXML() {
040                    return XmlUtil.getPrettyXML(doc.getRootElement());
041            }
042            public List<MessageBrokerConfig> getMessageBrokers() {
043                    return Collections.unmodifiableList(brokers);
044            }
045            public MessageBrokersConfig(Document doc) throws MactorException {
046                    if (doc == null || doc.getRootElement() == null)
047                            throw new MactorException("Invalid MessageBrokerConfig: null");
048                    this.doc = doc;
049                    Element element = doc.getRootElement();
050                    if (!"message_broker_config".equals(element.getName()))
051                            throw new MactorException("Invalid MessageBrokerConfig. Root node: '" + element.getName() + "'. Expected: 'message_broker_config'");
052                    Iterator it = element.elementIterator("message_broker");
053                    while (it.hasNext()) {
054                            brokers.add(MessageBrokerConfig.loadConfig((Element) it.next()));
055                    }
056            }
057            public static class MessageBrokerConfig {
058                    private Map<String, ChannelConfig> channels = new HashMap<String, ChannelConfig>();
059                    private Map<String, String> values = new HashMap<String, String>();
060                    private String brokerClass;
061                    private String name;
062                    private String archivePath;
063                    private boolean arhiveDeadLetterMessage;
064                    private boolean archiveConsumedMessages;
065                    private int messageReadLimit;
066                    private int messageReadIntervalSeconds;
067                    public boolean isArchiveConsumedMessages() {
068                            return archiveConsumedMessages;
069                    }
070                    public String getArchivePath() {
071                            return archivePath;
072                    }
073                    public boolean isArhiveDeadLetterMessage() {
074                            return arhiveDeadLetterMessage;
075                    }
076                    public String getBrokerClass() {
077                            return brokerClass;
078                    }
079                    public Map<String, ChannelConfig> getChannels() {
080                            return channels;
081                    }
082                    public String getName() {
083                            return name;
084                    }
085                    public Map<String, String> getValues() {
086                            return values;
087                    }
088                    public String getValue(String name) {
089                            return values.get(name);
090                    }
091                    public ChannelConfig getChannelConfig(String channelName) {
092                            return channels.get(channelName);
093                    }
094                    public ChannelConfig getRequieredChannelConfig(String channelName) throws MactorException {
095                            ChannelConfig cf = channels.get(channelName);
096                            if (cf == null)
097                                    throw new MactorException("There is no channel config for channel '" + channelName + "'");
098                            return cf;
099                    }
100                    private static MessageBrokerConfig loadConfig(Element element) throws MactorException {
101                            MessageBrokerConfig mbc = new MessageBrokerConfig();
102                            mbc.name = element.attributeValue("name");
103                            mbc.archivePath = element.attributeValue("archive_path");
104                            mbc.brokerClass = element.attributeValue("broker_class");
105                            mbc.messageReadIntervalSeconds = ParseUtil.tryParseIntVal(element.attributeValue("message_read_interval_seconds"));
106                            if (mbc.messageReadIntervalSeconds == 0)
107                                    mbc.messageReadIntervalSeconds = 10;
108                            mbc.messageReadLimit = ParseUtil.tryParseIntVal(element.attributeValue("message_read_limit"));
109                            if (mbc.messageReadLimit == 0)
110                                    mbc.messageReadLimit = 20;
111                            mbc.archiveConsumedMessages = Boolean.parseBoolean(element.attributeValue("archive_consumed_messages"));
112                            mbc.arhiveDeadLetterMessage = Boolean.parseBoolean(element.attributeValue("archive_dead_letter_messages"));
113                            Iterator it = element.elementIterator("channel");
114                            while (it.hasNext()) {
115                                    ChannelConfig c = ChannelConfig.loadConfig((Element) it.next());
116                                    mbc.channels.put(c.getName(), c);
117                            }
118                            it = element.elementIterator("value");
119                            while (it.hasNext()) {
120                                    Element e = (Element) it.next();
121                                    mbc.values.put(e.attributeValue("name"), e.getTextTrim());
122                            }
123                            return mbc;
124                    }
125                    public static class ChannelConfig {
126                            private Map<String, String> values = new HashMap<String, String>();
127                            private String name;
128                            private boolean requiresResponse;
129                            public String getValue(String valueName) {
130                                    return values.get(valueName);
131                            }
132                            public String getRequieredValue(String valueName) throws MactorException {
133                                    String value = getValue(valueName);
134                                    if (value == null)
135                                            throw new MactorException("The channel config named '" + name + "' does not specify the requiered value '" + valueName + "'");
136                                    return value;
137                            }
138                            public String getValue(String valueName, String defValue) {
139                                    String v = values.get(valueName);
140                                    return v == null ? defValue : v;
141                            }
142                            public static ChannelConfig loadConfig(Element element) throws MactorException {
143                                    ChannelConfig c = new ChannelConfig();
144                                    c.name = element.attributeValue("name");
145                                    c.requiresResponse = Boolean.parseBoolean(element.attributeValue("requires_response"));
146                                    Iterator it = element.elementIterator("value");
147                                    while (it.hasNext()) {
148                                            Element e = (Element) it.next();
149                                            c.values.put(e.attributeValue("name"), e.getTextTrim());
150                                    }
151                                    return c;
152                            }
153                            public String getName() {
154                                    return name;
155                            }
156                            public Map<String, String> getValues() {
157                                    return values;
158                            }
159                            private void writeNodes(Element e) {
160                                    e.addAttribute("name", getName());
161                                    e.addAttribute("requires_response", requiresResponse + "");
162                                    for (Entry<String, String> entry : values.entrySet()) {
163                                            Element val = e.addElement("value");
164                                            val.addAttribute("name", entry.getKey());
165                                            val.setText(entry.getValue().trim());
166                                    }
167                            }
168                            public boolean isRequiresResponse() {
169                                    return requiresResponse;
170                            }
171                    }
172                    public int getMessageReadIntervalSeconds() {
173                            return messageReadIntervalSeconds;
174                    }
175                    public int getMessageReadLimit() {
176                            return messageReadLimit;
177                    }
178                    private void writeNodes(Element e) {
179                            e.addAttribute("archive_path", getArchivePath() + "");
180                            e.addAttribute("broker_class", getBrokerClass());
181                            e.addAttribute("message_read_interval_seconds", getMessageReadLimit() + "");
182                            e.addAttribute("archive_consumed_messages", isArchiveConsumedMessages() + "");
183                            e.addAttribute("archive_dead_letter_messages", isArhiveDeadLetterMessage() + "");
184                            for (Entry<String, ChannelConfig> entry : channels.entrySet()) {
185                                    Element channelElement = e.addElement("channel");
186                                    entry.getValue().writeNodes(channelElement);
187                            }
188                    }
189            }
190            private void writeNodes(Element e) {
191                    for (MessageBrokerConfig config : brokers)
192                            config.writeNodes(e.addElement("message_brokers_config"));
193            }
194            public Document toNewDocument() {
195                    Document newDoc = DocumentHelper.createDocument();
196                    writeNodes(newDoc.addElement("message_brokers_config"));
197                    return newDoc;
198            }
199    }