001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.geronimo.system.configuration;
018
019 import java.io.File;
020 import java.io.FileInputStream;
021 import java.io.FileOutputStream;
022 import java.io.IOException;
023 import java.io.Writer;
024 import java.io.Reader;
025 import java.io.FileReader;
026 import java.io.BufferedReader;
027 import java.io.FileWriter;
028 import java.io.BufferedWriter;
029 import java.util.ArrayList;
030 import java.util.Collection;
031 import java.util.HashMap;
032 import java.util.Iterator;
033 import java.util.List;
034 import java.util.Map;
035 import java.util.Properties;
036 import java.util.Timer;
037 import java.util.TimerTask;
038
039 import javax.xml.parsers.ParserConfigurationException;
040 import javax.xml.bind.JAXBException;
041 import javax.xml.stream.XMLStreamException;
042
043 import org.apache.commons.logging.Log;
044 import org.apache.commons.logging.LogFactory;
045 import org.apache.geronimo.gbean.AbstractName;
046 import org.apache.geronimo.gbean.GAttributeInfo;
047 import org.apache.geronimo.gbean.GBeanData;
048 import org.apache.geronimo.gbean.GBeanInfo;
049 import org.apache.geronimo.gbean.GBeanInfoBuilder;
050 import org.apache.geronimo.gbean.GBeanLifecycle;
051 import org.apache.geronimo.gbean.GReferenceInfo;
052 import org.apache.geronimo.gbean.ReferencePatterns;
053 import org.apache.geronimo.kernel.InvalidGBeanException;
054 import org.apache.geronimo.kernel.config.Configuration;
055 import org.apache.geronimo.kernel.config.InvalidConfigException;
056 import org.apache.geronimo.kernel.config.ManageableAttributeStore;
057 import org.apache.geronimo.kernel.config.PersistentConfigurationList;
058 import org.apache.geronimo.kernel.repository.Artifact;
059 import org.apache.geronimo.system.configuration.condition.JexlExpressionParser;
060 import org.apache.geronimo.system.configuration.condition.ParserUtils;
061 import org.apache.geronimo.system.plugin.model.GbeanType;
062 import org.apache.geronimo.system.plugin.model.AttributesType;
063 import org.apache.geronimo.system.serverinfo.ServerInfo;
064 import org.xml.sax.SAXException;
065
066 /**
067 * Stores managed attributes in an XML file on the local filesystem.
068 *
069 * @version $Rev: 889880 $ $Date: 2009-12-12 10:45:24 +0800 (Sat, 12 Dec 2009) $
070 */
071 public class LocalAttributeManager implements LocalPluginAttributeStore, PersistentConfigurationList, GBeanLifecycle {
072 private static final Log log = LogFactory.getLog(LocalAttributeManager.class);
073
074 private static final String CONFIG_FILE_PROPERTY = "org.apache.geronimo.config.file";
075 private final static String SUBSTITUTIONS_FILE_PROPERTY = "org.apache.geronimo.config.substitutions.file";
076 private final static String SUBSTITUTION_PREFIX_PREFIX = "org.apache.geronimo.config.substitution.prefix";
077
078 private static final String BACKUP_EXTENSION = ".bak";
079 private static final String TEMP_EXTENSION = ".working";
080 private static final int SAVE_BUFFER_MS = 5000;
081
082 private final ServerInfo serverInfo;
083 private final String configFile;
084 private final boolean readOnly;
085 private final JexlExpressionParser expressionParser;
086
087 private File attributeFile;
088 private File backupFile;
089 private File tempFile;
090 private ServerOverride serverOverride;
091
092 private Timer timer;
093 private TimerTask currentTask;
094
095 private boolean kernelFullyStarted;
096
097 private String prefix;
098 private File configSubstitutionsFile;
099 private Properties localConfigSubstitutions;
100 private String resolvedPropertiesFile;
101 private static final byte[] INSTRUCTION = ("# Put variables and their substitution values in this file. \n"
102 + "# They will be used when processing the corresponding config.xml. \n"
103 + "# Values in this file can be overridden by environment variables and system properties \n"
104 + "# by prefixing the property name with 'org.apache.geronimo.config.substitution.' \n"
105 + "# For example, an entry such as hostName=localhost \n"
106 + "# can be overridden by an environment variable or system property org.apache.geronimo.config.substitution.hostName=foo \n"
107 + "# When running multiple instances of Geronimo choose a PortOffset value such that none of the ports conflict. \n"
108 + "# For example, try PortOffset=10 \n").getBytes();
109
110 public LocalAttributeManager(String configFile, String configSubstitutionsFileName, String configSubstitutionsPrefix, boolean readOnly, ServerInfo serverInfo) {
111 this.configFile = System.getProperty(CONFIG_FILE_PROPERTY, configFile);
112 resolvedPropertiesFile = System.getProperty(SUBSTITUTIONS_FILE_PROPERTY, configSubstitutionsFileName);
113 configSubstitutionsFile = resolvedPropertiesFile == null? null: serverInfo.resolveServer(resolvedPropertiesFile);
114 localConfigSubstitutions = loadConfigSubstitutions(configSubstitutionsFile);
115 prefix = System.getProperty(SUBSTITUTION_PREFIX_PREFIX, configSubstitutionsPrefix);
116 Map<String, Object> configSubstitutions = loadAllConfigSubstitutions(localConfigSubstitutions, prefix);
117 expressionParser = new JexlExpressionParser(configSubstitutions);
118 this.readOnly = readOnly;
119 this.serverInfo = serverInfo;
120 serverOverride = new ServerOverride();
121 log.debug("setting configSubstitutionsFile to " + configSubstitutionsFile + ".");
122 }
123
124 public boolean isReadOnly() {
125 return readOnly;
126 }
127
128
129 public String getConfigFile() {
130 return configFile;
131 }
132
133 public String getConfigSubstitutionsFile() {
134 return resolvedPropertiesFile;
135 }
136
137 public String getConfigSubstitutionsPrefix() {
138 return prefix;
139 }
140
141 public synchronized Collection applyOverrides(Artifact configName, Collection<GBeanData> untypedGbeanDatas, ClassLoader classLoader) throws InvalidConfigException {
142 // clone the datas since we will be modifying this collection
143 Collection<GBeanData> gbeanDatas = new ArrayList<GBeanData>(untypedGbeanDatas);
144
145 ConfigurationOverride configuration = serverOverride.getConfiguration(configName);
146 if (configuration == null) {
147 return gbeanDatas;
148 }
149
150 // index the incoming datas
151 Map<Object, GBeanData> datasByName = new HashMap<Object, GBeanData>();
152 for (GBeanData gbeanData : gbeanDatas) {
153 datasByName.put(gbeanData.getAbstractName(), gbeanData);
154 datasByName.put(gbeanData.getAbstractName().getName().get("name"), gbeanData);
155 }
156
157 // add the new GBeans
158 for (Object o : configuration.getGBeans().entrySet()) {
159 Map.Entry entry = (Map.Entry) o;
160 Object name = entry.getKey();
161 GBeanOverride gbean = (GBeanOverride) entry.getValue();
162 if (!datasByName.containsKey(name) && gbean.isLoad()) {
163 if (gbean.getGBeanInfo() == null || !(name instanceof AbstractName)) {
164 String sep = "";
165 StringBuffer message = new StringBuffer("New GBeans must be specified with ");
166 if (gbean.getGBeanInfo() == null) {
167 message.append("a GBeanInfo ");
168 sep = "and ";
169 }
170 if (!(name instanceof AbstractName)) {
171 message.append(sep).append("a full AbstractName ");
172 }
173 message.append("configuration=").append(configName);
174 message.append(" gbeanName=").append(name);
175 throw new InvalidConfigException(message.toString());
176 }
177 GBeanInfo gbeanInfo = GBeanInfo.getGBeanInfo(gbean.getGBeanInfo(), classLoader);
178 AbstractName abstractName = (AbstractName) name;
179 GBeanData gBeanData = new GBeanData(abstractName, gbeanInfo);
180 gbeanDatas.add(gBeanData);
181 }
182 }
183
184 // set the attributes
185 for (Iterator iterator = gbeanDatas.iterator(); iterator.hasNext();) {
186 GBeanData data = (GBeanData) iterator.next();
187 boolean load = setAttributes(data, configuration, configName, classLoader);
188 if (!load) {
189 iterator.remove();
190 }
191 }
192 return gbeanDatas;
193 }
194
195 /**
196 * Set the attributes from the attribute store on a single gbean, and return whether or not to load the gbean.
197 *
198 * @param data GBeanData we are going to override attributes on
199 * @param configuration the module override the gbean relates to
200 * @param configName name of the module (why can't this be determined from the configuration?)
201 * @param classLoader ClassLoader to use for property objects/PropertyEditors
202 * @return true if the gbean should be loaded, false otherwise.
203 * @throws org.apache.geronimo.kernel.config.InvalidConfigException
204 * if we cannot update the gbeanData
205 */
206 private synchronized boolean setAttributes(GBeanData data, ConfigurationOverride configuration, Artifact configName, ClassLoader classLoader) throws InvalidConfigException {
207 AbstractName gbeanName = data.getAbstractName();
208 GBeanOverride gbean = configuration.getGBean(gbeanName);
209 if (gbean == null) {
210 gbean = configuration.getGBean((String) gbeanName.getName().get("name"));
211 }
212
213 if (gbean == null) {
214 //no attr info, load by default
215 return true;
216 }
217
218 return gbean.applyOverrides(data, configName, gbeanName, classLoader);
219 }
220
221 public void setModuleGBeans(Artifact moduleName, List<GbeanType> gbeans, boolean load, String condition) throws InvalidGBeanException {
222 if (readOnly) {
223 return;
224 }
225 ConfigurationOverride configuration = serverOverride.getConfiguration(moduleName, true);
226 if (gbeans != null) {
227 for (GbeanType gbean : gbeans) {
228 GBeanOverride override = new GBeanOverride(gbean, expressionParser);
229 configuration.addGBean(override);
230 }
231 }
232 configuration.setLoad(load);
233 configuration.setCondition(condition);
234 log.info("Added gbeans for module: " + moduleName + " load: " + load);
235 attributeChanged();
236 }
237
238 public void addConfigSubstitutions(Properties properties) {
239 localConfigSubstitutions.putAll(properties);
240 Map<String, Object> configSubstutions = loadAllConfigSubstitutions(localConfigSubstitutions, prefix);
241 storeConfigSubstitutions(configSubstitutionsFile, localConfigSubstitutions);
242 expressionParser.setVariables(configSubstutions);
243 }
244
245 public synchronized void setValue(Artifact configurationName, AbstractName gbeanName, GAttributeInfo attribute, Object value, ClassLoader classLoader) {
246 if (readOnly) {
247 return;
248 }
249 ConfigurationOverride configuration = serverOverride.getConfiguration(configurationName, true);
250 GBeanOverride gbean = configuration.getGBean(gbeanName);
251 if (gbean == null) {
252 gbean = configuration.getGBean((String) gbeanName.getName().get("name"));
253 if (gbean == null) {
254 gbean = new GBeanOverride(gbeanName, true, expressionParser);
255 configuration.addGBean(gbeanName, gbean);
256 }
257 }
258
259 try {
260 gbean.setAttribute(attribute, value, classLoader);
261 attributeChanged();
262 } catch (InvalidAttributeException e) {
263 // attribute can not be represented as a string
264 log.error(e.getMessage());
265 }
266 }
267
268 public synchronized void setReferencePatterns(Artifact configurationName, AbstractName gbeanName, GReferenceInfo reference, ReferencePatterns patterns) {
269 if (readOnly) {
270 return;
271 }
272
273 ConfigurationOverride configuration = serverOverride.getConfiguration(configurationName, true);
274 GBeanOverride gbean = configuration.getGBean(gbeanName);
275 if (gbean == null) {
276 gbean = configuration.getGBean((String) gbeanName.getName().get("name"));
277 if (gbean == null) {
278 gbean = new GBeanOverride(gbeanName, true, expressionParser);
279 configuration.addGBean(gbeanName, gbean);
280 }
281 }
282 gbean.setReferencePatterns(reference.getName(), patterns);
283 attributeChanged();
284 }
285
286 public synchronized void setShouldLoad(Artifact configurationName, AbstractName gbeanName, boolean load) {
287 if (readOnly) {
288 return;
289 }
290 ConfigurationOverride configuration = serverOverride.getConfiguration(configurationName, true);
291
292 GBeanOverride gbean = configuration.getGBean(gbeanName);
293 if (gbean == null) {
294 // attempt to lookup by short name
295 gbean = configuration.getGBean((String) gbeanName.getName().get("name"));
296 }
297
298 if (gbean == null) {
299 gbean = new GBeanOverride(gbeanName, load, expressionParser);
300 configuration.addGBean(gbeanName, gbean);
301 } else {
302 gbean.setLoad(load);
303 }
304 attributeChanged();
305 }
306
307 public void addGBean(Artifact configurationName, GBeanData gbeanData, ClassLoader classLoader) {
308 if (readOnly) {
309 return;
310 }
311 ConfigurationOverride configuration = serverOverride.getConfiguration(configurationName);
312 if (configuration == null) {
313 log.debug("Can not add GBean; Configuration not found " + configurationName);
314 return;
315 }
316 try {
317 GBeanOverride gbean = new GBeanOverride(gbeanData, expressionParser, classLoader);
318 configuration.addGBean(gbean);
319 attributeChanged();
320 } catch (InvalidAttributeException e) {
321 // attribute can not be represented as a string
322 log.error(e.getMessage());
323 }
324 }
325
326 public synchronized void load() throws IOException {
327 ensureParentDirectory();
328 if (!attributeFile.exists()) {
329 return;
330 }
331 Reader input = new BufferedReader(new FileReader(attributeFile));
332
333 try {
334 serverOverride = read(input, expressionParser);
335
336 } catch (SAXException e) {
337 log.error("Unable to read saved manageable attributes", e);
338 } catch (ParserConfigurationException e) {
339 log.error("Unable to read saved manageable attributes", e);
340 } catch (InvalidGBeanException e) {
341 log.error("Unable to read saved manageable attributes", e);
342 } catch (JAXBException e) {
343 log.error("Unable to read saved manageable attributes", e);
344 } catch (XMLStreamException e) {
345 log.error("Unable to read saved manageable attributes", e);
346 } finally {
347 // input is always non-null
348 input.close();
349 }
350 }
351
352 static ServerOverride read(Reader input, JexlExpressionParser expressionParser) throws ParserConfigurationException, IOException, SAXException, JAXBException, XMLStreamException, InvalidGBeanException {
353 AttributesType attributes = AttributesXmlUtil.loadAttributes(input);
354 return new ServerOverride(attributes, expressionParser);
355 }
356
357 public synchronized void save() throws IOException {
358 if (readOnly) {
359 return;
360 }
361 ensureParentDirectory();
362 if (!tempFile.exists() && !tempFile.createNewFile()) {
363 throw new IOException("Unable to create manageable attribute working file for save " + tempFile.getAbsolutePath());
364 }
365 if (!tempFile.canWrite()) {
366 throw new IOException("Unable to write to manageable attribute working file for save " + tempFile.getAbsolutePath());
367 }
368
369 // write the new configuration to the temp file
370 saveXmlToFile(tempFile, serverOverride);
371
372 // delete the current backup file
373 if (backupFile.exists()) {
374 if (!backupFile.delete()) {
375 throw new IOException("Unable to delete old backup file in order to back up current manageable attribute working file for save");
376 }
377 }
378
379 // rename the existing configuration file to the backup file
380 if (attributeFile.exists()) {
381 if (!attributeFile.renameTo(backupFile)) {
382 throw new IOException("Unable to rename " + attributeFile.getAbsolutePath() + " to " + backupFile.getAbsolutePath() + " in order to back up manageable attribute save file");
383 }
384 }
385
386 // rename the temp file the the configuration file
387 if (!tempFile.renameTo(attributeFile)) {
388 throw new IOException(
389 "EXTREMELY CRITICAL! Unable to move manageable attributes working file to proper file name! Configuration will revert to defaults unless this is manually corrected! (could not rename " + tempFile.getAbsolutePath() + " to " + attributeFile.getAbsolutePath() + ")");
390 }
391 }
392
393 void write(Writer writer) throws XMLStreamException, JAXBException,
394 IOException {
395 AttributesType attributes = serverOverride.writeXml();
396 AttributesXmlUtil.writeAttributes(attributes, writer);
397 writer.flush();
398 }
399
400 private static void saveXmlToFile(File file, ServerOverride serverOverride) {
401 try {
402 Writer fileOut = new FileWriter(file);
403 try {
404 Writer writer = new BufferedWriter(fileOut);
405 write(serverOverride, writer);
406 } catch (JAXBException e) {
407 log.error("Unable to write config.xml", e);
408 } catch (XMLStreamException e) {
409 log.error("Unable to write config.xml", e);
410 } finally {
411 fileOut.close();
412 }
413 } catch (IOException e) {
414 log.error("Unable to write config.xml", e);
415 }
416 }
417
418 static void write(ServerOverride serverOverride, Writer writer) throws XMLStreamException, JAXBException, IOException {
419 AttributesType attributes = serverOverride.writeXml();
420 AttributesXmlUtil.writeAttributes(attributes, writer);
421 writer.flush();
422 }
423
424 //PersistentConfigurationList
425 public synchronized boolean isKernelFullyStarted() {
426 return kernelFullyStarted;
427 }
428
429 public synchronized void setKernelFullyStarted(boolean kernelFullyStarted) {
430 this.kernelFullyStarted = kernelFullyStarted;
431 }
432
433 public synchronized List<Artifact> restore() throws IOException {
434 List<Artifact> configs = new ArrayList<Artifact>();
435 for (Map.Entry<Artifact, ConfigurationOverride> entry : serverOverride.getConfigurations().entrySet()) {
436 ConfigurationOverride configuration = entry.getValue();
437 if (configuration.isLoad()) {
438 Artifact configID = entry.getKey();
439 configs.add(configID);
440 }
441 }
442 return configs;
443 }
444
445 public void startConfiguration(Artifact configurationName) {
446 if (readOnly) {
447 return;
448 }
449 ConfigurationOverride configuration = serverOverride.getConfiguration(configurationName, false);
450 if (configuration == null) {
451 return;
452 }
453 configuration.setLoad(true);
454 attributeChanged();
455 }
456
457 public synchronized void addConfiguration(Artifact configurationName) {
458 if (readOnly) {
459 return;
460 }
461 // Check whether we have it already
462 ConfigurationOverride configuration = serverOverride.getConfiguration(configurationName, false);
463 // If not, initialize it
464 if (configuration == null) {
465 configuration = serverOverride.getConfiguration(configurationName, true);
466 configuration.setLoad(false);
467 attributeChanged();
468 }
469 }
470
471 public synchronized void removeConfiguration(Artifact configName) {
472 if (readOnly) {
473 return;
474 }
475 ConfigurationOverride configuration = serverOverride.getConfiguration(configName);
476 if (configuration == null) {
477 return;
478 }
479 serverOverride.removeConfiguration(configName);
480 attributeChanged();
481 }
482
483 public Artifact[] getListedConfigurations(Artifact query) {
484 return serverOverride.queryConfigurations(query);
485 }
486
487 public void stopConfiguration(Artifact configName) {
488 if (readOnly) {
489 return;
490 }
491 ConfigurationOverride configuration = serverOverride.getConfiguration(configName);
492 if (configuration == null) {
493 return;
494 }
495 configuration.setLoad(false);
496 attributeChanged();
497 }
498
499 public void migrateConfiguration(Artifact oldName, Artifact newName, Configuration configuration) {
500 if (readOnly) {
501 return;
502 }
503 ConfigurationOverride configInfo = serverOverride.getConfiguration(oldName);
504 if (configInfo == null) {
505 throw new IllegalArgumentException("Trying to migrate unknown configuration: " + oldName);
506 }
507 serverOverride.removeConfiguration(oldName);
508 configInfo = new ConfigurationOverride(configInfo, newName);
509 //todo: check whether all the attributes are still valid for the new configuration
510 serverOverride.addConfiguration(configInfo);
511 attributeChanged();
512 }
513
514 /**
515 * This method checks if there are any custom gbean attributes in the configuration.
516 *
517 * @param configName Name of the configuration
518 * @return true if the configuration contains any custom gbean attributes
519 */
520 public boolean hasGBeanAttributes(Artifact configName) {
521 ConfigurationOverride configInfo = serverOverride.getConfiguration(configName);
522 return configInfo != null && !configInfo.getGBeans().isEmpty();
523 }
524
525 //GBeanLifeCycle
526 public synchronized void doStart() throws Exception {
527 load();
528 if (!readOnly) {
529 timer = new Timer(true);
530 }
531 log.debug("Started LocalAttributeManager with data on " + serverOverride.getConfigurations().size() + " configurations");
532 }
533
534 public synchronized void doStop() throws Exception {
535 boolean doSave = false;
536 synchronized (this) {
537 if (timer != null) {
538 timer.cancel();
539 if (currentTask != null) {
540 currentTask.cancel();
541 doSave = true;
542 }
543 }
544 }
545 if (doSave) {
546 save();
547 }
548 log.debug("Stopped LocalAttributeManager with data on " + serverOverride.getConfigurations().size() + " configurations");
549 serverOverride = new ServerOverride();
550 }
551
552 public synchronized void doFail() {
553 synchronized (this) {
554 if (timer != null) {
555 timer.cancel();
556 if (currentTask != null) {
557 currentTask.cancel();
558 }
559 }
560 }
561 serverOverride = new ServerOverride();
562 }
563
564 private synchronized void ensureParentDirectory() throws IOException {
565 if (attributeFile == null) {
566 attributeFile = serverInfo.resolveServer(configFile);
567 tempFile = new File(attributeFile.getAbsolutePath() + TEMP_EXTENSION);
568 backupFile = new File(attributeFile.getAbsolutePath() + BACKUP_EXTENSION);
569 }
570 File parent = attributeFile.getParentFile();
571 if (!parent.isDirectory()) {
572 if (!parent.mkdirs()) {
573 throw new IOException("Unable to create directory for list:" + parent);
574 }
575 }
576 if (!parent.canRead()) {
577 throw new IOException("Unable to read manageable attribute files in directory " + parent.getAbsolutePath());
578 }
579 if (!readOnly && !parent.canWrite()) {
580 throw new IOException("Unable to write manageable attribute files to directory " + parent.getAbsolutePath());
581 }
582 }
583
584 private synchronized void attributeChanged() {
585 if (currentTask != null) {
586 currentTask.cancel();
587 }
588 if (timer != null) {
589 currentTask = new TimerTask() {
590
591 public void run() {
592 try {
593 LocalAttributeManager.this.save();
594 } catch (IOException e) {
595 log.error("IOException occurred while saving attributes", e);
596 } catch (Throwable t) {
597 log.error("Error occurred during execution of attributeChanged TimerTask", t);
598 }
599 }
600 };
601 timer.schedule(currentTask, SAVE_BUFFER_MS);
602 }
603 }
604
605 private static Map<String, Object> loadAllConfigSubstitutions(Properties configSubstitutions, String prefix) {
606 Map<String, Object> vars = new HashMap<String, Object>();
607 //most significant are the command line system properties
608 addGeronimoSubstitutions(vars, System.getProperties(), prefix);
609 //environment variables are next
610 addGeronimoSubstitutions(vars, System.getenv(), prefix);
611 //properties file is least significant
612 if (configSubstitutions != null) {
613 addGeronimoSubstitutions(vars, configSubstitutions, "");
614 }
615 ParserUtils.addDefaultVariables(vars);
616 return vars;
617 }
618
619 private static Properties loadConfigSubstitutions(File configSubstitutionsFile) {
620 Properties properties = new Properties();
621 if (configSubstitutionsFile != null) {
622 if (!configSubstitutionsFile.exists()) {
623 //write out empty file with instructions as a hint to users.
624 storeConfigSubstitutions(configSubstitutionsFile, properties);
625 } else {
626 try {
627 FileInputStream in = new FileInputStream(configSubstitutionsFile);
628 try {
629 properties.load(in);
630 } finally {
631 in.close();
632 }
633 } catch (Exception e) {
634 log.error("Caught exception " + e
635 + " trying to read properties file " + configSubstitutionsFile.getAbsolutePath());
636 }
637 }
638 }
639 return properties;
640 }
641
642 private static void storeConfigSubstitutions(File configSubstitutionsFile, Properties properties) {
643 if (configSubstitutionsFile != null) {
644 try {
645 FileOutputStream out = new FileOutputStream(configSubstitutionsFile);
646 try {
647 out.write(INSTRUCTION);
648 properties.store(out, null);
649 } finally {
650 out.close();
651 }
652 } catch (Exception e) {
653 log.error("Caught exception " + e
654 + " trying to write properties file " + configSubstitutionsFile.getAbsolutePath());
655 }
656 }
657 }
658
659 private static void addGeronimoSubstitutions(Map<String, Object> vars, Map props, String prefix) {
660 if (prefix != null) {
661 int start = prefix.length();
662 for (Object o : props.entrySet()) {
663 Map.Entry entry = (Map.Entry) o;
664 if (((String) entry.getKey()).startsWith(prefix)) {
665 String key = ((String) entry.getKey()).substring(start);
666 if (!vars.containsKey(key)) {
667 vars.put(key, entry.getValue());
668 }
669 }
670 }
671 }
672 }
673
674 public static final GBeanInfo GBEAN_INFO;
675
676 static {
677 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(LocalAttributeManager.class, "AttributeStore");
678 infoFactory.addReference("ServerInfo", ServerInfo.class, "GBean");
679 infoFactory.addAttribute("configFile", String.class, true);
680 infoFactory.addAttribute("readOnly", boolean.class, true);
681 infoFactory.addAttribute("substitutionsFile", String.class, true);
682 infoFactory.addAttribute("substitutionPrefix", String.class, true);
683 infoFactory.addInterface(ManageableAttributeStore.class);
684 infoFactory.addInterface(PersistentConfigurationList.class);
685
686 infoFactory.setConstructor(new String[]{"configFile", "substitutionsFile", "substitutionPrefix", "readOnly", "ServerInfo"});
687
688 GBEAN_INFO = infoFactory.getBeanInfo();
689 }
690
691 public static GBeanInfo getGBeanInfo() {
692 return GBEAN_INFO;
693 }
694 }