001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package org.apache.hadoop.conf;
020
021 import org.apache.commons.logging.*;
022
023 import java.util.Collection;
024
025 /**
026 * Utility base class for implementing the Reconfigurable interface.
027 *
028 * Subclasses should override reconfigurePropertyImpl to change individual
029 * properties and getReconfigurableProperties to get all properties that
030 * can be changed at run time.
031 */
032 public abstract class ReconfigurableBase
033 extends Configured implements Reconfigurable {
034
035 private static final Log LOG =
036 LogFactory.getLog(ReconfigurableBase.class);
037
038 /**
039 * Construct a ReconfigurableBase.
040 */
041 public ReconfigurableBase() {
042 super(new Configuration());
043 }
044
045 /**
046 * Construct a ReconfigurableBase with the {@link Configuration}
047 * conf.
048 */
049 public ReconfigurableBase(Configuration conf) {
050 super((conf == null) ? new Configuration() : conf);
051 }
052
053 /**
054 * {@inheritDoc}
055 *
056 * This method makes the change to this objects {@link Configuration}
057 * and calls reconfigurePropertyImpl to update internal data structures.
058 * This method cannot be overridden, subclasses should instead override
059 * reconfigureProperty.
060 */
061 @Override
062 public final String reconfigureProperty(String property, String newVal)
063 throws ReconfigurationException {
064 if (isPropertyReconfigurable(property)) {
065 LOG.info("changing property " + property + " to " + newVal);
066 String oldVal;
067 synchronized(getConf()) {
068 oldVal = getConf().get(property);
069 reconfigurePropertyImpl(property, newVal);
070 if (newVal != null) {
071 getConf().set(property, newVal);
072 } else {
073 getConf().unset(property);
074 }
075 }
076 return oldVal;
077 } else {
078 throw new ReconfigurationException(property, newVal,
079 getConf().get(property));
080 }
081 }
082
083 /**
084 * {@inheritDoc}
085 *
086 * Subclasses must override this.
087 */
088 @Override
089 public abstract Collection<String> getReconfigurableProperties();
090
091
092 /**
093 * {@inheritDoc}
094 *
095 * Subclasses may wish to override this with a more efficient implementation.
096 */
097 @Override
098 public boolean isPropertyReconfigurable(String property) {
099 return getReconfigurableProperties().contains(property);
100 }
101
102 /**
103 * Change a configuration property.
104 *
105 * Subclasses must override this. This method applies the change to
106 * all internal data structures derived from the configuration property
107 * that is being changed. If this object owns other Reconfigurable objects
108 * reconfigureProperty should be called recursively to make sure that
109 * to make sure that the configuration of these objects is updated.
110 */
111 protected abstract void reconfigurePropertyImpl(String property, String newVal)
112 throws ReconfigurationException;
113
114 }