Configurator.java
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 lengththrows 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 attributesthrows 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 namethrows 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 }