001 /*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements. See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership. The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied. See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 *
020 */
021 package org.apache.qpid.management.configuration;
022
023 import java.io.BufferedReader;
024 import java.io.File;
025 import java.io.FileInputStream;
026 import java.io.InputStreamReader;
027 import java.util.UUID;
028
029 import javax.xml.parsers.SAXParser;
030 import javax.xml.parsers.SAXParserFactory;
031
032 import org.apache.qpid.management.Messages;
033 import org.apache.qpid.management.Names;
034 import org.apache.qpid.management.Protocol;
035 import org.apache.qpid.management.domain.handler.impl.ConfigurationMessageHandler;
036 import org.apache.qpid.management.domain.handler.impl.EventContentMessageHandler;
037 import org.apache.qpid.management.domain.handler.impl.HeartBeatIndicationMessageHandler;
038 import org.apache.qpid.management.domain.handler.impl.InstrumentationMessageHandler;
039 import org.apache.qpid.management.domain.handler.impl.MethodResponseMessageHandler;
040 import org.apache.qpid.management.domain.handler.impl.SchemaResponseMessageHandler;
041 import org.apache.qpid.management.domain.model.AccessMode;
042 import org.apache.qpid.management.domain.model.type.AbsTime;
043 import org.apache.qpid.management.domain.model.type.DeltaTime;
044 import org.apache.qpid.management.domain.model.type.ObjectReference;
045 import org.apache.qpid.management.domain.model.type.Str16;
046 import org.apache.qpid.management.domain.model.type.Str8;
047 import org.apache.qpid.management.domain.model.type.Uint16;
048 import org.apache.qpid.management.domain.model.type.Uint32;
049 import org.apache.qpid.management.domain.model.type.Uint64;
050 import org.apache.qpid.management.domain.model.type.Uint8;
051 import org.apache.qpid.transport.util.Logger;
052 import org.xml.sax.Attributes;
053 import org.xml.sax.InputSource;
054 import org.xml.sax.SAXException;
055 import org.xml.sax.helpers.DefaultHandler;
056
057 /**
058 * Director used for coordinating the build process of configuration.
059 * This is the only component which has a read-write permission on Configuration object.
060 */
061 public class Configurator extends DefaultHandler
062 {
063 private final static Logger LOGGER = Logger.get(Configurator.class);
064
065 /**
066 * Default (empty) parser used when there's no need to process data (non relevant elements).
067 */
068 final static IParser DEFAULT_PARSER = new IParser() {
069
070 public void setCurrrentAttributeValue (String value)
071 {
072 }
073
074 public void setCurrentAttributeName (String name)
075 {
076 }
077 };
078
079 IParser _brokerConfigurationParser = new BrokerConnectionDataParser();
080 IParser _workerManagerConfigurationParser = new WorkerManagerConfigurationParser();
081 IParser _currentParser = DEFAULT_PARSER;
082
083 /**
084 * Delegates the processing to the current parser.
085 */
086 @Override
087 public void characters (char[] ch, int start, int length) throws SAXException
088 {
089 String value = new String(ch,start,length).trim();
090 if (value.length() != 0) {
091 _currentParser.setCurrrentAttributeValue(value);
092 }
093 }
094
095 /**
096 * Here is defined what parser needs to be used for processing the current data.
097 */
098 @Override
099 public void startElement (String uri, String localName, String name, Attributes attributes) throws SAXException
100 {
101 switch(Tag.get(name))
102 {
103 case BROKERS :
104 {
105 _currentParser = _brokerConfigurationParser;
106 break;
107 }
108 case WORK_MANAGER :
109 {
110 _currentParser = _workerManagerConfigurationParser;
111 break;
112 }
113 }
114 }
115
116 @Override
117 public void endElement (String uri, String localName, String name) throws SAXException
118 {
119 _currentParser.setCurrentAttributeName(name);
120 }
121
122 /**
123 * Builds whole configuration.
124 *
125 * @throws ConfigurationException when the build fails.
126 */
127 public void configure() throws ConfigurationException
128 {
129 BufferedReader reader = null;
130 try
131 {
132 String initialConfigFileName = System.getProperty(Names.QMAN_CONFIG_OPTION_NAME);
133 if (initialConfigFileName != null && initialConfigFileName.trim().length() != 0)
134 {
135 File initialConfigurationFile = new File(initialConfigFileName);
136 if (initialConfigurationFile.canRead())
137 {
138 SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
139 reader = new BufferedReader(
140 new InputStreamReader(
141 new FileInputStream(initialConfigFileName)));
142 InputSource source = new InputSource(reader);
143 parser.parse(source, this);
144 } else {
145 LOGGER.warn(
146 Messages.QMAN_300004_INVALID_CONFIGURATION_FILE,
147 initialConfigFileName);
148 }
149 }
150
151 addTypeMappings();
152 addAccessModeMappings();
153
154 addMandatoryManagementMessageHandlers();
155 addMandatoryMethodReplyMessageHandlers();
156 } catch (Exception exception)
157 {
158 throw new ConfigurationException(exception);
159 } finally
160 {
161 try
162 {
163 reader.close();
164 } catch (Exception ignore)
165 {
166 }
167 }
168 }
169
170 /**
171 * Creates and return a value object (BrokerConnectionData) with the given parameters.
172 * Note that that object will be stored on configuration and it could be used to set a connection with the broker.
173 * This happens when the "initialPoolCapacity" is greater than 0 : in this case the caller is indicatinf that it wants to open
174 * one or more connections immediately at startup and therefore Q-Man will try to do that.
175 *
176 * @param host the hostname where the broker is running.
177 * @param port the port where the broker is running.
178 * @param username the username for connecting with the broker.
179 * @param password the password for connecting with the broker.
180 * @param virtualHost the virtual host.
181 * @param initialPoolCapacity the number of the connection that must be immediately opened.
182 * @param maxPoolCapacity the maximum number of opened connection.
183 * @param maxWaitTimeout the maximum amount of time that a client will wait for obtaining a connection.
184 * @return the value object containing the data above.
185 * @throws BrokerAlreadyConnectedException when the broker is already connected.
186 * @throws BrokerConnectionException when a connection cannot be estabilished.
187 */
188 public BrokerConnectionData createAndReturnBrokerConnectionData(
189 UUID brokerId,
190 String host,
191 int port,
192 String username,
193 String password,
194 String virtualHost,
195 int initialPoolCapacity,
196 int maxPoolCapacity,
197 long maxWaitTimeout) throws BrokerAlreadyConnectedException, BrokerConnectionException
198 {
199 BrokerConnectionData data = new BrokerConnectionData(
200 host,
201 port,
202 virtualHost,
203 username,
204 password,
205 initialPoolCapacity,
206 maxPoolCapacity,
207 maxWaitTimeout);
208 Configuration.getInstance().addBrokerConnectionData(brokerId, data);
209 return data;
210 }
211
212 /**
213 * Configures access mode mappings.
214 * An access mode mapping is an association between a code and an access mode.
215 */
216 private void addAccessModeMappings() {
217 Configuration configuration = Configuration.getInstance();
218 configuration.addAccessModeMapping(new AccessModeMapping(1,AccessMode.RC));
219 configuration.addAccessModeMapping(new AccessModeMapping(2,AccessMode.RW));
220 configuration.addAccessModeMapping(new AccessModeMapping(3,AccessMode.RO));
221 }
222
223 /**
224 * Configures type mappings.
225 * A type mapping is an association between a code and a management type.
226 */
227 private void addTypeMappings()
228 {
229 Configuration configuration = Configuration.getInstance();
230 configuration.addTypeMapping(new TypeMapping(1,new Uint8(),Names.NUMBER_VALIDATOR));
231 configuration.addTypeMapping(new TypeMapping(2,new Uint16(),Names.NUMBER_VALIDATOR));
232 configuration.addTypeMapping(new TypeMapping(3,new Uint32(),Names.NUMBER_VALIDATOR));
233 configuration.addTypeMapping(new TypeMapping(4,new Uint64(),Names.NUMBER_VALIDATOR));
234 configuration.addTypeMapping(new TypeMapping(6,new Str8(),Names.STRING_VALIDATOR));
235 configuration.addTypeMapping(new TypeMapping(7,new Str16(),Names.STRING_VALIDATOR));
236 configuration.addTypeMapping(new TypeMapping(8,new AbsTime()));
237 configuration.addTypeMapping(new TypeMapping(9,new DeltaTime()));
238 configuration.addTypeMapping(new TypeMapping(10,new ObjectReference()));
239 configuration.addTypeMapping(new TypeMapping(11,new org.apache.qpid.management.domain.model.type.Boolean()));
240 configuration.addTypeMapping(new TypeMapping(14,new org.apache.qpid.management.domain.model.type.Uuid()));
241 configuration.addTypeMapping(new TypeMapping(15,new org.apache.qpid.management.domain.model.type.Map()));
242 }
243
244 /**
245 * Configures the mandatory management message handlers.
246 */
247 void addMandatoryMethodReplyMessageHandlers ()
248 {
249 Configuration.getInstance().addMethodReplyMessageHandlerMapping(
250 new MessageHandlerMapping(
251 Protocol.OPERATION_INVOCATION_RESPONSE_OPCODE,
252 new MethodResponseMessageHandler()));
253
254 Configuration.getInstance().addMethodReplyMessageHandlerMapping(
255 new MessageHandlerMapping(
256 Protocol.SCHEMA_RESPONSE_OPCODE,
257 new SchemaResponseMessageHandler()));
258 }
259
260 /**
261 * Configures the mandatory management message handlers.
262 */
263 void addMandatoryManagementMessageHandlers ()
264 {
265 Configuration.getInstance().addManagementMessageHandlerMapping(
266 new MessageHandlerMapping(
267 Protocol.INSTRUMENTATION_CONTENT_RESPONSE_OPCODE,
268 new InstrumentationMessageHandler()));
269
270 Configuration.getInstance().addManagementMessageHandlerMapping(
271 new MessageHandlerMapping(
272 Protocol.CONFIGURATION_CONTENT_RESPONSE_OPCDE,
273 new ConfigurationMessageHandler()));
274
275 Configuration.getInstance().addManagementMessageHandlerMapping(
276 new MessageHandlerMapping(
277 Protocol.EVENT_CONTENT_RESPONSE_OPCDE,
278 new EventContentMessageHandler()));
279
280 Configuration.getInstance().addManagementMessageHandlerMapping(
281 new MessageHandlerMapping(
282 Protocol.HEARTBEAT_INDICATION_RESPONSE_OPCODE,
283 new HeartBeatIndicationMessageHandler()));
284 }
285 }
|