diff options
Diffstat (limited to 'java/broker-core/src/main/java/org/apache')
25 files changed, 796 insertions, 239 deletions
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java b/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java index 0a1979128f..0b925d130c 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java @@ -40,6 +40,7 @@ import org.apache.qpid.server.logging.LogRecorder; import org.apache.qpid.server.logging.SystemOutMessageLogger; import org.apache.qpid.server.logging.log4j.LoggingManagementFacade; import org.apache.qpid.server.logging.messages.BrokerMessages; +import org.apache.qpid.server.model.BrokerShutdownProvider; import org.apache.qpid.server.model.SystemConfig; import org.apache.qpid.server.plugin.PluggableFactoryLoader; import org.apache.qpid.server.plugin.SystemConfigFactory; @@ -48,7 +49,7 @@ import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.store.DurableConfigurationStore; -public class Broker +public class Broker implements BrokerShutdownProvider { private static final Logger LOGGER = Logger.getLogger(Broker.class); @@ -143,7 +144,7 @@ public class Broker LogRecorder logRecorder = new LogRecorder(); _taskExecutor.start(); - SystemConfig systemConfig = configFactory.newInstance(_taskExecutor, _eventLogger, logRecorder, options); + SystemConfig systemConfig = configFactory.newInstance(_taskExecutor, _eventLogger, logRecorder, options, this); systemConfig.open(); DurableConfigurationStore store = systemConfig.getConfigurationStore(); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java index b71d667fe0..6c67a44bb0 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java @@ -29,9 +29,12 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; +import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.configuration.updater.VoidTask; import org.apache.qpid.server.exchange.AbstractExchange; import org.apache.qpid.server.exchange.ExchangeImpl; +import org.apache.qpid.server.filter.AMQInvalidArgumentException; +import org.apache.qpid.server.filter.FilterSupport; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.messages.BindingMessages; import org.apache.qpid.server.logging.subjects.BindingLogSubject; @@ -269,4 +272,23 @@ public class BindingImpl ); } + + @Override + public void validateOnCreate() + { + AMQQueue queue = getAMQQueue(); + Map<String, Object> arguments = getArguments(); + if (arguments!=null && !arguments.isEmpty() && FilterSupport.argumentsContainFilter(arguments)) + { + try + { + FilterSupport.createMessageFilter(arguments, queue); + } + catch (AMQInvalidArgumentException e) + { + throw new IllegalConfigurationException(e.getMessage(), e); + } + } + } + } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java index fd0333f6e7..989a4abea5 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java @@ -118,16 +118,6 @@ public abstract class AbstractExchange<T extends AbstractExchange<T>> throw new IllegalArgumentException("Unknown attributes provided: " + providedAttributeNames); } _virtualHost = vhost; - // check ACL - try - { - _virtualHost.getSecurityManager().authoriseCreateExchange(this); - } - catch (AccessControlException e) - { - deleted(); - throw e; - } _logSubject = new ExchangeLogSubject(this, this.getVirtualHost()); @@ -145,6 +135,12 @@ public abstract class AbstractExchange<T extends AbstractExchange<T>> } @Override + public void validateOnCreate() + { + _virtualHost.getSecurityManager().authoriseCreateExchange(this); + } + + @Override public void onValidate() { super.onValidate(); @@ -756,7 +752,7 @@ public abstract class AbstractExchange<T extends AbstractExchange<T>> final Map<String, Object> oldArguments); - @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE) + @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE) private void activate() { setState(State.ACTIVE); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java index d3741cd846..e6f79fef16 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java @@ -47,6 +47,7 @@ import java.util.concurrent.atomic.AtomicReference; import javax.security.auth.Subject; +import org.apache.log4j.Logger; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.JsonProcessingException; import org.codehaus.jackson.Version; @@ -72,6 +73,8 @@ import org.apache.qpid.util.Strings; public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> implements ConfiguredObject<X> { + private static final Logger LOGGER = Logger.getLogger(AbstractConfiguredObject.class); + private static final Map<Class, Object> SECURE_VALUES; public static final String SECURED_STRING_VALUE = "********"; @@ -156,9 +159,10 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im private final OwnAttributeResolver _attributeResolver = new OwnAttributeResolver(this); - @ManagedAttributeField( afterSet = "attainStateIfResolved" ) + @ManagedAttributeField( afterSet = "attainStateIfOpenedOrReopenFailed" ) private State _desiredState; private boolean _openComplete; + private boolean _openFailed; private volatile State _state = State.UNINITIALIZED; protected static Map<Class<? extends ConfiguredObject>, ConfiguredObject<?>> parentsMap(ConfiguredObject<?>... parents) @@ -404,10 +408,19 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im { if(_dynamicState.compareAndSet(DynamicState.UNINIT, DynamicState.OPENED)) { - doResolution(true); - doValidation(true); - doOpening(true); - doAttainState(); + _openFailed = false; + OpenExceptionHandler exceptionHandler = new OpenExceptionHandler(); + try + { + doResolution(true, exceptionHandler); + doValidation(true, exceptionHandler); + doOpening(true, exceptionHandler); + doAttainState(exceptionHandler); + } + catch(RuntimeException e) + { + exceptionHandler.handleException(e, this); + } } } @@ -485,18 +498,76 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im _lastUpdatedTime = currentTime; _createdTime = currentTime; - doResolution(true); - doValidation(true); + CreateExceptionHandler createExceptionHandler = new CreateExceptionHandler(); + try + { + doResolution(true, createExceptionHandler); + doValidation(true, createExceptionHandler); + validateOnCreate(); + registerWithParents(); + } + catch(RuntimeException e) + { + createExceptionHandler.handleException(e, this); + } + + AbstractConfiguredObjectExceptionHandler unregisteringExceptionHandler = new CreateExceptionHandler(true); + try + { + doCreation(true, unregisteringExceptionHandler); + doOpening(true, unregisteringExceptionHandler); + doAttainState(unregisteringExceptionHandler); + } + catch(RuntimeException e) + { + unregisteringExceptionHandler.handleException(e, this); + } + } + } + + protected void validateOnCreate() + { + } + + protected final void handleExceptionOnOpen(RuntimeException e) + { + if (e instanceof ServerScopedRuntimeException) + { + throw e; + } + + LOGGER.error("Failed to open object with name '" + getName() + "'. Object will be put into ERROR state.", e); - registerWithParents(); + try + { + onExceptionInOpen(e); + } + catch (RuntimeException re) + { + LOGGER.error("Unexpected exception while handling exception on open for " + getName(), e); + } - doCreation(true); - doOpening(true); - doAttainState(); + if (!_openComplete) + { + _openFailed = true; + _dynamicState.compareAndSet(DynamicState.OPENED, DynamicState.UNINIT); } + + //TODO: children of ERRORED CO will continue to remain in ACTIVE state + setState(State.ERRORED); + } + + /** + * Callback method to perform ConfiguredObject specific exception handling on exception in open. + * <p/> + * The method is not expected to throw any runtime exception. + * @param e open exception + */ + protected void onExceptionInOpen(RuntimeException e) + { } - private void doAttainState() + private void doAttainState(final AbstractConfiguredObjectExceptionHandler exceptionHandler) { applyToChildren(new Action<ConfiguredObject<?>>() { @@ -505,14 +576,25 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im { if (child instanceof AbstractConfiguredObject) { - ((AbstractConfiguredObject) child).doAttainState(); + AbstractConfiguredObject configuredObject = (AbstractConfiguredObject) child; + if (configuredObject._dynamicState.get() == DynamicState.OPENED) + { + try + { + configuredObject.doAttainState(exceptionHandler); + } + catch (RuntimeException e) + { + exceptionHandler.handleException(e, configuredObject); + } + } } } }); attainState(); } - protected void doOpening(final boolean skipCheck) + protected void doOpening(boolean skipCheck, final AbstractConfiguredObjectExceptionHandler exceptionHandler) { if(skipCheck || _dynamicState.compareAndSet(DynamicState.UNINIT,DynamicState.OPENED)) { @@ -523,9 +605,17 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im @Override public void performAction(final ConfiguredObject<?> child) { - if (child instanceof AbstractConfiguredObject) + if (child.getState() != State.ERRORED && child instanceof AbstractConfiguredObject) { - ((AbstractConfiguredObject) child).doOpening(false); + AbstractConfiguredObject configuredObject = (AbstractConfiguredObject) child; + try + { + configuredObject.doOpening(false, exceptionHandler); + } + catch (RuntimeException e) + { + exceptionHandler.handleException(e, configuredObject); + } } } }); @@ -533,7 +623,7 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im } } - protected final void doValidation(final boolean skipCheck) + protected final void doValidation(final boolean skipCheck, final AbstractConfiguredObjectExceptionHandler exceptionHandler) { if(skipCheck || _dynamicState.get() != DynamicState.OPENED) { @@ -542,9 +632,17 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im @Override public void performAction(final ConfiguredObject<?> child) { - if (child instanceof AbstractConfiguredObject) + if (child.getState() != State.ERRORED && child instanceof AbstractConfiguredObject) { - ((AbstractConfiguredObject) child).doValidation(false); + AbstractConfiguredObject configuredObject = (AbstractConfiguredObject) child; + try + { + configuredObject.doValidation(false, exceptionHandler); + } + catch (RuntimeException e) + { + exceptionHandler.handleException(e, configuredObject); + } } } }); @@ -552,20 +650,28 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im } } - protected final void doResolution(final boolean skipCheck) + protected final void doResolution(boolean skipCheck, final AbstractConfiguredObjectExceptionHandler exceptionHandler) { if(skipCheck || _dynamicState.get() != DynamicState.OPENED) { onResolve(); postResolve(); - applyToChildren(new Action<ConfiguredObject<?>>() + applyToChildren(new Action() { @Override - public void performAction(final ConfiguredObject<?> child) + public void performAction(Object child) { if (child instanceof AbstractConfiguredObject) { - ((AbstractConfiguredObject) child).doResolution(false); + AbstractConfiguredObject configuredObject = (AbstractConfiguredObject) child; + try + { + configuredObject.doResolution(false, exceptionHandler); + } + catch (RuntimeException e) + { + exceptionHandler.handleException(e, configuredObject); + } } } }); @@ -576,7 +682,7 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im { } - protected final void doCreation(final boolean skipCheck) + protected final void doCreation(final boolean skipCheck, final AbstractConfiguredObjectExceptionHandler exceptionHandler) { if(skipCheck || _dynamicState.get() != DynamicState.OPENED) { @@ -588,7 +694,15 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im { if (child instanceof AbstractConfiguredObject) { - ((AbstractConfiguredObject) child).doCreation(false); + AbstractConfiguredObject configuredObject =(AbstractConfiguredObject) child; + try + { + configuredObject.doCreation(false, exceptionHandler); + } + catch (RuntimeException e) + { + exceptionHandler.handleException(e, configuredObject); + } } } }); @@ -711,12 +825,16 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im } } - private void attainStateIfResolved() + private void attainStateIfOpenedOrReopenFailed() { - if(_openComplete) + if (_openComplete || getDesiredState() == State.DELETED) { attainState(); } + else if (_openFailed) + { + open(); + } } protected void onOpen() @@ -830,8 +948,13 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im State state = getState(); if(desiredState == getDesiredState() && desiredState != state) { - attainState(); - return getState(); + attainStateIfOpenedOrReopenFailed(); + final State currentState = getState(); + if (currentState != state) + { + notifyStateChanged(state, currentState); + } + return currentState; } else { @@ -1217,7 +1340,6 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im { if (_childrenByName.get(categoryClass).containsKey(name)) { - child.delete(); throw new DuplicateNameException(child); } _childrenByName.get(categoryClass).put(name, child); @@ -1756,4 +1878,54 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im return _name; } } + + interface AbstractConfiguredObjectExceptionHandler + { + void handleException(RuntimeException exception, AbstractConfiguredObject<?> source); + } + + private static class OpenExceptionHandler implements AbstractConfiguredObjectExceptionHandler + { + @Override + public void handleException(RuntimeException exception, AbstractConfiguredObject<?> source) + { + source.handleExceptionOnOpen(exception); + } + } + + private static class CreateExceptionHandler implements AbstractConfiguredObjectExceptionHandler + { + private final boolean _unregister; + + private CreateExceptionHandler() + { + this(false); + } + + private CreateExceptionHandler(boolean unregister) + { + _unregister = unregister; + } + + @Override + + public void handleException(RuntimeException exception, AbstractConfiguredObject<?> source) + { + try + { + if (source.getState() != State.DELETED) + { + source.delete(); + } + } + finally + { + if (_unregister) + { + source.unregister(false); + } + throw exception; + } + } + } } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java index 19f6139387..f8dac7cbe9 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java @@ -49,13 +49,15 @@ public abstract class AbstractSystemConfig<X extends SystemConfig<X>> private final EventLogger _eventLogger; private final LogRecorder _logRecorder; private final BrokerOptions _brokerOptions; + private final BrokerShutdownProvider _brokerShutdownProvider; private DurableConfigurationStore _configurationStore; public AbstractSystemConfig(final TaskExecutor taskExecutor, final EventLogger eventLogger, final LogRecorder logRecorder, - final BrokerOptions brokerOptions) + final BrokerOptions brokerOptions, + final BrokerShutdownProvider brokerShutdownProvider) { super(parentsMap(), updateAttributes(brokerOptions.convertToSystemAttributes()), @@ -64,6 +66,7 @@ public abstract class AbstractSystemConfig<X extends SystemConfig<X>> getTaskExecutor().start(); _logRecorder = logRecorder; _brokerOptions = brokerOptions; + _brokerShutdownProvider = brokerShutdownProvider; } private static Map<String, Object> updateAttributes(Map<String, Object> attributes) @@ -212,4 +215,9 @@ public abstract class AbstractSystemConfig<X extends SystemConfig<X>> } + @Override + public BrokerShutdownProvider getBrokerShutdownProvider() + { + return _brokerShutdownProvider; + } } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java new file mode 100644 index 0000000000..5c8ab3e850 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java @@ -0,0 +1,26 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +public interface BrokerShutdownProvider +{ + void shutdown(); +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java index 1763aca524..c9a828e7e4 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java @@ -38,9 +38,10 @@ public class JsonSystemConfigImpl extends AbstractSystemConfig<JsonSystemConfigI public JsonSystemConfigImpl(final TaskExecutor taskExecutor, final EventLogger eventLogger, final LogRecorder logRecorder, - final BrokerOptions brokerOptions) + final BrokerOptions brokerOptions, + final BrokerShutdownProvider brokerShutdownProvider) { - super(taskExecutor, eventLogger, logRecorder, brokerOptions); + super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider); } public String getStorePath() diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java index 7943c32c42..ec063142b4 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java @@ -37,4 +37,6 @@ public interface SystemConfig<X extends SystemConfig<X>> extends ConfiguredObjec LogRecorder getLogRecorder(); DurableConfigurationStore getConfigurationStore(); + + BrokerShutdownProvider getBrokerShutdownProvider(); } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java index 92ac43e629..109aaff5bd 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java @@ -943,6 +943,28 @@ public class BrokerAdapter extends AbstractConfiguredObject<BrokerAdapter> imple _eventLogger = eventLogger; } + @Override + protected void onExceptionInOpen(RuntimeException e) + { + SystemConfig systemConfig = getParent(SystemConfig.class); + if (systemConfig != null) + { + BrokerShutdownProvider shutdownProvider = systemConfig.getBrokerShutdownProvider(); + if (shutdownProvider != null) + { + shutdownProvider.shutdown(); + } + else + { + throw new IllegalStateException("Shutdown provider is not found in system config"); + } + } + else + { + throw new IllegalStateException("SystemConfig is not found among broker parents"); + } + } + public void registerMessageDelivered(long messageSize) { _messagesDelivered.registerEvent(1L); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java index c96f4c0849..1b3d0591c0 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java @@ -114,22 +114,27 @@ public class FileBasedGroupProviderImpl throw new IllegalArgumentException("Cannot change the path"); } } + + @Override protected void onOpen() { super.onOpen(); - if(_groupDatabase == null) + FileGroupDatabase groupDatabase = new FileGroupDatabase(); + try { - _groupDatabase = new FileGroupDatabase(); - try - { - _groupDatabase.setGroupFile(getPath()); - } - catch (IOException e) + groupDatabase.setGroupFile(getPath()); + } + catch(IOException | RuntimeException e) + { + if (e instanceof IllegalConfigurationException) { - setState(State.ERRORED); - LOGGER.warn(("Unable to open preferences file at " + _path)); + throw (IllegalConfigurationException) e; } + throw new IllegalConfigurationException(String.format("Cannot load groups from '%s'", getPath()), e); } + + _groupDatabase = groupDatabase; + Set<Principal> groups = getGroupPrincipals(); Collection<Group> principals = new ArrayList<Group>(groups.size()); for (Principal group : groups) @@ -150,43 +155,47 @@ public class FileBasedGroupProviderImpl protected void onCreate() { super.onCreate(); - _groupDatabase = new FileGroupDatabase(); - File file = new File(_path); if (!file.exists()) { File parent = file.getParentFile(); - if (!parent.exists()) + if (!parent.exists() && !file.getParentFile().mkdirs()) { - parent.mkdirs(); + throw new IllegalConfigurationException(String.format("Cannot create groups file at '%s'",_path)); } - if (parent.exists()) + try { - try - { - file.createNewFile(); - } - catch (IOException e) - { - throw new IllegalConfigurationException("Cannot create group file"); - } + file.createNewFile(); } - else + catch (IOException e) { - throw new IllegalConfigurationException("Cannot create group file"); + throw new IllegalConfigurationException(String.format("Cannot create groups file at '%s'", _path), e); } } - try - { - _groupDatabase.setGroupFile(getPath()); - } - catch (IOException e) - { - setState(State.ERRORED); - LOGGER.warn(("Unable to open preferences file at " + _path)); - } + } + @Override + protected void validateOnCreate() + { + super.validateOnCreate(); + File groupsFile = new File(_path); + if (groupsFile.exists()) + { + if (!groupsFile.canRead()) + { + throw new IllegalConfigurationException(String.format("Cannot read groups file '%s'. Please check permissions.", _path)); + } + FileGroupDatabase groupDatabase = new FileGroupDatabase(); + try + { + groupDatabase.setGroupFile(_path); + } + catch (Exception e) + { + throw new IllegalConfigurationException(String.format("Cannot load groups from '%s'", _path), e); + } + } } @Override @@ -205,6 +214,11 @@ public class FileBasedGroupProviderImpl getSecurityManager().authoriseGroupOperation(Operation.CREATE, groupName); + if (getState() != State.ACTIVE) + { + throw new IllegalConfigurationException(String.format("Group provider '%s' is not activated. Cannot create a group.", getName())); + } + _groupDatabase.createGroup(groupName); Map<String,Object> attrMap = new HashMap<String, Object>(); @@ -247,20 +261,22 @@ public class FileBasedGroupProviderImpl return _broker.getSecurityManager(); } - @StateTransition( currentState = { State.UNINITIALIZED, State.QUIESCED }, desiredState = State.ACTIVE ) + @StateTransition( currentState = { State.UNINITIALIZED, State.QUIESCED, State.ERRORED }, desiredState = State.ACTIVE ) private void activate() { - try + if (_groupDatabase != null) { - _groupDatabase.setGroupFile(getPath()); setState(State.ACTIVE); } - catch(IOException | RuntimeException e) + else { - setState(State.ERRORED); if (_broker.isManagementMode()) { - LOGGER.warn("Failed to activate group provider: " + getName(), e); + LOGGER.warn("Failed to activate group provider: " + getName()); + } + else + { + throw new IllegalConfigurationException(String.format("Cannot load groups from '%s'", getPath())); } } } @@ -268,6 +284,7 @@ public class FileBasedGroupProviderImpl @StateTransition( currentState = { State.QUIESCED, State.ACTIVE, State.ERRORED}, desiredState = State.DELETED ) private void doDelete() { + close(); File file = new File(getPath()); if (file.exists()) { @@ -289,7 +306,7 @@ public class FileBasedGroupProviderImpl public Set<Principal> getGroupPrincipalsForUser(String username) { - Set<String> groups = _groupDatabase.getGroupsForUser(username); + Set<String> groups = _groupDatabase == null ? Collections.<String>emptySet(): _groupDatabase.getGroupsForUser(username); if (groups.isEmpty()) { return Collections.emptySet(); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java index f2be4fd861..e3ded3006d 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java @@ -76,20 +76,64 @@ public class FileSystemPreferencesProviderImpl _authenticationProvider = authenticationProvider; } - @StateTransition( currentState = State.UNINITIALIZED, desiredState = State.ACTIVE ) + @Override + protected void validateOnCreate() + { + super.validateOnCreate(); + File storeFile = new File(_path); + if (storeFile.exists() ) + { + if (!storeFile.canRead()) + { + throw new IllegalConfigurationException(String.format("Cannot read preferences file '%s'. Please check permissions.", _path)); + } + + FileSystemPreferencesStore store = null; + try + { + store = new FileSystemPreferencesStore(storeFile); + store.open(); + } + catch (RuntimeException e) + { + if (e instanceof IllegalConfigurationException) + { + throw e; + } + throw new IllegalConfigurationException(String.format("Cannot open preferences store at '%s'", _path), e); + } + finally + { + if (store != null) + { + store.close(); + } + } + } + } + + @Override + protected void onOpen() + { + FileSystemPreferencesStore store = new FileSystemPreferencesStore(new File(_path)); + + // we need to check and create file if it does not exist every time on open + store.createIfNotExist(); + store.open(); + _store = store; + _open = true; + } + + @StateTransition( currentState = {State.UNINITIALIZED, State.ERRORED}, desiredState = State.ACTIVE ) private void activate() { - try + if (_store != null) { - _store = new FileSystemPreferencesStore(new File(_path)); - createStoreIfNotExist(); - _store.open(); - _open = true; setState(State.ACTIVE); } - catch( RuntimeException e ) + else { - setState(State.ERRORED); + throw new IllegalStateException("Cannot open preferences provider " + getName() + " in state " + getState() ); } } @@ -148,9 +192,14 @@ public class FileSystemPreferencesProviderImpl setState(State.DELETED); } - @StateTransition(currentState = { State.QUIESCED, State.ERRORED }, desiredState = State.ACTIVE ) + @StateTransition(currentState = State.QUIESCED, desiredState = State.ACTIVE ) private void restart() { + if (_store == null) + { + throw new IllegalStateException("Cannot open preferences provider " + getName() + " in state " + getState() ); + } + _store.open(); setState(State.ACTIVE); } @@ -158,24 +207,39 @@ public class FileSystemPreferencesProviderImpl @Override public Map<String, Object> getPreferences(String userId) { - return _store.getPreferences(userId); + return _store == null? Collections.<String, Object>emptyMap() : _store.getPreferences(userId); } @Override public Map<String, Object> setPreferences(String userId, Map<String, Object> preferences) { + if (_store == null) + { + throw new IllegalStateException("Cannot set preferences with preferences provider " + getName() + " in state " + getState() ); + } + return _store.setPreferences(userId, preferences); } @Override public String[] deletePreferences(String... userIDs) { + if (_store == null) + { + throw new IllegalStateException("Cannot delete preferences with preferences provider " + getName() + " in state " + getState() ); + } + return _store.deletePreferences(userIDs); } @Override public Set<String> listUserIDs() { + if (_store == null) + { + return Collections.emptySet(); + } + return _store.listUserIDs(); } @@ -215,9 +279,10 @@ public class FileSystemPreferencesProviderImpl } else { - _store = new FileSystemPreferencesStore(new File(_path)); - createStoreIfNotExist(); - _store.open(); + FileSystemPreferencesStore store = new FileSystemPreferencesStore(new File(_path)); + store.createIfNotExist(); + store.open(); + _store = store; } } } @@ -265,11 +330,6 @@ public class FileSystemPreferencesProviderImpl } - private void createStoreIfNotExist() - { - _store.createIfNotExist(); - } - public static class FileSystemPreferencesStore { private final ObjectMapper _objectMapper; @@ -294,18 +354,18 @@ public class FileSystemPreferencesProviderImpl File parent = _storeFile.getParentFile(); if (!parent.exists() && !parent.mkdirs()) { - throw new IllegalConfigurationException("Cannot create preferences store folders"); + throw new IllegalConfigurationException(String.format("Cannot create preferences store folder at '%s'", _storeFile.getAbsolutePath())); } try { if (_storeFile.createNewFile() && !_storeFile.exists()) { - throw new IllegalConfigurationException("Preferences store file was not created:" + _storeFile.getAbsolutePath()); + throw new IllegalConfigurationException(String.format("Cannot create preferences store file at '%s'", _storeFile.getAbsolutePath())); } } catch (IOException e) { - throw new IllegalConfigurationException("Cannot create preferences store file"); + throw new IllegalConfigurationException(String.format("Cannot create preferences store file at '%s'", _storeFile.getAbsolutePath()), e); } } } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java index c0aa99a7d6..e2e7eff322 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java @@ -317,7 +317,7 @@ abstract public class AbstractPort<X extends AbstractPort<X>> extends AbstractCo setState(State.DELETED); } - @StateTransition( currentState = {State.UNINITIALIZED, State.QUIESCED}, desiredState = State.ACTIVE ) + @StateTransition( currentState = {State.UNINITIALIZED, State.QUIESCED, State.ERRORED}, desiredState = State.ACTIVE ) protected void activate() { try @@ -327,8 +327,7 @@ abstract public class AbstractPort<X extends AbstractPort<X>> extends AbstractCo catch (RuntimeException e) { setState(State.ERRORED); - LOGGER.error("Unable to active port '" + getName() + "'of type " + getType() + " on port " + getPort(), - e); + throw new IllegalConfigurationException("Unable to active port '" + getName() + "'of type " + getType() + " on " + getPort(), e); } } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java index fe7d419c78..afe3c9a44e 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java @@ -34,6 +34,7 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; +import org.apache.qpid.server.util.PortUtil; import org.codehaus.jackson.map.ObjectMapper; import org.apache.qpid.server.configuration.BrokerProperties; @@ -187,6 +188,18 @@ public class AmqpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider< } } + @Override + public void validateOnCreate() + { + super.validateOnCreate(); + String bindingAddress = getBindingAddress(); + if (!PortUtil.isPortAvailable(bindingAddress, getPort())) + { + throw new IllegalConfigurationException(String.format("Cannot bind to port %d and binding address '%s'. Port is already is use.", + getPort(), bindingAddress == null || "".equals(bindingAddress) ? "*" : bindingAddress)); + } + } + private SSLContext createSslContext() { KeyStore keyStore = getKeyStore(); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java index 1774f16ab6..3be5854645 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java @@ -22,10 +22,12 @@ package org.apache.qpid.server.model.port; import java.util.Map; +import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ManagedAttributeField; import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; import org.apache.qpid.server.model.State; +import org.apache.qpid.server.util.PortUtil; public class HttpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider<HttpPortImpl> implements HttpPort<HttpPortImpl> { @@ -65,4 +67,16 @@ public class HttpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider< return State.QUIESCED; } } + + @Override + public void validateOnCreate() + { + super.validateOnCreate(); + String bindingAddress = getBindingAddress(); + if (!PortUtil.isPortAvailable(bindingAddress, getPort())) + { + throw new IllegalConfigurationException(String.format("Cannot bind to port %d and binding address '%s'. Port is already is use.", + getPort(), bindingAddress == null || "".equals(bindingAddress) ? "*" : bindingAddress)); + } + } } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java b/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java index 9162f9e095..885194d939 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java @@ -24,6 +24,7 @@ import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.LogRecorder; +import org.apache.qpid.server.model.BrokerShutdownProvider; import org.apache.qpid.server.model.SystemConfig; public interface SystemConfigFactory<X extends SystemConfig<X>> extends Pluggable @@ -31,5 +32,6 @@ public interface SystemConfigFactory<X extends SystemConfig<X>> extends Pluggabl public X newInstance(final TaskExecutor taskExecutor, final EventLogger eventLogger, final LogRecorder logRecorder, - final BrokerOptions brokerOptions); + final BrokerOptions brokerOptions, + final BrokerShutdownProvider brokerShutdownProvider); } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java b/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java index a5156c9073..53e446ba2d 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java @@ -254,6 +254,12 @@ public abstract class AbstractQueue<X extends AbstractQueue<X>> } @Override + protected void validateOnCreate() + { + _virtualHost.getSecurityManager().authoriseCreateQueue(this); + } + + @Override protected void onCreate() { super.onCreate(); @@ -304,6 +310,7 @@ public abstract class AbstractQueue<X extends AbstractQueue<X>> } } + @Override protected void onOpen() { super.onOpen(); @@ -319,17 +326,6 @@ public abstract class AbstractQueue<X extends AbstractQueue<X>> _logSubject = new QueueLogSubject(this); - try - { - - _virtualHost.getSecurityManager().authoriseCreateQueue(this); - } - catch(AccessControlException e) - { - deleted(); - throw e; - } - Subject activeSubject = Subject.getSubject(AccessController.getContext()); Set<SessionPrincipal> sessionPrincipals = activeSubject == null ? Collections.<SessionPrincipal>emptySet() : activeSubject.getPrincipals(SessionPrincipal.class); AMQSessionModel<?,?> sessionModel; @@ -2798,7 +2794,7 @@ public abstract class AbstractQueue<X extends AbstractQueue<X>> //============= - @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE) + @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE) private void activate() { setState(State.ACTIVE); @@ -2965,7 +2961,10 @@ public abstract class AbstractQueue<X extends AbstractQueue<X>> { throw new IllegalConfigurationException("Flow resume size can't be greater than flow control size"); } - + else if (changedAttributes.contains(DURABLE) && proxyForValidation.isDurable() != isDurable()) + { + throw new IllegalConfigurationException("Message durability cannot be modified after queue creation"); + } for (String attrName : NON_NEGATIVE_NUMBERS) { diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java index a6a2ea8d34..192a096d12 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java @@ -76,25 +76,32 @@ public abstract class PrincipalDatabaseAuthenticationManager<T extends Principal } @Override + protected void validateOnCreate() + { + super.validateOnCreate(); + File passwordFile = new File(_path); + if (passwordFile.exists() && !passwordFile.canRead()) + { + throw new IllegalConfigurationException(String.format("Cannot read password file '%s'. Please check permissions.", _path)); + } + } + + @Override protected void onCreate() { super.onCreate(); - try + File passwordFile = new File(_path); + if (!passwordFile.exists()) { - File passwordFile = new File(_path); - if (!passwordFile.exists()) + try { passwordFile.createNewFile(); } - else if (!passwordFile.canRead()) + catch (IOException e) { - throw new IllegalConfigurationException("Cannot read password file" + _path + ". Check permissions."); + throw new IllegalConfigurationException(String.format("Cannot create password file at '%s'", _path), e); } } - catch (IOException e) - { - throw new IllegalConfigurationException("Cannot use password database at :" + _path, e); - } } @Override @@ -102,23 +109,14 @@ public abstract class PrincipalDatabaseAuthenticationManager<T extends Principal { super.onOpen(); _principalDatabase = createDatabase(); - try + initialise(); + List<Principal> users = _principalDatabase == null ? Collections.<Principal>emptyList() : _principalDatabase.getUsers(); + for (Principal user : users) { - initialise(); - List<Principal> users = - _principalDatabase == null ? Collections.<Principal>emptyList() : _principalDatabase.getUsers(); - for (Principal user : users) - { - PrincipalAdapter principalAdapter = new PrincipalAdapter(user); - principalAdapter.registerWithParents(); - principalAdapter.open(); - _userMap.put(user, principalAdapter); - } - } - catch(IllegalConfigurationException e) - { - setState(State.ERRORED); - + PrincipalAdapter principalAdapter = new PrincipalAdapter(user); + principalAdapter.registerWithParents(); + principalAdapter.open(); + _userMap.put(user, principalAdapter); } } @@ -457,7 +455,7 @@ public abstract class PrincipalDatabaseAuthenticationManager<T extends Principal return super.changeAttribute(name, expected, desired); } - @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE) + @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE) private void activate() { setState(State.ACTIVE); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java index 4e285df384..260fdfd1c6 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java @@ -22,6 +22,7 @@ package org.apache.qpid.server.security.auth.manager; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.ManagedAttribute; +import org.apache.qpid.server.model.ManagedContextDefault; import org.apache.qpid.server.model.ManagedObject; import org.apache.qpid.server.model.TrustStore; @@ -29,24 +30,34 @@ import org.apache.qpid.server.model.TrustStore; public interface SimpleLDAPAuthenticationManager<X extends SimpleLDAPAuthenticationManager<X>> extends AuthenticationProvider<X> { String PROVIDER_TYPE = "SimpleLDAP"; + String PROVIDER_URL = "providerUrl"; + String PROVIDER_AUTH_URL = "providerAuthUrl"; + String SEARCH_CONTEXT = "searchContext"; + String LDAP_CONTEXT_FACTORY = "ldapContextFactory"; + String SEARCH_USERNAME = "getSearchUsername"; + String SEARCH_PASSWORD = "getSearchPassword"; String TRUST_STORE = "trustStore"; - @ManagedAttribute( description = "LDAP server URL" ) + + @ManagedAttribute( description = "LDAP server URL", mandatory = true) String getProviderUrl(); @ManagedAttribute( description = "LDAP authentication URL") String getProviderAuthUrl(); - @ManagedAttribute( description = "Search context") + @ManagedAttribute( description = "Search context", mandatory = true) String getSearchContext(); - @ManagedAttribute( description = "Search filter") + @ManagedAttribute( description = "Search filter", mandatory = true) String getSearchFilter(); @ManagedAttribute( description = "Bind without search") boolean isBindWithoutSearch(); - @ManagedAttribute( description = "LDAP context factory") + @ManagedContextDefault( name = "ldap.context.factory") + String DEFAULT_LDAP_CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory"; + + @ManagedAttribute( description = "LDAP context factory", defaultValue = "${ldap.context.factory}") String getLdapContextFactory(); @ManagedAttribute( description = "Trust store name") diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java index a0ba4518c8..6a0b83eb94 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java @@ -19,15 +19,18 @@ package org.apache.qpid.server.security.auth.manager; +import static java.util.Collections.disjoint; +import static java.util.Collections.unmodifiableList; +import static java.util.Collections.singletonList; + import java.io.IOException; import java.security.GeneralSecurityException; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; import java.security.Principal; -import java.util.Collections; +import java.util.Arrays; import java.util.Hashtable; import java.util.List; import java.util.Map; +import java.util.Set; import javax.naming.AuthenticationException; import javax.naming.Context; @@ -48,7 +51,9 @@ import javax.security.sasl.SaslServer; import org.apache.log4j.Logger; +import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.ManagedAttributeField; import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; import org.apache.qpid.server.model.TrustStore; @@ -59,7 +64,6 @@ import org.apache.qpid.server.security.auth.manager.ldap.AbstractLDAPSSLSocketFa import org.apache.qpid.server.security.auth.manager.ldap.LDAPSSLSocketFactoryGenerator; import org.apache.qpid.server.security.auth.sasl.plain.PlainPasswordCallback; import org.apache.qpid.server.security.auth.sasl.plain.PlainSaslServer; -import org.apache.qpid.server.util.ServerScopedRuntimeException; import org.apache.qpid.server.util.StringUtil; import org.apache.qpid.ssl.SSLContextFactory; @@ -68,6 +72,14 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM { private static final Logger _logger = Logger.getLogger(SimpleLDAPAuthenticationManagerImpl.class); + private static final List<String> CONNECTIVITY_ATTRS = unmodifiableList(Arrays.asList(PROVIDER_URL, + PROVIDER_AUTH_URL, + SEARCH_CONTEXT, + LDAP_CONTEXT_FACTORY, + SEARCH_USERNAME, + SEARCH_PASSWORD, + TRUST_STORE)); + /** * Environment key to instruct {@link InitialDirContext} to override the socket factory. */ @@ -111,15 +123,37 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM super(attributes, broker); } + @Override + protected void validateOnCreate() + { + super.validateOnCreate(); + + Class<? extends SocketFactory> sslSocketFactoryOverrideClass = _trustStore == null ? null : createSslSocketFactoryOverrideClass(_trustStore); + validateInitialDirContext(sslSocketFactoryOverrideClass, _providerUrl, _searchUsername, _searchPassword); + } + + @Override + protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes) + { + super.validateChange(proxyForValidation, changedAttributes); + + if (!disjoint(changedAttributes, CONNECTIVITY_ATTRS)) + { + SimpleLDAPAuthenticationManager changed = (SimpleLDAPAuthenticationManager)proxyForValidation; + TrustStore changedTruststore = changed.getTrustStore(); + Class<? extends SocketFactory> sslSocketFactoryOverrideClass = changedTruststore == null ? null : createSslSocketFactoryOverrideClass( + changedTruststore); + validateInitialDirContext(sslSocketFactoryOverrideClass, changed.getProviderUrl(), changed.getSearchUsername(), + changed.getSearchPassword()); + } + } @Override protected void onOpen() { super.onOpen(); - _sslSocketFactoryOverrideClass = createSslSocketFactoryOverrideClass(); - - // validateInitialDirContext(); + _sslSocketFactoryOverrideClass = _trustStore == null ? null : createSslSocketFactoryOverrideClass(_trustStore); } @Override @@ -174,7 +208,7 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM @Override public List<String> getMechanisms() { - return Collections.singletonList(PlainSaslServer.MECHANISM); + return singletonList(PlainSaslServer.MECHANISM); } @Override @@ -259,7 +293,7 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM InitialDirContext ctx = null; try { - ctx = createInitialDirContext(env); + ctx = createInitialDirContext(env, _sslSocketFactoryOverrideClass); //Authentication succeeded return new AuthenticationResult(new UsernamePrincipal(name)); @@ -291,7 +325,8 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM return env; } - private InitialDirContext createInitialDirContext(Hashtable<String, Object> env) throws NamingException + private InitialDirContext createInitialDirContext(Hashtable<String, Object> env, + Class<? extends SocketFactory> sslSocketFactoryOverrideClass) throws NamingException { ClassLoader existingContextClassLoader = null; @@ -300,11 +335,11 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM boolean revertContentClassLoader = false; try { - if (isLdaps && _sslSocketFactoryOverrideClass != null) + if (isLdaps && sslSocketFactoryOverrideClass != null) { existingContextClassLoader = Thread.currentThread().getContextClassLoader(); - env.put(JAVA_NAMING_LDAP_FACTORY_SOCKET, _sslSocketFactoryOverrideClass.getName()); - Thread.currentThread().setContextClassLoader(_sslSocketFactoryOverrideClass.getClassLoader()); + env.put(JAVA_NAMING_LDAP_FACTORY_SOCKET, sslSocketFactoryOverrideClass.getName()); + Thread.currentThread().setContextClassLoader(sslSocketFactoryOverrideClass.getClassLoader()); revertContentClassLoader = true; } return new InitialDirContext(env); @@ -323,59 +358,59 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM * associated with the {@link SSLContext} generated from that trust store. * * @return generated socket factory class + * @param trustStore */ - private Class<? extends SocketFactory> createSslSocketFactoryOverrideClass() + private Class<? extends SocketFactory> createSslSocketFactoryOverrideClass(final TrustStore trustStore) { - if (_trustStore != null) + String clazzName = new StringUtil().createUniqueJavaName(getName() + "_" + trustStore.getName()); + SSLContext sslContext = null; + try { - String clazzName = new StringUtil().createUniqueJavaName(getName()); - SSLContext sslContext = null; - try - { - sslContext = SSLContext.getInstance("TLS"); - sslContext.init(null, _trustStore.getTrustManagers(), null); - } - catch (NoSuchAlgorithmException e) - { - _logger.error("Exception creating SSLContext", e); - throw new ServerScopedRuntimeException("Error creating SSLContext for trust store : " + _trustStore.getName() , e); - } - catch (KeyManagementException e) - { - _logger.error("Exception creating SSLContext", e); - throw new ServerScopedRuntimeException("Error creating SSLContext for trust store : " + _trustStore.getName() , e); - } - catch (GeneralSecurityException e) - { - _logger.error("Exception creating SSLContext", e); - throw new ServerScopedRuntimeException("Error creating SSLContext for trust store : " + _trustStore.getName() , e); - } + sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, trustStore.getTrustManagers(), null); + } + catch (GeneralSecurityException e) + { + _logger.error("Exception creating SSLContext", e); + throw new IllegalConfigurationException("Error creating SSLContext with trust store : " + trustStore.getName() , e); + } - Class<? extends AbstractLDAPSSLSocketFactory> clazz = LDAPSSLSocketFactoryGenerator.createSubClass(clazzName, sslContext.getSocketFactory()); - if (_logger.isDebugEnabled()) - { - _logger.debug("Connection to Directory will use custom SSL socket factory : " + clazz); - } - return clazz; + Class<? extends AbstractLDAPSSLSocketFactory> clazz = LDAPSSLSocketFactoryGenerator.createSubClass(clazzName, sslContext.getSocketFactory()); + if (_logger.isDebugEnabled()) + { + _logger.debug("Connection to Directory will use custom SSL socket factory : " + clazz); } + return clazz; + } - return null; + @Override + public String toString() + { + return "SimpleLDAPAuthenticationManagerImpl [id=" + getId() + ", name=" + getName() + + ", providerUrl=" + _providerUrl + ", providerAuthUrl=" + _providerAuthUrl + + ", searchContext=" + _searchContext + ", state=" + getState() + + ", searchFilter=" + _searchFilter + ", ldapContextFactory=" + _ldapContextFactory + + ", bindWithoutSearch=" + _bindWithoutSearch + ", trustStore=" + _trustStore + + ", searchUsername=" + _searchUsername + "]"; } - private void validateInitialDirContext() + private void validateInitialDirContext(Class<? extends SocketFactory> sslSocketFactoryOverrideClass, + final String providerUrl, + final String searchUsername, final String searchPassword) { - Hashtable<String,Object> env = createInitialDirContextEnvironment(_providerUrl); + Hashtable<String,Object> env = createInitialDirContextEnvironment(providerUrl); - setupSearchContext(env); + setupSearchContext(env, searchUsername, searchPassword); InitialDirContext ctx = null; try { - ctx = createInitialDirContext(env); + ctx = createInitialDirContext(env, sslSocketFactoryOverrideClass); } catch (NamingException e) { - throw new ServerScopedRuntimeException("Unable to establish connection to the ldap server at " + _providerUrl, e); + _logger.error("Failed to establish connectivity to the ldap server for " + providerUrl, e); + throw new IllegalConfigurationException("Failed to establish connectivity to the ldap server." , e); } finally { @@ -383,13 +418,14 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM } } - private void setupSearchContext(final Hashtable<String, Object> env) + private void setupSearchContext(final Hashtable<String, Object> env, + final String searchUsername, final String searchPassword) { if(_searchUsername != null && _searchUsername.trim().length()>0) { env.put(Context.SECURITY_AUTHENTICATION, "simple"); - env.put(Context.SECURITY_PRINCIPAL, _searchUsername); - env.put(Context.SECURITY_CREDENTIALS, _searchPassword); + env.put(Context.SECURITY_PRINCIPAL, searchUsername); + env.put(Context.SECURITY_CREDENTIALS, searchPassword); } else { @@ -454,9 +490,9 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM { Hashtable<String, Object> env = createInitialDirContextEnvironment(_providerUrl); - setupSearchContext(env); + setupSearchContext(env, _searchUsername, _searchPassword); - InitialDirContext ctx = createInitialDirContext(env); + InitialDirContext ctx = createInitialDirContext(env, _sslSocketFactoryOverrideClass); try { diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCConfigurationStore.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCConfigurationStore.java index 52072678e8..4fbfdfdd2d 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCConfigurationStore.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCConfigurationStore.java @@ -572,7 +572,7 @@ public abstract class AbstractJDBCConfigurationStore implements MessageStoreProv } catch (SQLException e) { - throw new StoreException("Error creating ConfiguredObject " + object); + throw new StoreException("Error creating ConfiguredObject " + object, e); } } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java index 9633e32408..4dfaa716cf 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java @@ -133,7 +133,7 @@ public abstract class AbstractJDBCMessageStore implements MessageStore } catch (SQLException e) { - throw new StoreException(e); + throw new StoreException("Failed to determine maximum ids", e); } } @@ -816,7 +816,6 @@ public abstract class AbstractJDBCMessageStore implements MessageStore private void commitTran(ConnectionWrapper connWrapper) throws StoreException { - try { Connection conn = connWrapper.getConnection(); @@ -833,10 +832,6 @@ public abstract class AbstractJDBCMessageStore implements MessageStore { throw new StoreException("Error commit tx: " + e.getMessage(), e); } - finally - { - - } } private StoreFuture commitTranAsync(ConnectionWrapper connWrapper) throws StoreException @@ -1448,7 +1443,7 @@ public abstract class AbstractJDBCMessageStore implements MessageStore } catch (SQLException e) { - throw new StoreException(e); + throw new StoreException("Failed to get metadata for message id: " + _messageId, e); } } @@ -1507,7 +1502,7 @@ public abstract class AbstractJDBCMessageStore implements MessageStore } catch (SQLException e) { - throw new StoreException(e); + throw new StoreException("Failed to get content for message id " + _messageId, e); } } else @@ -1551,7 +1546,7 @@ public abstract class AbstractJDBCMessageStore implements MessageStore } catch (SQLException e) { - throw new StoreException(e); + throw new StoreException("Failed to get content for message id: " + _messageId, e); } } else @@ -1598,11 +1593,7 @@ public abstract class AbstractJDBCMessageStore implements MessageStore } catch (SQLException e) { - throw new StoreException(e); - } - finally - { - + throw new StoreException("Failed to flow to disk", e); } return true; } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/util/PortUtil.java b/java/broker-core/src/main/java/org/apache/qpid/server/util/PortUtil.java new file mode 100644 index 0000000000..5d093bd3d5 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/util/PortUtil.java @@ -0,0 +1,69 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.util; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.ServerSocket; + +public class PortUtil +{ + public static boolean isPortAvailable(String hostName, int port) + { + InetSocketAddress socketAddress = null; + if ( hostName == null || "".equals(hostName) || "*".equals(hostName) ) + { + socketAddress = new InetSocketAddress(port); + } + else + { + socketAddress = new InetSocketAddress(hostName, port); + } + + ServerSocket serverSocket = null; + try + { + serverSocket = new ServerSocket(); + serverSocket.setReuseAddress(true); + serverSocket.bind(socketAddress); + return true; + } + catch (IOException e) + { + return false; + } + finally + { + if (serverSocket != null) + { + try + { + serverSocket.close(); + } + catch (IOException e) + { + throw new RuntimeException("Couldn't close port " + port + " that was created to check its availability", e); + } + } + } + } +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java index f52c1967f8..48077ba503 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java @@ -37,7 +37,6 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; import javax.security.auth.Subject; @@ -231,6 +230,47 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte } @Override + public void validateOnCreate() + { + super.validateOnCreate(); + validateMessageStoreCreation(); + } + + private void validateMessageStoreCreation() + { + MessageStore store = createMessageStore(); + if (store != null) + { + try + { + store.openMessageStore(this); + } + catch (Exception e) + { + throw new IllegalConfigurationException("Cannot open virtual host message store:" + e.getMessage(), e); + } + finally + { + try + { + store.closeMessageStore(); + } + catch(Exception e) + { + _logger.warn("Failed to close database", e); + } + } + } + } + + @Override + protected void onExceptionInOpen(RuntimeException e) + { + super.onExceptionInOpen(e); + closeMessageStore(); + } + + @Override protected void onOpen() { super.onOpen(); @@ -638,6 +678,7 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte protected void onClose() { + setState(State.UNAVAILABLE); //Stop Connections _connectionRegistry.close(); _dtxRegistry.close(); @@ -659,11 +700,11 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte { _logger.error("Failed to close message store", e); } - } - if (!(_virtualHostNode.getConfigurationStore() instanceof MessageStoreProvider)) - { - getEventLogger().message(getMessageStoreLogSubject(), MessageStoreMessages.CLOSED()); + if (!(_virtualHostNode.getConfigurationStore() instanceof MessageStoreProvider)) + { + getEventLogger().message(getMessageStoreLogSubject(), MessageStoreMessages.CLOSED()); + } } } @@ -1355,7 +1396,7 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte getDurableConfigurationStore().create(new ConfiguredObjectRecordImpl(record.getId(), record.getType(), record.getAttributes())); } - @StateTransition( currentState = { State.UNINITIALIZED }, desiredState = State.ACTIVE ) + @StateTransition( currentState = { State.UNINITIALIZED,State.ERRORED }, desiredState = State.ACTIVE ) private void onActivate() { _houseKeepingTasks = new ScheduledThreadPoolExecutor(getHousekeepingThreadCount()); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java index ce97502124..03c30a9cd4 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java @@ -41,6 +41,7 @@ import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.store.ConfiguredObjectRecord; import org.apache.qpid.server.store.ConfiguredObjectRecordImpl; +import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.VirtualHostStoreUpgraderAndRecoverer; public abstract class AbstractStandardVirtualHostNode<X extends AbstractStandardVirtualHostNode<X>> extends AbstractVirtualHostNode<X> @@ -169,4 +170,33 @@ public abstract class AbstractStandardVirtualHostNode<X extends AbstractStandard { return Collections.emptyList(); } + + @Override + public void validateOnCreate() + { + super.validateOnCreate(); + DurableConfigurationStore store = createConfigurationStore(); + if (store != null) + { + try + { + store.openConfigurationStore(this, false); + } + catch (Exception e) + { + throw new IllegalConfigurationException("Cannot open node configuration store:" + e.getMessage(), e); + } + finally + { + try + { + store.closeConfigurationStore(); + } + catch(Exception e) + { + LOGGER.warn("Failed to close database", e); + } + } + } + } } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java index 5cbfb0942a..aea07e3ed3 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java @@ -36,7 +36,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; -import java.util.concurrent.atomic.AtomicReference; import org.apache.log4j.Logger; @@ -100,8 +99,6 @@ public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode< { super.onOpen(); _durableConfigurationStore = createConfigurationStore(); - _configurationStoreLogSubject = new MessageStoreLogSubject(getName(), _durableConfigurationStore.getClass().getSimpleName()); - } @Override @@ -167,11 +164,6 @@ public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode< return _eventLogger; } - protected DurableConfigurationStore getDurableConfigurationStore() - { - return _durableConfigurationStore; - } - protected MessageStoreLogSubject getConfigurationStoreLogSubject() { return _configurationStoreLogSubject; @@ -184,7 +176,11 @@ public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode< deleteVirtualHostIfExists(); close(); deleted(); - getConfigurationStore().onDelete(this); + DurableConfigurationStore configurationStore = getConfigurationStore(); + if (configurationStore != null) + { + configurationStore.onDelete(this); + } } protected void deleteVirtualHostIfExists() @@ -205,11 +201,30 @@ public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode< protected void stopAndSetStateTo(State stoppedState) { closeChildren(); - closeConfigurationStore(); + closeConfigurationStoreSafely(); setState(stoppedState); } @Override + protected void onExceptionInOpen(RuntimeException e) + { + super.onExceptionInOpen(e); + closeConfigurationStoreSafely(); + } + + @Override + protected void postResolve() + { + super.postResolve(); + DurableConfigurationStore store = getConfigurationStore(); + if (store == null) + { + store = createConfigurationStore(); + } + _configurationStoreLogSubject = new MessageStoreLogSubject(getName(), store.getClass().getSimpleName()); + } + + @Override protected void onClose() { closeConfigurationStore(); @@ -262,6 +277,18 @@ public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode< } } + private void closeConfigurationStoreSafely() + { + try + { + closeConfigurationStore(); + } + catch(Exception e) + { + LOGGER.warn("Unexpected exception on close of configuration store", e); + } + } + @Override public String getVirtualHostInitialConfiguration() { |