Merge from trunk
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/QPID-6262-JavaBrokerNIO@1655057 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/qpid/cpp/examples/messaging/client.cpp b/qpid/cpp/examples/messaging/client.cpp
index 983f0a8..44720ef 100644
--- a/qpid/cpp/examples/messaging/client.cpp
+++ b/qpid/cpp/examples/messaging/client.cpp
@@ -7,9 +7,9 @@
* 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
@@ -39,7 +39,7 @@
int main(int argc, char** argv) {
const char* url = argc>1 ? argv[1] : "amqp:tcp:127.0.0.1:5672";
std::string connectionOptions = argc > 2 ? argv[2] : "";
-
+
Connection connection(url, connectionOptions);
try {
connection.open();
@@ -62,10 +62,11 @@
Message request;
request.setReplyTo(responseQueue);
for (int i=0; i<4; i++) {
- request.setContent(s[i]);
+ request.setContentObject(s[i]);
sender.send(request);
Message response = receiver.fetch();
- std::cout << request.getContent() << " -> " << response.getContent() << std::endl;
+ std::cout << request.getContentObject() << " -> " << response.getContentObject() << std::endl;
+ session.acknowledge(response);
}
connection.close();
return 0;
diff --git a/qpid/cpp/examples/messaging/server.cpp b/qpid/cpp/examples/messaging/server.cpp
index aa271d9..ba9fa9e 100644
--- a/qpid/cpp/examples/messaging/server.cpp
+++ b/qpid/cpp/examples/messaging/server.cpp
@@ -52,15 +52,31 @@
const Address& address = request.getReplyTo();
if (address) {
Sender sender = session.createSender(address);
- std::string s = request.getContent();
- std::transform(s.begin(), s.end(), s.begin(), toupper);
- Message response(s);
+ Message response;
+
+ qpid::types::Variant requestObj = request.getContentObject();
+ if (requestObj.getType() == qpid::types::VAR_STRING) {
+ // Received a string.
+ // Server returns request string in upper case with same encoding.
+ std::string s = requestObj;
+ std::transform(s.begin(), s.end(), s.begin(), toupper);
+ qpid::types::Variant responseObj(s);
+ responseObj.setEncoding( requestObj.getEncoding() );
+ response.setContentObject( responseObj );
+ } else {
+ // Received something other than a string.
+ // Server echos received object as a utf8 string.
+ qpid::types::Variant responseObj( requestObj.asString() );
+ responseObj.setEncoding( "utf8" );
+ response.setContentObject( requestObj );
+ }
sender.send(response);
- std::cout << "Processed request: "
- << request.getContent()
- << " -> "
- << response.getContent() << std::endl;
+ std::cout << "Processed request: "
+ << request.getContentObject()
+ << " -> "
+ << response.getContentObject() << std::endl;
session.acknowledge();
+ sender.close();
} else {
std::cerr << "Error: no reply address specified for request: " << request.getContent() << std::endl;
session.reject(request);
diff --git a/qpid/cpp/src/CMakeLists.txt b/qpid/cpp/src/CMakeLists.txt
index fe7a809..3e5165d 100644
--- a/qpid/cpp/src/CMakeLists.txt
+++ b/qpid/cpp/src/CMakeLists.txt
@@ -1077,6 +1077,7 @@
qpid/broker/IngressCompletion.cpp
qpid/broker/Link.cpp
qpid/broker/LinkRegistry.cpp
+ qpid/broker/LossyLvq.cpp
qpid/broker/LossyQueue.cpp
qpid/broker/Lvq.cpp
qpid/broker/Message.cpp
diff --git a/qpid/cpp/src/amqp.cmake b/qpid/cpp/src/amqp.cmake
index 3be9f52..b2ff10b 100644
--- a/qpid/cpp/src/amqp.cmake
+++ b/qpid/cpp/src/amqp.cmake
@@ -22,7 +22,7 @@
find_package(Proton 0.5)
set (amqp_default ${amqp_force})
-set (maximum_version 0.7)
+set (maximum_version 0.9)
if (Proton_FOUND)
if (Proton_VERSION GREATER ${maximum_version})
message(WARNING "Qpid proton ${Proton_VERSION} is not a tested version and might not be compatible, ${maximum_version} is highest tested; build may not work")
@@ -35,7 +35,11 @@
endif (NOT Proton_VERSION EQUAL 0.5)
if (Proton_VERSION GREATER 0.7)
set (USE_PROTON_TRANSPORT_CONDITION 1)
+ set (HAVE_PROTON_EVENTS 1)
endif (Proton_VERSION GREATER 0.7)
+ if (Proton_VERSION GREATER 0.8)
+ set (NO_PROTON_DELIVERY_TAG_T 1)
+ endif (Proton_VERSION GREATER 0.8)
else ()
message(STATUS "Qpid proton not found, amqp 1.0 support not enabled")
endif ()
diff --git a/qpid/cpp/src/config.h.cmake b/qpid/cpp/src/config.h.cmake
index f813926..777fc1b 100644
--- a/qpid/cpp/src/config.h.cmake
+++ b/qpid/cpp/src/config.h.cmake
@@ -58,5 +58,6 @@
#cmakedefine HAVE_LOG_FTP
#cmakedefine HAVE_PROTON_TRACER
#cmakedefine USE_PROTON_TRANSPORT_CONDITION
-
+#cmakedefine HAVE_PROTON_EVENTS
+#cmakedefine NO_PROTON_DELIVERY_TAG_T
#endif /* QPID_CONFIG_H */
diff --git a/qpid/cpp/src/qpid/amqp_0_10/Connection.cpp b/qpid/cpp/src/qpid/amqp_0_10/Connection.cpp
index 87085b6..866f980 100644
--- a/qpid/cpp/src/qpid/amqp_0_10/Connection.cpp
+++ b/qpid/cpp/src/qpid/amqp_0_10/Connection.cpp
@@ -54,7 +54,7 @@
}
}
framing::AMQFrame frame;
- while(frame.decode(in)) {
+ while(!pushClosed && frame.decode(in)) {
QPID_LOG(trace, "RECV [" << identifier << "]: " << frame);
connection->received(frame);
}
diff --git a/qpid/cpp/src/qpid/amqp_0_10/SessionHandler.cpp b/qpid/cpp/src/qpid/amqp_0_10/SessionHandler.cpp
index 43f39c2..bd0dcbf 100644
--- a/qpid/cpp/src/qpid/amqp_0_10/SessionHandler.cpp
+++ b/qpid/cpp/src/qpid/amqp_0_10/SessionHandler.cpp
@@ -276,6 +276,7 @@
}
void SessionHandler::gap(const SequenceSet& /*commands*/) {
+ checkAttached();
throw NotImplementedException("session.gap not supported");
}
diff --git a/qpid/cpp/src/qpid/broker/AsyncCompletion.h b/qpid/cpp/src/qpid/broker/AsyncCompletion.h
index 1ab69f3..cb5d589 100644
--- a/qpid/cpp/src/qpid/broker/AsyncCompletion.h
+++ b/qpid/cpp/src/qpid/broker/AsyncCompletion.h
@@ -111,13 +111,14 @@
qpid::sys::Mutex::ScopedLock l(callbackLock);
if (active) {
if (callback.get()) {
+ boost::intrusive_ptr<Callback> save = callback;
+ callback = boost::intrusive_ptr<Callback>(); // Nobody else can run callback.
inCallback = true;
{
qpid::sys::Mutex::ScopedUnlock ul(callbackLock);
- callback->completed(sync);
+ save->completed(sync);
}
inCallback = false;
- callback = boost::intrusive_ptr<Callback>();
callbackLock.notifyAll();
}
active = false;
diff --git a/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp b/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp
index 2afdc5a..8972040 100644
--- a/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp
+++ b/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp
@@ -93,14 +93,14 @@
} else if (isOpen()) {
handler->connection.getChannel(frame.getChannel()).in(frame);
} else {
- handler->proxy.close(
+ handler->connection.close(
connection::CLOSE_CODE_FRAMING_ERROR,
"Connection not yet open, invalid frame received.");
}
}catch(ConnectionException& e){
- handler->proxy.close(e.code, e.what());
+ handler->connection.close(e.code, e.what());
}catch(std::exception& e){
- handler->proxy.close(541/*internal error*/, e.what());
+ handler->connection.close(connection::CLOSE_CODE_CONNECTION_FORCED, e.what());
}
}
@@ -234,21 +234,25 @@
void ConnectionHandler::Handler::open(const string& /*virtualHost*/,
const framing::Array& /*capabilities*/, bool /*insist*/)
{
+ if (connection.getUserId().empty()) {
+ throw ConnectionForcedException("Not authenticated!");
+ }
+
if (connection.isFederationLink()) {
AclModule* acl = connection.getBroker().getAcl();
if (acl && acl->userAclRules()) {
if (!acl->authorise(connection.getUserId(),acl::ACT_CREATE,acl::OBJ_LINK,"")){
- proxy.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED,
- QPID_MSG("ACL denied " << connection.getUserId()
- << " creating a federation link"));
+ connection.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED,
+ QPID_MSG("ACL denied " << connection.getUserId()
+ << " creating a federation link"));
return;
}
} else {
if (connection.getBroker().isAuthenticating()) {
- proxy.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED,
- QPID_MSG("User " << connection.getUserId()
- << " federation connection denied. Systems with authentication "
- "enabled must specify ACL create link rules."));
+ connection.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED,
+ QPID_MSG("User " << connection.getUserId()
+ << " federation connection denied. Systems with authentication "
+ "enabled must specify ACL create link rules."));
return;
}
}
@@ -302,6 +306,11 @@
const framing::Array& supportedMechanisms,
const framing::Array& /*locales*/)
{
+ if (serverMode) {
+ throw ConnectionForcedException("Invalid protocol sequence.");
+ }
+
+
string requestedMechanism = connection.getAuthMechanism();
std::string username = connection.getUsername();
@@ -388,6 +397,10 @@
void ConnectionHandler::Handler::secure(const string& challenge )
{
+ if (serverMode) {
+ throw ConnectionForcedException("Invalid protocol sequence.");
+ }
+
if (sasl.get()) {
string response = sasl->step(challenge);
proxy.secureOk(response);
@@ -402,6 +415,10 @@
uint16_t /*heartbeatMin*/,
uint16_t heartbeatMax)
{
+ if (serverMode) {
+ throw ConnectionForcedException("Invalid protocol sequence.");
+ }
+
maxFrameSize = std::min(maxFrameSize, maxFrameSizeProposed);
connection.setFrameMax(maxFrameSize);
@@ -420,6 +437,10 @@
void ConnectionHandler::Handler::openOk(const framing::Array& knownHosts)
{
+ if (serverMode) {
+ throw ConnectionForcedException("Invalid protocol sequence.");
+ }
+
for (Array::ValueVector::const_iterator i = knownHosts.begin(); i != knownHosts.end(); ++i) {
Url url((*i)->get<std::string>());
connection.getKnownHosts().push_back(url);
diff --git a/qpid/cpp/src/qpid/broker/ConnectionHandler.h b/qpid/cpp/src/qpid/broker/ConnectionHandler.h
index 7af2fe3..30155fb 100644
--- a/qpid/cpp/src/qpid/broker/ConnectionHandler.h
+++ b/qpid/cpp/src/qpid/broker/ConnectionHandler.h
@@ -100,13 +100,14 @@
std::auto_ptr<Handler> handler;
bool handle(const qpid::framing::AMQMethodBody& method);
+ void close(framing::connection::CloseCode code, const std::string& text);
public:
ConnectionHandler(amqp_0_10::Connection& connection, bool isClient );
- void close(framing::connection::CloseCode code, const std::string& text);
void heartbeat();
void handle(framing::AMQFrame& frame);
void setSecureConnection(SecureConnection* secured);
bool isOpen() { return handler->isOpen; }
+ friend class amqp_0_10::Connection;
};
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface3.java b/qpid/cpp/src/qpid/broker/LossyLvq.cpp
similarity index 69%
copy from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface3.java
copy to qpid/cpp/src/qpid/broker/LossyLvq.cpp
index d1d0a1b..f59ecc1 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface3.java
+++ b/qpid/cpp/src/qpid/broker/LossyLvq.cpp
@@ -18,12 +18,13 @@
* under the License.
*
*/
-package org.apache.qpid.server.model.testmodel;
+#include "LossyLvq.h"
+#include "MessageMap.h"
-import org.apache.qpid.server.model.ManagedAnnotation;
-import org.apache.qpid.server.model.ManagedInterface;
+namespace qpid {
+namespace broker {
-@ManagedAnnotation
-public interface TestManagedInterface3 extends ManagedInterface
-{
-}
+LossyLvq::LossyLvq(const std::string& n, std::auto_ptr<MessageMap> m, const QueueSettings& s, MessageStore* const ms, management::Manageable* p, Broker* b)
+ : Queue(n, s, ms, p, b), Lvq(n, m, s, ms, p, b), LossyQueue(n, s, ms, p, b) {}
+
+}} // namespace qpid::broker
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java b/qpid/cpp/src/qpid/broker/LossyLvq.h
similarity index 61%
copy from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
copy to qpid/cpp/src/qpid/broker/LossyLvq.h
index 75c6c19..e0a266a 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
+++ b/qpid/cpp/src/qpid/broker/LossyLvq.h
@@ -1,4 +1,8 @@
+#ifndef QPID_BROKER_LOSSYLVQ_H
+#define QPID_BROKER_LOSSYLVQ_H
+
/*
+ *
* 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
@@ -15,18 +19,23 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
+ *
*/
+#include "qpid/broker/Lvq.h"
+#include "qpid/broker/LossyQueue.h"
-package org.apache.qpid.server.model.testmodel;
+namespace qpid {
+namespace broker {
+class MessageMap;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-public enum TestEnum
+/**
+ * Combination of LossyQueue and Lvq behaviours.
+ */
+class LossyLvq : public Lvq, public LossyQueue
{
- TEST_ENUM1,
- TEST_ENUM2,
- TEST_ENUM3;
-}
+ public:
+ LossyLvq(const std::string&, std::auto_ptr<MessageMap>, const QueueSettings&, MessageStore* const, management::Manageable*, Broker*);
+};
+}} // namespace qpid::broker
+
+#endif /*!QPID_BROKER_LOSSYLVQ_H*/
diff --git a/qpid/cpp/src/qpid/broker/LossyQueue.h b/qpid/cpp/src/qpid/broker/LossyQueue.h
index 3e62151..705865f 100644
--- a/qpid/cpp/src/qpid/broker/LossyQueue.h
+++ b/qpid/cpp/src/qpid/broker/LossyQueue.h
@@ -29,7 +29,7 @@
/**
* Drops messages to prevent a breach of any configured maximum depth.
*/
-class LossyQueue : public Queue
+class LossyQueue : public virtual Queue
{
public:
LossyQueue(const std::string&, const QueueSettings&, MessageStore* const, management::Manageable*, Broker*);
diff --git a/qpid/cpp/src/qpid/broker/Lvq.h b/qpid/cpp/src/qpid/broker/Lvq.h
index 335270a..26ba2b4 100644
--- a/qpid/cpp/src/qpid/broker/Lvq.h
+++ b/qpid/cpp/src/qpid/broker/Lvq.h
@@ -32,7 +32,7 @@
* conjunction with the MessageMap class. This requires an existing
* message to be 'replaced' by a newer message with the same key.
*/
-class Lvq : public Queue
+class Lvq : public virtual Queue
{
public:
Lvq(const std::string&, std::auto_ptr<MessageMap>, const QueueSettings&, MessageStore* const, management::Manageable*, Broker*);
diff --git a/qpid/cpp/src/qpid/broker/MessageBuilder.cpp b/qpid/cpp/src/qpid/broker/MessageBuilder.cpp
index 7cb9951..f5e9332 100644
--- a/qpid/cpp/src/qpid/broker/MessageBuilder.cpp
+++ b/qpid/cpp/src/qpid/broker/MessageBuilder.cpp
@@ -45,6 +45,9 @@
switch(state) {
case METHOD:
checkType(METHOD_BODY, type);
+ if (!frame.getMethod()->isA<qpid::framing::MessageTransferBody>())
+ throw NotImplementedException(QPID_MSG("Unexpected method: " << *(frame.getMethod())));
+
exchange = frame.castBody<qpid::framing::MessageTransferBody>()->getDestination();
state = HEADER;
break;
diff --git a/qpid/cpp/src/qpid/broker/Protocol.cpp b/qpid/cpp/src/qpid/broker/Protocol.cpp
index 2ef8c66..e9e7892 100644
--- a/qpid/cpp/src/qpid/broker/Protocol.cpp
+++ b/qpid/cpp/src/qpid/broker/Protocol.cpp
@@ -35,8 +35,10 @@
qpid::sys::ConnectionCodec* ProtocolRegistry::create(const qpid::framing::ProtocolVersion& v, qpid::sys::OutputControl& o, const std::string& id, const qpid::sys::SecuritySettings& s)
{
- if (v == qpid::framing::ProtocolVersion(0, 10) && isEnabled(AMQP_0_10)) {
- return create_0_10(o, id, s, false);
+ if (v == qpid::framing::ProtocolVersion(0, 10)) {
+ if (isEnabled(AMQP_0_10)) {
+ return create_0_10(o, id, s, false);
+ }
}
qpid::sys::ConnectionCodec* codec = 0;
for (Protocols::const_iterator i = protocols.begin(); !codec && i != protocols.end(); ++i) {
@@ -51,7 +53,22 @@
return create_0_10(o, id, s, true);
}
-bool ProtocolRegistry::isEnabled(const std::string& name)
+qpid::framing::ProtocolVersion ProtocolRegistry::supportedVersion() const
+{
+ if (isEnabled(AMQP_0_10)) {
+ return qpid::framing::ProtocolVersion(0,10);
+ } else {
+ for (Protocols::const_iterator i = protocols.begin(); i != protocols.end(); ++i) {
+ if (isEnabled(i->first)) {
+ return i->second->supportedVersion();
+ }
+ }
+ }
+ QPID_LOG(error, "No enabled protocols!");
+ return qpid::framing::ProtocolVersion(0,0);
+}
+
+bool ProtocolRegistry::isEnabled(const std::string& name) const
{
return enabled.empty()/*if nothing is explicitly enabled, assume everything is*/ || enabled.find(name) != enabled.end();
}
diff --git a/qpid/cpp/src/qpid/broker/Protocol.h b/qpid/cpp/src/qpid/broker/Protocol.h
index 59a6318..a7dbc98 100644
--- a/qpid/cpp/src/qpid/broker/Protocol.h
+++ b/qpid/cpp/src/qpid/broker/Protocol.h
@@ -61,6 +61,7 @@
virtual qpid::sys::ConnectionCodec* create(const qpid::framing::ProtocolVersion&, qpid::sys::OutputControl&, const std::string&, const qpid::sys::SecuritySettings&) = 0;
virtual boost::intrusive_ptr<const qpid::broker::amqp_0_10::MessageTransfer> translate(const Message&) = 0;
virtual boost::shared_ptr<RecoverableMessage> recover(qpid::framing::Buffer&) = 0;
+ virtual qpid::framing::ProtocolVersion supportedVersion() const = 0;
private:
};
@@ -70,6 +71,7 @@
public:
QPID_BROKER_EXTERN qpid::sys::ConnectionCodec* create(const qpid::framing::ProtocolVersion&, qpid::sys::OutputControl&, const std::string&, const qpid::sys::SecuritySettings&);
QPID_BROKER_EXTERN qpid::sys::ConnectionCodec* create(qpid::sys::OutputControl&, const std::string&, const qpid::sys::SecuritySettings&);
+ QPID_BROKER_EXTERN qpid::framing::ProtocolVersion supportedVersion() const;
QPID_BROKER_EXTERN boost::intrusive_ptr<const qpid::broker::amqp_0_10::MessageTransfer> translate(const Message&);
QPID_BROKER_EXTERN boost::shared_ptr<RecoverableMessage> recover(qpid::framing::Buffer&);
QPID_BROKER_EXTERN Message decode(qpid::framing::Buffer&);
@@ -86,7 +88,7 @@
Broker* broker;
qpid::sys::ConnectionCodec* create_0_10(qpid::sys::OutputControl&, const std::string&, const qpid::sys::SecuritySettings&, bool);
- bool isEnabled(const std::string&);
+ bool isEnabled(const std::string&) const;
};
}} // namespace qpid::broker
diff --git a/qpid/cpp/src/qpid/broker/Queue.cpp b/qpid/cpp/src/qpid/broker/Queue.cpp
index d897029..b1f7d05 100644
--- a/qpid/cpp/src/qpid/broker/Queue.cpp
+++ b/qpid/cpp/src/qpid/broker/Queue.cpp
@@ -1258,6 +1258,10 @@
if (has_userId)
result.first->setOwningUser(_userId);
+ if (result.first->getSettings().autoDeleteDelay) {
+ result.first->scheduleAutoDelete();
+ }
+
return result.first;
}
@@ -1296,10 +1300,10 @@
}
};
-void Queue::scheduleAutoDelete()
+void Queue::scheduleAutoDelete(bool immediate)
{
if (canAutoDelete()) {
- if (settings.autoDeleteDelay) {
+ if (!immediate && settings.autoDeleteDelay) {
AbsTime time(now(), Duration(settings.autoDeleteDelay * TIME_SEC));
autoDeleteTask = boost::intrusive_ptr<qpid::sys::TimerTask>(new AutoDeleteTask(shared_from_this(), time));
broker->getTimer().add(autoDeleteTask);
@@ -1339,7 +1343,7 @@
return o == owner;
}
-void Queue::releaseExclusiveOwnership()
+void Queue::releaseExclusiveOwnership(bool immediateExpiry)
{
bool unused;
{
@@ -1351,7 +1355,7 @@
unused = !users.isUsed();
}
if (unused && settings.autodelete) {
- scheduleAutoDelete();
+ scheduleAutoDelete(immediateExpiry);
}
}
diff --git a/qpid/cpp/src/qpid/broker/Queue.h b/qpid/cpp/src/qpid/broker/Queue.h
index 65a91b8..efca9b9 100644
--- a/qpid/cpp/src/qpid/broker/Queue.h
+++ b/qpid/cpp/src/qpid/broker/Queue.h
@@ -379,7 +379,7 @@
QPID_BROKER_EXTERN uint32_t getConsumerCount() const;
inline const std::string& getName() const { return name; }
QPID_BROKER_EXTERN bool isExclusiveOwner(const OwnershipToken* const o) const;
- QPID_BROKER_EXTERN void releaseExclusiveOwnership();
+ QPID_BROKER_EXTERN void releaseExclusiveOwnership(bool immediateExpiry=false);
QPID_BROKER_EXTERN bool setExclusiveOwner(const OwnershipToken* const o);
QPID_BROKER_EXTERN bool hasExclusiveConsumer() const;
QPID_BROKER_EXTERN bool hasExclusiveOwner() const;
@@ -389,7 +389,7 @@
inline bool isAutoDelete() const { return settings.autodelete; }
inline bool isBrowseOnly() const { return settings.isBrowseOnly; }
QPID_BROKER_EXTERN bool canAutoDelete() const;
- QPID_BROKER_EXTERN void scheduleAutoDelete();
+ QPID_BROKER_EXTERN void scheduleAutoDelete(bool immediate=false);
QPID_BROKER_EXTERN bool isDeleted() const;
const QueueBindings& getBindings() const { return bindings; }
diff --git a/qpid/cpp/src/qpid/broker/QueueFactory.cpp b/qpid/cpp/src/qpid/broker/QueueFactory.cpp
index 8104fff..16cdea3 100644
--- a/qpid/cpp/src/qpid/broker/QueueFactory.cpp
+++ b/qpid/cpp/src/qpid/broker/QueueFactory.cpp
@@ -22,6 +22,7 @@
#include "qpid/broker/Broker.h"
#include "qpid/broker/QueueSettings.h"
#include "qpid/broker/Queue.h"
+#include "qpid/broker/LossyLvq.h"
#include "qpid/broker/LossyQueue.h"
#include "qpid/broker/Lvq.h"
#include "qpid/broker/Messages.h"
@@ -51,10 +52,17 @@
boost::shared_ptr<QueueFlowLimit> flow_ptr(QueueFlowLimit::createLimit(name, settings));
//1. determine Queue type (i.e. whether we are subclassing Queue)
- // -> if 'ring' policy is in use then subclass
boost::shared_ptr<Queue> queue;
if (settings.dropMessagesAtLimit) {
- queue = boost::shared_ptr<Queue>(new LossyQueue(name, settings, settings.durable ? store : 0, parent, broker));
+ // -> if 'ring' policy is in use then subclass
+ if (settings.lvqKey.size()) {
+ //combination of ring and lvq:
+ std::auto_ptr<MessageMap> map(new MessageMap(settings.lvqKey));
+ queue = boost::shared_ptr<Queue>(new LossyLvq(name, map, settings, settings.durable ? store : 0, parent, broker));
+ } else {
+ //simple ring:
+ queue = boost::shared_ptr<Queue>(new LossyQueue(name, settings, settings.durable ? store : 0, parent, broker));
+ }
} else if (settings.selfDestructAtLimit) {
queue = boost::shared_ptr<Queue>(new SelfDestructQueue(name, settings, settings.durable ? store : 0, parent, broker));
} else if (settings.lvqKey.size()) {
diff --git a/qpid/cpp/src/qpid/broker/amqp/Connection.cpp b/qpid/cpp/src/qpid/broker/amqp/Connection.cpp
index 04bbe8b..3a93e2a 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Connection.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/Connection.cpp
@@ -37,6 +37,9 @@
extern "C" {
#include <proton/engine.h>
#include <proton/error.h>
+#ifdef HAVE_PROTON_EVENTS
+#include <proton/event.h>
+#endif
}
namespace qpid {
@@ -117,8 +120,14 @@
: BrokerContext(b), ManagedConnection(getBroker(), i, brokerInitiated),
connection(pn_connection()),
transport(pn_transport()),
+ collector(0),
out(o), id(i), haveOutput(true), closeInitiated(false), closeRequested(false)
{
+#ifdef HAVE_PROTON_EVENTS
+ collector = pn_collector();
+ pn_connection_collect(connection, collector);
+#endif
+
if (pn_transport_bind(transport, connection)) {
//error
QPID_LOG(error, "Failed to bind transport to connection: " << getError());
@@ -157,6 +166,9 @@
getBroker().getConnectionObservers().closed(*this);
pn_transport_free(transport);
pn_connection_free(connection);
+#ifdef HAVE_PROTON_EVENTS
+ pn_collector_free(collector);
+#endif
}
pn_transport_t* Connection::getTransport()
@@ -222,10 +234,15 @@
void Connection::doOutput(size_t capacity)
{
- for (ssize_t n = pn_transport_pending(transport); n > 0 && n < (ssize_t) capacity; n = pn_transport_pending(transport)) {
- if (dispatch()) processDeliveries();
- else break;
- }
+ ssize_t n = 0;
+ do {
+ if (dispatch()) {
+ processDeliveries();
+ ssize_t next = pn_transport_pending(transport);
+ if (n == next) break;
+ n = next;
+ } else break;
+ } while (n > 0 && n < (ssize_t) capacity);
}
bool Connection::dispatch()
@@ -327,122 +344,92 @@
{
return qpid::framing::ProtocolVersion(1,0);
}
-namespace {
-pn_state_t REQUIRES_OPEN = PN_LOCAL_UNINIT | PN_REMOTE_ACTIVE;
-pn_state_t REQUIRES_CLOSE = PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED;
-}
void Connection::process()
{
QPID_LOG(trace, id << " process()");
+#ifdef HAVE_PROTON_EVENTS
+ pn_event_t *event = pn_collector_peek(collector);
+ while (event) {
+ switch (pn_event_type(event)) {
+ case PN_CONNECTION_REMOTE_OPEN:
+ doConnectionRemoteOpen();
+ break;
+ case PN_CONNECTION_REMOTE_CLOSE:
+ doConnectionRemoteClose();
+ break;
+ case PN_SESSION_REMOTE_OPEN:
+ doSessionRemoteOpen(pn_event_session(event));
+ break;
+ case PN_SESSION_REMOTE_CLOSE:
+ doSessionRemoteClose(pn_event_session(event));
+ break;
+ case PN_LINK_REMOTE_OPEN:
+ doLinkRemoteOpen(pn_event_link(event));
+ break;
+ case PN_LINK_REMOTE_CLOSE:
+ doLinkRemoteClose(pn_event_link(event));
+ break;
+ case PN_DELIVERY:
+ doDeliveryUpdated(pn_event_delivery(event));
+ break;
+ default:
+ break;
+ }
+ pn_collector_pop(collector);
+ event = pn_collector_peek(collector);
+ }
+
+#else // !HAVE_PROTON_EVENTS
+
+ const pn_state_t REQUIRES_OPEN = PN_LOCAL_UNINIT | PN_REMOTE_ACTIVE;
+ const pn_state_t REQUIRES_CLOSE = PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED;
+
if ((pn_connection_state(connection) & REQUIRES_OPEN) == REQUIRES_OPEN) {
- QPID_LOG_CAT(debug, model, id << " connection opened");
- open();
- setContainerId(pn_connection_remote_container(connection));
+ doConnectionRemoteOpen();
}
for (pn_session_t* s = pn_session_head(connection, REQUIRES_OPEN); s; s = pn_session_next(s, REQUIRES_OPEN)) {
- QPID_LOG_CAT(debug, model, id << " session begun");
- pn_session_open(s);
- boost::shared_ptr<Session> ssn(new Session(s, *this, out));
- sessions[s] = ssn;
+ doSessionRemoteOpen(s);
}
for (pn_link_t* l = pn_link_head(connection, REQUIRES_OPEN); l; l = pn_link_next(l, REQUIRES_OPEN)) {
- pn_link_open(l);
-
- Sessions::iterator session = sessions.find(pn_link_session(l));
- if (session == sessions.end()) {
- QPID_LOG(error, id << " Link attached on unknown session!");
- } else {
- try {
- session->second->attach(l);
- QPID_LOG_CAT(debug, protocol, id << " link " << l << " attached on " << pn_link_session(l));
- } catch (const Exception& e) {
- QPID_LOG_CAT(error, protocol, "Error on attach: " << e.what());
- pn_condition_t* error = pn_link_condition(l);
- pn_condition_set_name(error, e.symbol());
- pn_condition_set_description(error, e.what());
- pn_link_close(l);
- } catch (const qpid::framing::UnauthorizedAccessException& e) {
- QPID_LOG_CAT(error, protocol, "Error on attach: " << e.what());
- pn_condition_t* error = pn_link_condition(l);
- pn_condition_set_name(error, qpid::amqp::error_conditions::UNAUTHORIZED_ACCESS.c_str());
- pn_condition_set_description(error, e.what());
- pn_link_close(l);
- } catch (const std::exception& e) {
- QPID_LOG_CAT(error, protocol, "Error on attach: " << e.what());
- pn_condition_t* error = pn_link_condition(l);
- pn_condition_set_name(error, qpid::amqp::error_conditions::INTERNAL_ERROR.c_str());
- pn_condition_set_description(error, e.what());
- pn_link_close(l);
- }
- }
+ doLinkRemoteOpen(l);
}
processDeliveries();
for (pn_link_t* l = pn_link_head(connection, REQUIRES_CLOSE); l; l = pn_link_next(l, REQUIRES_CLOSE)) {
- pn_link_close(l);
- Sessions::iterator session = sessions.find(pn_link_session(l));
- if (session == sessions.end()) {
- QPID_LOG(error, id << " peer attempted to detach link on unknown session!");
- } else {
- session->second->detach(l);
- QPID_LOG_CAT(debug, model, id << " link detached");
- }
+ doLinkRemoteClose(l);
}
for (pn_session_t* s = pn_session_head(connection, REQUIRES_CLOSE); s; s = pn_session_next(s, REQUIRES_CLOSE)) {
- pn_session_close(s);
- Sessions::iterator i = sessions.find(s);
- if (i != sessions.end()) {
- i->second->close();
- sessions.erase(i);
- QPID_LOG_CAT(debug, model, id << " session ended");
- } else {
- QPID_LOG(error, id << " peer attempted to close unrecognised session");
- }
+ doSessionRemoteClose(s);
}
if ((pn_connection_state(connection) & REQUIRES_CLOSE) == REQUIRES_CLOSE) {
- QPID_LOG_CAT(debug, model, id << " connection closed");
- pn_connection_close(connection);
+ doConnectionRemoteClose();
}
+#endif // !HAVE_PROTON_EVENTS
}
namespace {
std::string convert(pn_delivery_tag_t in)
{
+#ifdef NO_PROTON_DELIVERY_TAG_T
+ return std::string(in.start, in.size);
+#else
return std::string(in.bytes, in.size);
+#endif
}
}
void Connection::processDeliveries()
{
- //handle deliveries
+#ifdef HAVE_PROTON_EVENTS
+ // with the event API, there's no way to selectively process only
+ // the delivery-related events. We have to process all events:
+ process();
+#else
for (pn_delivery_t* delivery = pn_work_head(connection); delivery; delivery = pn_work_next(delivery)) {
- pn_link_t* link = pn_delivery_link(delivery);
- try {
- if (pn_link_is_receiver(link)) {
- Sessions::iterator i = sessions.find(pn_link_session(link));
- if (i != sessions.end()) {
- i->second->readable(link, delivery);
- } else {
- pn_delivery_update(delivery, PN_REJECTED);
- }
- } else { //i.e. SENDER
- Sessions::iterator i = sessions.find(pn_link_session(link));
- if (i != sessions.end()) {
- QPID_LOG(trace, id << " handling outgoing delivery for " << link << " on session " << pn_link_session(link));
- i->second->writable(link, delivery);
- } else {
- QPID_LOG(error, id << " Got delivery for non-existent session: " << pn_link_session(link) << ", link: " << link);
- }
- }
- } catch (const Exception& e) {
- QPID_LOG_CAT(error, protocol, "Error processing deliveries: " << e.what());
- pn_condition_t* error = pn_link_condition(link);
- pn_condition_set_name(error, e.symbol());
- pn_condition_set_description(error, e.what());
- pn_link_close(link);
- }
+ doDeliveryUpdated(delivery);
}
+#endif
}
std::string Connection::getError()
@@ -470,4 +457,132 @@
closeRequested = true;
out.activateOutput();
}
+
+// the peer has issued an Open performative
+void Connection::doConnectionRemoteOpen()
+{
+ // respond in kind if we haven't yet
+ if ((pn_connection_state(connection) & PN_LOCAL_UNINIT) == PN_LOCAL_UNINIT) {
+ QPID_LOG_CAT(debug, model, id << " connection opened");
+ open();
+ setContainerId(pn_connection_remote_container(connection));
+ }
+}
+
+// the peer has issued a Close performative
+void Connection::doConnectionRemoteClose()
+{
+ if ((pn_connection_state(connection) & PN_LOCAL_CLOSED) == 0) {
+ QPID_LOG_CAT(debug, model, id << " connection closed");
+ pn_connection_close(connection);
+ }
+}
+
+// the peer has issued a Begin performative
+void Connection::doSessionRemoteOpen(pn_session_t *session)
+{
+ if ((pn_session_state(session) & PN_LOCAL_UNINIT) == PN_LOCAL_UNINIT) {
+ QPID_LOG_CAT(debug, model, id << " session begun");
+ pn_session_open(session);
+ boost::shared_ptr<Session> ssn(new Session(session, *this, out));
+ sessions[session] = ssn;
+ }
+}
+
+// the peer has issued an End performative
+void Connection::doSessionRemoteClose(pn_session_t *session)
+{
+ if ((pn_session_state(session) & PN_LOCAL_CLOSED) == 0) {
+ pn_session_close(session);
+ Sessions::iterator i = sessions.find(session);
+ if (i != sessions.end()) {
+ i->second->close();
+ sessions.erase(i);
+ QPID_LOG_CAT(debug, model, id << " session ended");
+ } else {
+ QPID_LOG(error, id << " peer attempted to close unrecognised session");
+ }
+ }
+}
+
+// the peer has issued an Attach performative
+void Connection::doLinkRemoteOpen(pn_link_t *link)
+{
+ if ((pn_link_state(link) & PN_LOCAL_UNINIT) == PN_LOCAL_UNINIT) {
+ pn_link_open(link);
+ Sessions::iterator session = sessions.find(pn_link_session(link));
+ if (session == sessions.end()) {
+ QPID_LOG(error, id << " Link attached on unknown session!");
+ } else {
+ try {
+ session->second->attach(link);
+ QPID_LOG_CAT(debug, protocol, id << " link " << link << " attached on " << pn_link_session(link));
+ } catch (const Exception& e) {
+ QPID_LOG_CAT(error, protocol, "Error on attach: " << e.what());
+ pn_condition_t* error = pn_link_condition(link);
+ pn_condition_set_name(error, e.symbol());
+ pn_condition_set_description(error, e.what());
+ pn_link_close(link);
+ } catch (const qpid::framing::UnauthorizedAccessException& e) {
+ QPID_LOG_CAT(error, protocol, "Error on attach: " << e.what());
+ pn_condition_t* error = pn_link_condition(link);
+ pn_condition_set_name(error, qpid::amqp::error_conditions::UNAUTHORIZED_ACCESS.c_str());
+ pn_condition_set_description(error, e.what());
+ pn_link_close(link);
+ } catch (const std::exception& e) {
+ QPID_LOG_CAT(error, protocol, "Error on attach: " << e.what());
+ pn_condition_t* error = pn_link_condition(link);
+ pn_condition_set_name(error, qpid::amqp::error_conditions::INTERNAL_ERROR.c_str());
+ pn_condition_set_description(error, e.what());
+ pn_link_close(link);
+ }
+ }
+ }
+}
+
+// the peer has issued a Detach performative
+void Connection::doLinkRemoteClose(pn_link_t *link)
+{
+ if ((pn_link_state(link) & PN_LOCAL_CLOSED) == 0) {
+ pn_link_close(link);
+ Sessions::iterator session = sessions.find(pn_link_session(link));
+ if (session == sessions.end()) {
+ QPID_LOG(error, id << " peer attempted to detach link on unknown session!");
+ } else {
+ session->second->detach(link);
+ QPID_LOG_CAT(debug, model, id << " link detached");
+ }
+ }
+}
+
+// the status of the delivery has changed
+void Connection::doDeliveryUpdated(pn_delivery_t *delivery)
+{
+ pn_link_t* link = pn_delivery_link(delivery);
+ try {
+ if (pn_link_is_receiver(link)) {
+ Sessions::iterator i = sessions.find(pn_link_session(link));
+ if (i != sessions.end()) {
+ i->second->readable(link, delivery);
+ } else {
+ pn_delivery_update(delivery, PN_REJECTED);
+ }
+ } else { //i.e. SENDER
+ Sessions::iterator i = sessions.find(pn_link_session(link));
+ if (i != sessions.end()) {
+ QPID_LOG(trace, id << " handling outgoing delivery for " << link << " on session " << pn_link_session(link));
+ i->second->writable(link, delivery);
+ } else {
+ QPID_LOG(error, id << " Got delivery for non-existent session: " << pn_link_session(link) << ", link: " << link);
+ }
+ }
+ } catch (const Exception& e) {
+ QPID_LOG_CAT(error, protocol, "Error processing deliveries: " << e.what());
+ pn_condition_t* error = pn_link_condition(link);
+ pn_condition_set_name(error, e.symbol());
+ pn_condition_set_description(error, e.what());
+ pn_link_close(link);
+ }
+}
+
}}} // namespace qpid::broker::amqp
diff --git a/qpid/cpp/src/qpid/broker/amqp/Connection.h b/qpid/cpp/src/qpid/broker/amqp/Connection.h
index 17c5b0e..ea4ce06 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Connection.h
+++ b/qpid/cpp/src/qpid/broker/amqp/Connection.h
@@ -31,6 +31,9 @@
struct pn_connection_t;
struct pn_session_t;
struct pn_transport_t;
+struct pn_collector_t;
+struct pn_link_t;
+struct pn_delivery_t;
namespace qpid {
namespace sys {
@@ -69,6 +72,7 @@
typedef std::map<pn_session_t*, boost::shared_ptr<Session> > Sessions;
pn_connection_t* connection;
pn_transport_t* transport;
+ pn_collector_t* collector;
qpid::sys::OutputControl& out;
const std::string id;
bool haveOutput;
@@ -86,6 +90,17 @@
void open();
void readPeerProperties();
void closedByManagement();
+
+ private:
+ // handle Proton engine events
+ void doConnectionRemoteOpen();
+ void doConnectionRemoteClose();
+ void doSessionRemoteOpen(pn_session_t *session);
+ void doSessionRemoteClose(pn_session_t *session);
+ void doLinkRemoteOpen(pn_link_t *link);
+ void doLinkRemoteClose(pn_link_t *link);
+ void doDeliveryUpdated(pn_delivery_t *delivery);
+
};
}}} // namespace qpid::broker::amqp
diff --git a/qpid/cpp/src/qpid/broker/amqp/Domain.cpp b/qpid/cpp/src/qpid/broker/amqp/Domain.cpp
index cc714c0..c2d4782 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Domain.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/Domain.cpp
@@ -140,6 +140,10 @@
boost::shared_ptr<Domain>, BrokerContext&, boost::shared_ptr<Relay>);
qpid::sys::ConnectionCodec* create(const framing::ProtocolVersion&, qpid::sys::OutputControl&, const std::string&, const qpid::sys::SecuritySettings&);
qpid::sys::ConnectionCodec* create(qpid::sys::OutputControl&, const std::string&, const qpid::sys::SecuritySettings&);
+ qpid::framing::ProtocolVersion supportedVersion() const
+ {
+ return qpid::framing::ProtocolVersion(1, 0);
+ }
bool connect();
void failed(int, std::string);
private:
diff --git a/qpid/cpp/src/qpid/broker/amqp/Incoming.cpp b/qpid/cpp/src/qpid/broker/amqp/Incoming.cpp
index ce4c73d..d4f73fc 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Incoming.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/Incoming.cpp
@@ -57,7 +57,7 @@
return credit;//TODO: proper flow control
}
-void Incoming::detached()
+void Incoming::detached(bool /*closed*/)
{
}
diff --git a/qpid/cpp/src/qpid/broker/amqp/Incoming.h b/qpid/cpp/src/qpid/broker/amqp/Incoming.h
index 1a70643..ccf999a 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Incoming.h
+++ b/qpid/cpp/src/qpid/broker/amqp/Incoming.h
@@ -42,7 +42,7 @@
virtual ~Incoming();
virtual bool doWork();//do anything that requires output
virtual bool haveWork();//called when handling input to see whether any output work is needed
- virtual void detached();
+ virtual void detached(bool closed);
virtual void readable(pn_delivery_t* delivery) = 0;
void verify(const std::string& userid, const std::string& defaultRealm);
void wakeup();
diff --git a/qpid/cpp/src/qpid/broker/amqp/Outgoing.cpp b/qpid/cpp/src/qpid/broker/amqp/Outgoing.cpp
index 54993d0..0136d5a 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Outgoing.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/Outgoing.cpp
@@ -32,6 +32,7 @@
#include "qpid/framing/Buffer.h"
#include "qpid/framing/reply_exceptions.h"
#include "qpid/log/Statement.h"
+#include "config.h"
namespace qpid {
namespace broker {
@@ -156,7 +157,7 @@
return deliveries[current].delivery == 0 && pn_link_credit(link);
}
-void OutgoingFromQueue::detached()
+void OutgoingFromQueue::detached(bool closed)
{
QPID_LOG(debug, "Detaching outgoing link " << getName() << " from " << queue->getName());
queue->cancel(shared_from_this());
@@ -164,12 +165,14 @@
for (size_t i = 0 ; i < deliveries.capacity(); ++i) {
if (deliveries[i].msg) queue->release(deliveries[i].cursor, true);
}
- if (exclusive) queue->releaseExclusiveOwnership();
- else if (isControllingUser) queue->releaseFromUse(true);
+ if (exclusive) {
+ queue->releaseExclusiveOwnership(closed);
+ } else if (isControllingUser) {
+ queue->releaseFromUse(true);
+ }
cancelled = true;
}
-
OutgoingFromQueue::~OutgoingFromQueue()
{
if (!cancelled && isControllingUser) queue->releaseFromUse(true);
@@ -283,7 +286,11 @@
OutgoingFromQueue::Record::Record() : delivery(0), disposition(0), index(0)
{
+#ifdef NO_PROTON_DELIVERY_TAG_T
+ tag.start = tagData;
+#else
tag.bytes = tagData;
+#endif
tag.size = TAG_WIDTH;
}
void OutgoingFromQueue::Record::init(size_t i)
@@ -304,7 +311,11 @@
size_t OutgoingFromQueue::Record::getIndex(pn_delivery_tag_t t)
{
assert(t.size == TAG_WIDTH);
+#ifdef NO_PROTON_DELIVERY_TAG_T
+ qpid::framing::Buffer buffer(const_cast<char*>(t.start)/*won't ever be written to*/, t.size);
+#else
qpid::framing::Buffer buffer(const_cast<char*>(t.bytes)/*won't ever be written to*/, t.size);
+#endif
return (size_t) buffer.getLong();
}
diff --git a/qpid/cpp/src/qpid/broker/amqp/Outgoing.h b/qpid/cpp/src/qpid/broker/amqp/Outgoing.h
index 27d8205..d3825d0 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Outgoing.h
+++ b/qpid/cpp/src/qpid/broker/amqp/Outgoing.h
@@ -70,7 +70,7 @@
/**
* Signals that this link has been detached
*/
- virtual void detached() = 0;
+ virtual void detached(bool closed) = 0;
/**
* Called when a delivery is writable
*/
@@ -98,7 +98,7 @@
void write(const char* data, size_t size);
void handle(pn_delivery_t* delivery);
bool canDeliver();
- void detached();
+ void detached(bool closed);
//Consumer interface:
bool deliver(const QueueCursor& cursor, const qpid::broker::Message& msg);
diff --git a/qpid/cpp/src/qpid/broker/amqp/ProtocolPlugin.cpp b/qpid/cpp/src/qpid/broker/amqp/ProtocolPlugin.cpp
index 2ea381e..621f25f 100644
--- a/qpid/cpp/src/qpid/broker/amqp/ProtocolPlugin.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/ProtocolPlugin.cpp
@@ -73,6 +73,7 @@
qpid::sys::ConnectionCodec* create(const qpid::framing::ProtocolVersion&, qpid::sys::OutputControl&, const std::string&, const qpid::sys::SecuritySettings&);
boost::intrusive_ptr<const qpid::broker::amqp_0_10::MessageTransfer> translate(const qpid::broker::Message&);
boost::shared_ptr<RecoverableMessage> recover(qpid::framing::Buffer&);
+ qpid::framing::ProtocolVersion supportedVersion() const;
private:
};
@@ -158,5 +159,10 @@
}
}
+qpid::framing::ProtocolVersion ProtocolImpl::supportedVersion() const
+{
+ return qpid::framing::ProtocolVersion(1,0);
+}
+
}}} // namespace qpid::broker::amqp
diff --git a/qpid/cpp/src/qpid/broker/amqp/Relay.cpp b/qpid/cpp/src/qpid/broker/amqp/Relay.cpp
index 83b3e64..587a114 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Relay.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/Relay.cpp
@@ -23,6 +23,7 @@
#include "qpid/log/Statement.h"
#include <algorithm>
#include <string.h>
+#include "config.h"
namespace qpid {
namespace broker {
@@ -126,7 +127,13 @@
{
relay->check();
relay->setCredit(pn_link_credit(link));
- return relay->send(link);
+ bool worked = relay->send(link);
+ pn_delivery_t *d = pn_link_current(link);
+ if (d && pn_delivery_writable(d)) {
+ handle(d);
+ return true;
+ }
+ return worked;
}
/**
* Called when a delivery is writable
@@ -163,7 +170,7 @@
/**
* Signals that this link has been detached
*/
-void OutgoingFromRelay::detached()
+void OutgoingFromRelay::detached(bool /*closed*/)
{
relay->detached(this);
}
@@ -221,7 +228,7 @@
return relay->getCredit();
}
-void IncomingToRelay::detached()
+void IncomingToRelay::detached(bool /*closed*/)
{
relay->detached(this);
}
@@ -238,7 +245,11 @@
//copy delivery tag
pn_delivery_tag_t dt = pn_delivery_tag(d);
tag.resize(dt.size);
+#ifdef NO_PROTON_DELIVERY_TAG_T
+ ::memmove(&tag[0], dt.start, dt.size);
+#else
::memmove(&tag[0], dt.bytes, dt.size);
+#endif
//set context
pn_delivery_set_context(d, this);
@@ -258,7 +269,11 @@
void BufferedTransfer::initOut(pn_link_t* link)
{
pn_delivery_tag_t dt;
+#ifdef NO_PROTON_DELIVERY_TAG_T
+ dt.start = &tag[0];
+#else
dt.bytes = &tag[0];
+#endif
dt.size = tag.size();
out.handle = pn_delivery(link, dt);
//set context
diff --git a/qpid/cpp/src/qpid/broker/amqp/Relay.h b/qpid/cpp/src/qpid/broker/amqp/Relay.h
index ef70069..32f317b 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Relay.h
+++ b/qpid/cpp/src/qpid/broker/amqp/Relay.h
@@ -100,7 +100,7 @@
const std::string& target, const std::string& name, boost::shared_ptr<Relay>);
bool doWork();
void handle(pn_delivery_t* delivery);
- void detached();
+ void detached(bool closed);
void init();
void setSubjectFilter(const std::string&);
void setSelectorFilter(const std::string&);
@@ -118,7 +118,7 @@
bool settle();
bool doWork();
bool haveWork();
- void detached();
+ void detached(bool closed);
void readable(pn_delivery_t* delivery);
uint32_t getCredit();
private:
diff --git a/qpid/cpp/src/qpid/broker/amqp/Session.cpp b/qpid/cpp/src/qpid/broker/amqp/Session.cpp
index 85da8c0..538883f 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Session.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/Session.cpp
@@ -48,6 +48,7 @@
#include "qpid/framing/MessageTransferBody.h"
#include "qpid/log/Statement.h"
#include "qpid/amqp_0_10/Codecs.h"
+#include "config.h"
#include <boost/intrusive_ptr.hpp>
#include <boost/format.hpp>
#include <map>
@@ -505,10 +506,11 @@
if (!settings.autodelete) settings.autodelete = autodelete;
altExchange = node.topic->getAlternateExchange();
}
- if (!settings.autoDeleteDelay) {
+ if (settings.original.find("qpid.auto_delete_timeout") == settings.original.end()) {
//only use delay from link if policy didn't specify one
settings.autoDeleteDelay = pn_terminus_get_timeout(source);
- settings.original["qpid.auto_delete_timeout"] = settings.autoDeleteDelay;
+ if (settings.autoDeleteDelay)
+ settings.original["qpid.auto_delete_timeout"] = settings.autoDeleteDelay;
}
if (settings.autoDeleteDelay) {
settings.autodelete = true;
@@ -577,7 +579,7 @@
if (pn_link_is_sender(link)) {
OutgoingLinks::iterator i = outgoing.find(link);
if (i != outgoing.end()) {
- i->second->detached();
+ i->second->detached(true/*TODO: checked whether actually closed; see PROTON-773*/);
boost::shared_ptr<Queue> q = OutgoingFromQueue::getExclusiveSubscriptionQueue(i->second.get());
if (q && !q->isAutoDelete() && !q->isDeleted()) {
connection.getBroker().deleteQueue(q->getName(), connection.getUserId(), connection.getMgmtId());
@@ -588,7 +590,7 @@
} else {
IncomingLinks::iterator i = incoming.find(link);
if (i != incoming.end()) {
- i->second->detached();
+ i->second->detached(true/*TODO: checked whether actually closed; see PROTON-773*/);
incoming.erase(i);
QPID_LOG(debug, "Incoming link detached");
}
@@ -615,7 +617,11 @@
void Session::readable(pn_link_t* link, pn_delivery_t* delivery)
{
pn_delivery_tag_t tag = pn_delivery_tag(delivery);
+#ifdef NO_PROTON_DELIVERY_TAG_T
+ QPID_LOG(debug, "received delivery: " << std::string(tag.start, tag.size));
+#else
QPID_LOG(debug, "received delivery: " << std::string(tag.bytes, tag.size));
+#endif
incomingMessageReceived();
IncomingLinks::iterator target = incoming.find(link);
if (target == incoming.end()) {
@@ -653,7 +659,7 @@
pn_condition_set_name(error, e.symbol());
pn_condition_set_description(error, e.what());
pn_link_close(s->first);
- s->second->detached();
+ s->second->detached(true);
outgoing.erase(s++);
output = true;
}
@@ -678,7 +684,7 @@
pn_condition_set_name(error, e.symbol());
pn_condition_set_description(error, e.what());
pn_link_close(i->first);
- i->second->detached();
+ i->second->detached(true);
incoming.erase(i++);
output = true;
}
@@ -690,10 +696,10 @@
void Session::close()
{
for (OutgoingLinks::iterator i = outgoing.begin(); i != outgoing.end(); ++i) {
- i->second->detached();
+ i->second->detached(false);
}
for (IncomingLinks::iterator i = incoming.begin(); i != incoming.end(); ++i) {
- i->second->detached();
+ i->second->detached(false);
}
outgoing.clear();
incoming.clear();
diff --git a/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp b/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
index bbb310b..0225ee7 100644
--- a/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
+++ b/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
@@ -55,6 +55,7 @@
using qpid::framing::ExchangeBoundResult;
using qpid::framing::ExchangeQueryResult;
using qpid::framing::FieldTable;
+using qpid::framing::FieldValue;
using qpid::framing::QueueQueryResult;
using qpid::framing::ReplyTo;
using qpid::framing::Uuid;
@@ -140,6 +141,11 @@
const std::string PREFIX_QPID("qpid.");
const Verifier verifier;
+
+bool areEquivalent(const FieldValue& a, const FieldValue& b)
+{
+ return ((a == b) || (a.convertsTo<int64_t>() && b.convertsTo<int64_t>() && a.get<int64_t>() == b.get<int64_t>()));
+}
}
struct Binding
@@ -534,19 +540,19 @@
reliable(durable ? !AddressResolution::is_unreliable(address) : AddressResolution::is_reliable(address)),
actualType(type.empty() ? (specifiedType.empty() ? TOPIC_EXCHANGE : specifiedType) : type),
exclusiveQueue((Opt(address)/LINK/X_DECLARE/EXCLUSIVE).asBool(true)),
- autoDeleteQueue((Opt(address)/LINK/X_DECLARE/AUTO_DELETE).asBool(true)),
+ autoDeleteQueue((Opt(address)/LINK/X_DECLARE/AUTO_DELETE).asBool(!(durable || reliable))),
exclusiveSubscription((Opt(address)/LINK/X_SUBSCRIBE/EXCLUSIVE).asBool(exclusiveQueue)),
alternateExchange((Opt(address)/LINK/X_DECLARE/ALTERNATE_EXCHANGE).str())
{
- const Variant* timeout = (Opt(address)/LINK/TIMEOUT).value;
- if (timeout) {
+
+ if ((Opt(address)/LINK).hasKey(TIMEOUT)) {
+ const Variant* timeout = (Opt(address)/LINK/TIMEOUT).value;
if (timeout->asUint32()) queueOptions.setInt("qpid.auto_delete_timeout", timeout->asUint32());
- } else if (durable && !(Opt(address)/LINK/RELIABILITY).value) {
- //if durable but not explicitly reliable, then set a non-zero
- //default for the autodelete timeout (previously this would
- //have defaulted to autodelete immediately anyway, so the risk
- //of the change causing problems is mitigated)
- queueOptions.setInt("qpid.auto_delete_delay", 15*60);
+ } else if (durable && !reliable && !(Opt(address)/LINK/X_DECLARE).hasKey(AUTO_DELETE)) {
+ //if durable but not reliable, and auto-delete not
+ //explicitly set, then set a non-zero default for the
+ //autodelete timeout
+ queueOptions.setInt("qpid.auto_delete_timeout", 2*60);
}
(Opt(address)/LINK/X_DECLARE/ARGUMENTS).collect(queueOptions);
(Opt(address)/LINK/X_SUBSCRIBE/ARGUMENTS).collect(subscriptionOptions);
@@ -609,7 +615,7 @@
//create subscription queue:
session.queueDeclare(arg::queue=queue, arg::exclusive=exclusiveQueue,
- arg::autoDelete=autoDeleteQueue && (!(durable || reliable)), arg::durable=durable,
+ arg::autoDelete=autoDeleteQueue, arg::durable=durable,
arg::alternateExchange=alternateExchange,
arg::arguments=queueOptions);
//'default' binding:
@@ -806,7 +812,7 @@
FieldTable::ValuePtr v = result.getArguments().get(i->first);
if (!v) {
throw AssertionFailed((boost::format("Option %1% not set for %2%") % i->first % name).str());
- } else if (*i->second != *v) {
+ } else if (!areEquivalent(*i->second, *v)) {
throw AssertionFailed((boost::format("Option %1% does not match for %2%, expected %3%, got %4%")
% i->first % name % *(i->second) % *v).str());
}
@@ -906,7 +912,7 @@
FieldTable::ValuePtr v = result.getArguments().get(i->first);
if (!v) {
throw AssertionFailed((boost::format("Option %1% not set for %2%") % i->first % name).str());
- } else if (*i->second != *v) {
+ } else if (!areEquivalent(*i->second, *v)) {
throw AssertionFailed((boost::format("Option %1% does not match for %2%, expected %3%, got %4%")
% i->first % name % *(i->second) % *v).str());
}
diff --git a/qpid/cpp/src/qpid/framing/SequenceSet.cpp b/qpid/cpp/src/qpid/framing/SequenceSet.cpp
index 72fcd8a..6510842 100644
--- a/qpid/cpp/src/qpid/framing/SequenceSet.cpp
+++ b/qpid/cpp/src/qpid/framing/SequenceSet.cpp
@@ -33,7 +33,18 @@
namespace {
//each range contains 2 numbers, 4 bytes each
-uint16_t RANGE_SIZE = 2 * 4;
+uint16_t RANGE_SIZE = 2 * 4;
+int32_t MAX_RANGE = 2147483647;//2^31-1
+
+int32_t gap(const SequenceNumber& a, const SequenceNumber& b)
+{
+ return a < b ? b - a : a - b;
+}
+
+bool is_max_range(const SequenceNumber& a, const SequenceNumber& b)
+{
+ return gap(a, b) == MAX_RANGE;
+}
}
void SequenceSet::encode(Buffer& buffer) const
@@ -54,7 +65,21 @@
throw IllegalArgumentException(QPID_MSG("Invalid size for sequence set: " << size));
for (uint16_t i = 0; i < count; i++) {
- add(SequenceNumber(buffer.getLong()), SequenceNumber(buffer.getLong()));
+ SequenceNumber a(buffer.getLong());
+ SequenceNumber b(buffer.getLong());
+ if (b < a)
+ throw IllegalArgumentException(QPID_MSG("Invalid range in sequence set: " << a << " -> " << b));
+ if (is_max_range(a, b)) {
+ //RangeSet holds 'half-closed' ranges, where the end is
+ //one past the 'highest' value in the range. So if the
+ //range is already the maximum expressable with a 32bit
+ //sequence number, we can't represent it as a
+ //'half-closed' range, so we represent it as two ranges.
+ add(a, b-1);
+ add(b);
+ } else {
+ add(a, b);
+ }
}
}
diff --git a/qpid/cpp/src/qpid/ha/Primary.cpp b/qpid/cpp/src/qpid/ha/Primary.cpp
index 0e87346..870e472 100644
--- a/qpid/cpp/src/qpid/ha/Primary.cpp
+++ b/qpid/cpp/src/qpid/ha/Primary.cpp
@@ -482,6 +482,7 @@
{
shared_ptr<PrimaryTxObserver> observer =
PrimaryTxObserver::create(*this, haBroker, txBuffer);
+ sys::Mutex::ScopedLock l(lock);
txMap[observer->getTxQueue()->getName()] = observer;
return observer;
}
diff --git a/qpid/cpp/src/qpid/linearstore/ISSUES b/qpid/cpp/src/qpid/linearstore/ISSUES
index 2d5a389..4023ba9 100644
--- a/qpid/cpp/src/qpid/linearstore/ISSUES
+++ b/qpid/cpp/src/qpid/linearstore/ISSUES
@@ -25,7 +25,7 @@
------ ------- ----------------------
5359 - Linearstore: Implement new management schema and wire into store
5360 - Linearstore: Evaluate and rework logging to produce a consistent log output
- 5361 1145359 Linearstore: No tests for linearstore functionality currently exist
+* 5361 1145359 Linearstore: No tests for linearstore functionality currently exist
svn r.1564893 2014-02-05: Added tx-test-soak.sh
svn r.1564935 2014-02-05: Added license text to tx-test-soak.sh
svn r.1625283 2014-09-16: Basic python tests from legacystore ported over to linearstore
@@ -37,15 +37,22 @@
** Basic performance tests
5464 - [linearstore] Incompletely created journal files accumulate in EFP
- 1088944 [Linearstore] store does not return all files to EFP after purging big queue <queue purge issue>
- 6043 1066256 [LinearStore] changing efp size after using store broke the new durable nodes creation
+* - 1066256 [LinearStore] changing efp size after using store broke the new durable nodes creation
- 1067480 [LinearStore] Provide a way to limit max count/size of empty files in EFP
- 1067429 [LinearStore] last file from deleted queue is not moved to EFP <queue delete issue>
- - 1067482 [LinearStore] Provide a way to prealocate empty pages in EFP
-* 5671 [linearstore] Add ability to use disk partitions and select per-queue EFPs
- svn r.1636598 2014-11-04: WIP: New EFP and journal dir structure using symlinks
- svn r.1637985 2014-11-10: WIP: Auto-upgrade from old dir structure to new
- 6230 1165200 [linearstore] qpid-qls-analyze fails when analyzing empty journal
- svn r.1643053 2014-11-18: Proposed fix
+ - 1067482 [LinearStore] Provide a way to preallocate empty pages in EFP
+* 6303 1180660 [linearstore] Roll back auto-upgrade of store directory structure
+* 5362 1145363 Linearstore: No store tools exist for examining the journals
+ svn r.1556888 2014-01-09: WIP checkin for linearstore version of qpid_qls_analyze. Needs testing and tidy-up.
+ svn r.1560530 2014-01-22: Bugfixes for qpid_qls_analyze
+ svn r.1561848 2014-01-27: Bugfixes and enhancements for qpid_qls_analyze
+ svn r.1564808 2014-02-05: Bugfixes and enhancements for qpid_qls_analyze
+ svn r.1578899 2014-03-18: Bugfixes and enhancements for qpid_qls_analyze
+ svn r.1583778 2014-04-01: Bugfix for qpid_qls_analyze
+ * Store analysis and status
+ * Recovery/reading of message content
+ * Empty file pool status and management
+
@@ -115,16 +122,6 @@
5651 - [C++ broker] segfault in qpid::linearstore::journal::jdir::clear_dir when declaring durable queue
svn r.1582730 2014-03-28 Proposed fix by Pavel Moravec
* Bug introduced by r.1578899.
- 5362 1145363 Linearstore: No store tools exist for examining the journals
- svn r.1556888 2014-01-09: WIP checkin for linearstore version of qpid_qls_analyze. Needs testing and tidy-up.
- svn r.1560530 2014-01-22: Bugfixes for qpid_qls_analyze
- svn r.1561848 2014-01-27: Bugfixes and enhancements for qpid_qls_analyze
- svn r.1564808 2014-02-05: Bugfixes and enhancements for qpid_qls_analyze
- svn r.1578899 2014-03-18: Bugfixes and enhancements for qpid_qls_analyze
- svn r.1583778 2014-04-01: Bugfix for qpid_qls_analyze
- * Store analysis and status
- * Recovery/reading of message content
- * Empty file pool status and management
5661 - [linearstore] Set default cmake build to exclude linearstore
svn r.1584379 2014-04-03 Proposed solution.
* Run ccmake, select BUILD_LINEARSTORE to change its value to ON to build.
@@ -147,8 +144,16 @@
svn r.1631360 2014-10-13 Proposed solution
6157 1150397 linearstore: segfault when 2 journals request new journal file from empty EFP
svn r.1632504 2014-10-17 Proposed solution by pmoravec
- 6248 1167911 [linearstore] Symlink creation fails if store dir path is not absolute
+ 6230 1165200 [linearstore] qpid-qls-analyze fails when analyzing empty journal
+ svn r.1643053 2014-11-18: Proposed fix
+ 6248 1167911 [linearstore] Symlink creation fails if store dir path is not absolute
svn r.1641689 2014-11-25 Proposed solution
+ 5671 1160367 [linearstore] Add ability to use disk partitions and select per-queue EFPs
+ svn r.1636598 2014-11-04: WIP: New EFP and journal dir structure using symlinks
+ svn r.1637985 2014-11-10: WIP: Auto-upgrade from old dir structure to new
+ svn r.1649081 2015-01-02: WIP: Specify new queue using qpid-config --durable together with --efp-partition-num and/or --efp-pool-file-size. Needs testing.
+ - 1148807 [linearstore] Restarting broker with empty journal raises confusing warning
+ Fixed by svn r.1649081 of bug 5671 / 1160367 above
Ordered checkin list:
@@ -187,14 +192,17 @@
28. 1596509 5767 1098118 2014-05-21 0.22-mrg (pmoravec)
29. 1596633 NO-JIRA 1078937 2014-05-21 (includes tools install update)
30. 1599243 5767 1098118 2014-06-02 0.22-mrg
-30. 1599243 5767 1098118 2014-06-02
-31. 1614665 5924 1124906 2014-07-30
-32. 1620426 6043 1089652 2014-08-25
-33. 1631360 6147 1152012 2014-10-13 (pmoravec)
-34. 1632504 6157 1150397 2014-10-17 (pmoravec)
-35. 1636598 5671 2014-11-04
-36. 1637985 5671 2014-11-10
-37. 1641689 6248 1167911 2014-11-25
+31. 1599243 5767 1098118 2014-06-02
+32. 1614665 5924 1124906 2014-07-30
+33. 1620426 6043 1089652 2014-08-25
+34. 1631360 6147 1152012 2014-10-13 (pmoravec)
+35. 1632504 6157 1150397 2014-10-17 (pmoravec)
+36. 1636598 5671 1160367 2014-11-04
+37. 1637985 5671 1160367 2014-11-10
+38. 1643053 6230 1165200 2014-11-18
+39. 1641689 6248 1167911 2014-11-25
+40. 1649081 5671 1160367 2015-01-02
+41. 1649082 NO-JIRA - 2015-01-02
See above sections for details on these checkins.
diff --git a/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.cpp b/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.cpp
index 77d5703..70eac27 100644
--- a/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.cpp
+++ b/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.cpp
@@ -148,7 +148,7 @@
mgmtObject = qmf::org::apache::qpid::linearstore::Store::shared_ptr (
new qmf::org::apache::qpid::linearstore::Store(agent, this, broker));
- mgmtObject->set_location(storeDir);
+ mgmtObject->set_storeDir(storeDir);
mgmtObject->set_tplIsInitialized(false);
mgmtObject->set_tplDirectory(getTplBaseDir());
mgmtObject->set_tplWritePageSize(tplWCachePgSizeSblks * QLS_SBLK_SIZE_BYTES);
@@ -406,7 +406,7 @@
if (queue_.getName().size() == 0)
{
- QLS_LOG(error, "Cannot create store for empty (null) queue name - ignoring and attempting to continue.");
+ QLS_LOG(error, "Cannot create store for empty (null) queue name - queue create ignored.");
return;
}
@@ -449,15 +449,15 @@
MessageStoreImpl::getEmptyFilePool(const qpid::framing::FieldTable& args_) {
qpid::framing::FieldTable::ValuePtr value;
qpid::linearstore::journal::efpPartitionNumber_t localEfpPartition = defaultEfpPartitionNumber;
- value = args_.get("qpid.efp_partition");
+ value = args_.get("qpid.efp_partition_num");
if (value.get() != 0 && !value->empty() && value->convertsTo<int>()) {
- localEfpPartition = chkEfpPartition((uint32_t)value->get<int>(), "qpid.efp_partition");
+ localEfpPartition = chkEfpPartition((uint32_t)value->get<int>(), "qpid.efp_partition_num");
}
qpid::linearstore::journal::efpDataSize_kib_t localEfpFileSizeKib = defaultEfpFileSize_kib;
- value = args_.get("qpid.efp_file_size");
+ value = args_.get("qpid.efp_pool_file_size");
if (value.get() != 0 && !value->empty() && value->convertsTo<int>()) {
- localEfpFileSizeKib = chkEfpFileSizeKiB((uint32_t)value->get<int>(),"qpid.efp_file_size" );
+ localEfpFileSizeKib = chkEfpFileSizeKiB((uint32_t)value->get<int>(), "qpid.efp_pool_file_size");
}
return getEmptyFilePool(localEfpPartition, localEfpFileSizeKib);
}
@@ -1488,21 +1488,21 @@
std::string MessageStoreImpl::getJrnlBaseDir()
{
std::ostringstream dir;
- dir << storeDir << "/" << storeTopLevelDir << "/jrnl/" ;
+ dir << storeDir << "/" << storeTopLevelDir << "/jrnl2/" ;
return dir.str();
}
std::string MessageStoreImpl::getBdbBaseDir()
{
std::ostringstream dir;
- dir << storeDir << "/" << storeTopLevelDir << "/dat/" ;
+ dir << storeDir << "/" << storeTopLevelDir << "/dat2/" ;
return dir.str();
}
std::string MessageStoreImpl::getTplBaseDir()
{
std::ostringstream dir;
- dir << storeDir << "/" << storeTopLevelDir << "/tpl/" ;
+ dir << storeDir << "/" << storeTopLevelDir << "/tpl2/" ;
return dir.str();
}
diff --git a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePool.cpp b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePool.cpp
index 18f4d3a..08db3f7 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePool.cpp
+++ b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePool.cpp
@@ -59,10 +59,16 @@
EmptyFilePool::~EmptyFilePool() {}
void EmptyFilePool::initialize() {
-//std::cout << "*** Initializing EFP " << efpDataSize_kib_ << "k in partition " << partitionPtr_->getPartitionNumber() << "; efpDirectory=" << efpDirectory_ << std::endl; // DEBUG
- std::vector<std::string> dirList;
+ if (::mkdir(efpDirectory_.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) { // Create EFP dir if it does not yet exist
+ if (errno != EEXIST) {
+ std::ostringstream oss;
+ oss << "directory=" << efpDirectory_ << " " << FORMAT_SYSERR(errno);
+ throw jexception(jerrno::JERR_EFP_MKDIR, oss.str(), "EmptyFilePool", "initialize");
+ }
+ }
// Process empty files in main dir
+ std::vector<std::string> dirList;
jdir::read_dir(efpDirectory_, dirList, false, true, false, false);
for (std::vector<std::string>::iterator i = dirList.begin(); i != dirList.end(); ++i) {
size_t dotPos = i->rfind(".");
@@ -122,14 +128,14 @@
std::string EmptyFilePool::takeEmptyFile(const std::string& destDirectory) {
std::string emptyFileName = popEmptyFile();
- std::string newFileName = efpDirectory_ + "/" + s_inuseFileDirectory_ + emptyFileName.substr(emptyFileName.rfind('/'));
+ std::string newFileName = efpDirectory_ + "/" + s_inuseFileDirectory_ + emptyFileName.substr(emptyFileName.rfind('/')); // NOTE: substr() includes leading '/'
std::string symlinkName = destDirectory + emptyFileName.substr(emptyFileName.rfind('/')); // NOTE: substr() includes leading '/'
- if (moveFile(emptyFileName, newFileName)) {
+ if (!moveFile(emptyFileName, newFileName)) {
// Try again with new UUID for file name
newFileName = efpDirectory_ + "/" + s_inuseFileDirectory_ + "/" + getEfpFileName();
- if (moveFile(emptyFileName, newFileName)) {
+ if (!moveFile(emptyFileName, newFileName)) {
//std::cerr << "*** DEBUG: pushEmptyFile " << emptyFileName << "from EmptyFilePool::takeEmptyFile()" << std::endl; // DEBUG
- pushEmptyFile(emptyFileName);
+ pushEmptyFile(emptyFileName); // Return empty file to pool
std::ostringstream oss;
oss << "file=\"" << emptyFileName << "\" dest=\"" << newFileName << "\"" << FORMAT_SYSERR(errno);
throw jexception(jerrno::JERR_JDIR_FMOVE, oss.str(), "EmptyFilePool", "takeEmptyFile");
@@ -138,7 +144,7 @@
if (createSymLink(newFileName, symlinkName)) {
std::ostringstream oss;
oss << "file=\"" << emptyFileName << "\" dest=\"" << newFileName << "\" symlink=\"" << symlinkName << "\"" << FORMAT_SYSERR(errno);
- throw jexception(jerrno::JERR_EFP_SYMLINK, oss.str(), "EmptyFilePool", "takeEmptyFile");
+ throw jexception(jerrno::JERR__SYMLINK, oss.str(), "EmptyFilePool", "takeEmptyFile");
}
return symlinkName;
}
@@ -189,12 +195,27 @@
}
// --- protected functions ---
+void EmptyFilePool::checkIosState(std::ofstream& ofs,
+ const uint32_t jerrno,
+ const std::string& fqFileName,
+ const std::string& operation,
+ const std::string& errorMessage,
+ const std::string& className,
+ const std::string& fnName) {
+ if (!ofs.good()) {
+ if (ofs.is_open()) {
+ ofs.close();
+ }
+ std::ostringstream oss;
+ oss << "IO failure: eofbit=" << (ofs.eof()?"T":"F") << " failbit=" << (ofs.fail()?"T":"F") << " badbit="
+ << (ofs.bad()?"T":"F") << " file=" << fqFileName << " operation=" << operation << ": " << errorMessage;
+ throw jexception(jerrno, oss.str(), className, fnName);
+ }
+}
std::string EmptyFilePool::createEmptyFile() {
std::string efpfn = getEfpFileName();
- if (!overwriteFileContents(efpfn)) {
- // TODO: handle failure to prepare new file here
- }
+ overwriteFileContents(efpfn);
return efpfn;
}
@@ -226,24 +247,20 @@
}
}
-bool EmptyFilePool::overwriteFileContents(const std::string& fqFileName) {
+void EmptyFilePool::overwriteFileContents(const std::string& fqFileName) {
::file_hdr_t fh;
::file_hdr_create(&fh, QLS_FILE_MAGIC, QLS_JRNL_VERSION, QLS_JRNL_FHDR_RES_SIZE_SBLKS, partitionPtr_->getPartitionNumber(), efpDataSize_kib_);
std::ofstream ofs(fqFileName.c_str(), std::ofstream::out | std::ofstream::binary);
- if (ofs.good()) {
- ofs.write((char*)&fh, sizeof(::file_hdr_t));
- uint64_t rem = ((efpDataSize_kib_ + (QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_KIB)) * 1024) - sizeof(::file_hdr_t);
- while (rem--)
- ofs.put('\0');
- ofs.close();
- return true;
-//std::cout << "*** WARNING: EFP " << efpDirectory_ << " is empty - created new journal file " << fqFileName.substr(fqFileName.rfind('/') + 1) << " on the fly" << std::endl; // DEBUG
- } else {
- std::ostringstream oss;
- oss << "std::ofstream ofs: file=\"" << fqFileName.c_str() << "\"" << " failed to be open";
- throw jexception(jerrno::JERR_EFP_FOPEN, oss.str(), "EmptyFilePool", "overwriteFileContents");
+ checkIosState(ofs, jerrno::JERR_EFP_FOPEN, fqFileName, "constructor", "Failed to create file", "EmptyFilePool", "overwriteFileContents");
+ ofs.write((char*)&fh, sizeof(::file_hdr_t));
+ checkIosState(ofs, jerrno::JERR_EFP_FWRITE, fqFileName, "write()", "Failed to write header", "EmptyFilePool", "overwriteFileContents");
+ uint64_t rem = ((efpDataSize_kib_ + (QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_KIB)) * 1024) - sizeof(::file_hdr_t);
+ while (rem--) {
+ ofs.put('\0');
+ checkIosState(ofs, jerrno::JERR_EFP_FWRITE, fqFileName, "put()", "Failed to put \0", "EmptyFilePool", "overwriteFileContents");
}
- return false;
+ ofs.close();
+//std::cout << "*** WARNING: EFP " << efpDirectory_ << " is empty - created new journal file " << fqFileName.substr(fqFileName.rfind('/') + 1) << " on the fly" << std::endl; // DEBUG
}
std::string EmptyFilePool::popEmptyFile() {
@@ -271,7 +288,7 @@
void EmptyFilePool::returnEmptyFile(const std::string& emptyFileName) {
std::string returnedFileName = efpDirectory_ + "/" + s_returnedFileDirectory_ + emptyFileName.substr(emptyFileName.rfind('/')); // NOTE: substr() includes leading '/'
- if (moveFile(emptyFileName, returnedFileName)) {
+ if (!moveFile(emptyFileName, returnedFileName)) {
::unlink(emptyFileName.c_str());
//std::cerr << "*** WARNING: Unable to move file " << emptyFileName << " to " << returnedFileName << "; deleted." << std::endl; // DEBUG
}
@@ -283,7 +300,7 @@
overwriteFileContents(returnedFileName);
}
std::string sanitizedEmptyFileName = efpDirectory_ + returnedFileName.substr(returnedFileName.rfind('/')); // NOTE: substr() includes leading '/'
- if (moveFile(returnedFileName, sanitizedEmptyFileName)) {
+ if (!moveFile(returnedFileName, sanitizedEmptyFileName)) {
::unlink(returnedFileName.c_str());
//std::cerr << "*** WARNING: Unable to move file " << returnedFileName << " to " << sanitizedEmptyFileName << "; deleted." << std::endl; // DEBUG
} else {
@@ -395,18 +412,6 @@
return true;
}
-// static
-int EmptyFilePool::moveFile(const std::string& from,
- const std::string& to) {
- if (::rename(from.c_str(), to.c_str())) {
- if (errno == EEXIST) return errno; // File name exists
- std::ostringstream oss;
- oss << "file=\"" << from << "\" dest=\"" << to << "\"" << FORMAT_SYSERR(errno);
- throw jexception(jerrno::JERR_JDIR_FMOVE, oss.str(), "EmptyFilePool", "returnEmptyFile");
- }
- return 0;
-}
-
//static
int EmptyFilePool::createSymLink(const std::string& fqFileName,
const std::string& fqLinkName) {
@@ -414,7 +419,7 @@
if (errno == EEXIST) return errno; // File name exists
std::ostringstream oss;
oss << "file=\"" << fqFileName << "\" symlink=\"" << fqLinkName << "\"" << FORMAT_SYSERR(errno);
- throw jexception(jerrno::JERR_EFP_SYMLINK, oss.str(), "EmptyFilePool", "createSymLink");
+ throw jexception(jerrno::JERR__SYMLINK, oss.str(), "EmptyFilePool", "createSymLink");
}
return 0;
}
@@ -426,7 +431,7 @@
if (len < 0) {
std::ostringstream oss;
oss << "symlink=\"" << fqLinkName << "\"" << FORMAT_SYSERR(errno);
- throw jexception(jerrno::JERR_EFP_SYMLINK, oss.str(), "EmptyFilePool", "deleteSymlink");
+ throw jexception(jerrno::JERR__SYMLINK, oss.str(), "EmptyFilePool", "deleteSymlink");
}
::unlink(fqLinkName.c_str());
return std::string(buff, len);
@@ -455,4 +460,18 @@
}
+// static
+bool EmptyFilePool::moveFile(const std::string& from,
+ const std::string& to) {
+ if (::rename(from.c_str(), to.c_str())) {
+ if (errno == EEXIST) {
+ return false; // File name exists
+ }
+ std::ostringstream oss;
+ oss << "file=\"" << from << "\" dest=\"" << to << "\"" << FORMAT_SYSERR(errno);
+ throw jexception(jerrno::JERR_JDIR_FMOVE, oss.str(), "EmptyFilePool", "returnEmptyFile");
+ }
+ return true;
+}
+
}}}
diff --git a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePool.h b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePool.h
index 1a1264f..dc567ff 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePool.h
+++ b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePool.h
@@ -87,23 +87,30 @@
const efpPartitionNumber_t partitionNumber);
protected:
+ void checkIosState(std::ofstream& ofs,
+ const uint32_t jerrno,
+ const std::string& fqFileName,
+ const std::string& operation,
+ const std::string& errorMessage,
+ const std::string& className,
+ const std::string& fnName);
std::string createEmptyFile();
std::string getEfpFileName();
void initializeSubDirectory(const std::string& fqDirName);
- bool overwriteFileContents(const std::string& fqFileName);
+ void overwriteFileContents(const std::string& fqFileName);
std::string popEmptyFile();
void pushEmptyFile(const std::string fqFileName);
void returnEmptyFile(const std::string& emptyFileName);
void resetEmptyFileHeader(const std::string& fqFileName);
bool validateEmptyFile(const std::string& emptyFileName) const;
- static int moveFile(const std::string& fromFqPath,
- const std::string& toFqPath);
static int createSymLink(const std::string& fqFileName,
const std::string& fqLinkName);
static std::string deleteSymlink(const std::string& fqLinkName);
static bool isFile(const std::string& fqName);
static bool isSymlink(const std::string& fqName);
+ static bool moveFile(const std::string& fromFqPath,
+ const std::string& toFqPath);
};
}}}
diff --git a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolManager.cpp b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolManager.cpp
index 28e1b0b..a026797 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolManager.cpp
+++ b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolManager.cpp
@@ -74,6 +74,7 @@
if (!foundPartition) {
std::ostringstream oss1;
oss1 << qlsStorePath_ << "/" << EmptyFilePoolPartition::getPartionDirectoryName(defaultPartitionNumber_)
+ << "/" << EmptyFilePoolPartition::s_efpTopLevelDir_
<< "/" << EmptyFilePool::dirNameFromDataSize(defaultEfpDataSize_kib_);
jdir::create_dir(oss1.str());
insertPartition(defaultPartitionNumber_, oss1.str());
@@ -165,9 +166,10 @@
EmptyFilePool* EmptyFilePoolManager::getEmptyFilePool(const efpPartitionNumber_t partitionNumber,
const efpDataSize_kib_t efpDataSize_kib) {
EmptyFilePoolPartition* efppp = getEfpPartition(partitionNumber > 0 ? partitionNumber : defaultPartitionNumber_);
- if (efppp != 0)
- return efppp->getEmptyFilePool(efpDataSize_kib > 0 ? efpDataSize_kib : defaultEfpDataSize_kib_);
- return 0;
+ if (efppp == 0) {
+ return 0;
+ }
+ return efppp->getEmptyFilePool(efpDataSize_kib > 0 ? efpDataSize_kib : defaultEfpDataSize_kib_, true);
}
void EmptyFilePoolManager::getEmptyFilePools(std::vector<EmptyFilePool*>& emptyFilePoolList,
diff --git a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolPartition.cpp b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolPartition.cpp
index a31855e..12d2db7 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolPartition.cpp
+++ b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolPartition.cpp
@@ -32,6 +32,9 @@
namespace linearstore {
namespace journal {
+// static
+const std::string EmptyFilePoolPartition::s_efpTopLevelDir_("efp"); // Sets the top-level efp dir within a partition
+
EmptyFilePoolPartition::EmptyFilePoolPartition(const efpPartitionNumber_t partitionNum,
const std::string& partitionDir,
const bool overwriteBeforeReturnFlag,
@@ -57,72 +60,31 @@
void
EmptyFilePoolPartition::findEmptyFilePools() {
//std::cout << "*** EmptyFilePoolPartition::findEmptyFilePools(): Reading " << partitionDir_ << std::endl; // DEBUG
- std::vector<std::string> dirList;
- bool upgradeDirStructureFlag = false;
- std::string oldPartitionDir;
- jdir::read_dir(partitionDir_, dirList, true, false, false, false);
-//std::cout << "*** dirList.size()=" << dirList.size() << "; dirList.front()=" << dirList.front() << std::endl; // DEBUG
- if (dirList.size() == 1 && dirList.front().compare("efp") == 0) {
- upgradeDirStructureFlag = true;
- oldPartitionDir = partitionDir_ + "/efp";
-//std::cout << "*** oldPartitionDir=" << oldPartitionDir << std::endl; // DEBUG
- dirList.clear();
- jdir::read_dir(oldPartitionDir, dirList, true, false, false, false);
- }
+ std::string efpDir(partitionDir_ + "/" + s_efpTopLevelDir_);
+ if (jdir::is_dir(efpDir)) {
+ std::vector<std::string> dirList;
+ jdir::read_dir(efpDir, dirList, true, false, false, true);
for (std::vector<std::string>::iterator i = dirList.begin(); i != dirList.end(); ++i) {
- std::string fqFileName(partitionDir_ + "/" + *i);
- if (upgradeDirStructureFlag) {
- std::string fqOldFileName(partitionDir_ + "/efp/" + *i);
- if (::rename(fqOldFileName.c_str(), fqFileName.c_str())) {
- // File move failed
- std::ostringstream oss;
- oss << "File \'" << fqOldFileName << "\' could not be renamed to \'" << fqFileName << "\' (" << FORMAT_SYSERR(errno) << "); file deleted";
- journalLogRef_.log(JournalLog::LOG_WARN, oss.str());
- if (::unlink(fqOldFileName.c_str())) {
- std::ostringstream oss;
- oss << "File \'" << fqOldFileName << "\' could not be deleted (" << FORMAT_SYSERR(errno) << "\'; file orphaned";
- journalLogRef_.log(JournalLog::LOG_WARN, oss.str());
- }
- }
- }
- EmptyFilePool* efpp = 0;
- try {
- efpp = new EmptyFilePool(fqFileName, this, overwriteBeforeReturnFlag_, truncateFlag_, journalLogRef_);
- {
- slock l(efpMapMutex_);
- efpMap_[efpp->dataSize_kib()] = efpp;
- }
- }
- catch (const std::exception& e) {
- if (efpp != 0) {
- delete efpp;
- efpp = 0;
- }
- std::ostringstream oss;
- oss << "EmptyFilePool create failed: " << e.what();
- journalLogRef_.log(JournalLog::LOG_WARN, oss.str());
- }
- if (efpp != 0) {
- efpp->initialize();
- }
+ createEmptyFilePool(*i);
}
- if (upgradeDirStructureFlag) {
- std::string oldEfpDir(partitionDir_ + "/efp");
- if (::rmdir(oldEfpDir.c_str())) {
- // Unable to delete old "efp" dir
- std::ostringstream oss;
- oss << "Unable to delete old EFP directory \'" << oldEfpDir << "\' (" << FORMAT_SYSERR(errno) << "\'; directory orphaned";
- journalLogRef_.log(JournalLog::LOG_WARN, oss.str());
- }
- }
+ } else {
+ std::ostringstream oss;
+ oss << "Partition \"" << partitionDir_ << "\" does not contain top level EFP dir \"" << s_efpTopLevelDir_ << "\"";
+ journalLogRef_.log(JournalLog::LOG_WARN, oss.str());
+ }
}
-EmptyFilePool* EmptyFilePoolPartition::getEmptyFilePool(const efpDataSize_kib_t efpDataSize_kib) {
- slock l(efpMapMutex_);
- efpMapItr_t i = efpMap_.find(efpDataSize_kib);
- if (i == efpMap_.end())
- return 0;
- return i->second;
+EmptyFilePool* EmptyFilePoolPartition::getEmptyFilePool(const efpDataSize_kib_t efpDataSize_kib, const bool createIfNonExistent) {
+ {
+ slock l(efpMapMutex_);
+ efpMapItr_t i = efpMap_.find(efpDataSize_kib);
+ if (i != efpMap_.end())
+ return i->second;
+ }
+ if (createIfNonExistent) {
+ return createEmptyFilePool(efpDataSize_kib);
+ }
+ return 0;
}
void EmptyFilePoolPartition::getEmptyFilePools(std::vector<EmptyFilePool*>& efpList) {
@@ -183,7 +145,7 @@
//static
efpPartitionNumber_t EmptyFilePoolPartition::getPartitionNumber(const std::string& name) {
if (name.length() == 4 && name[0] == 'p' && ::isdigit(name[1]) && ::isdigit(name[2]) && ::isdigit(name[3])) {
- long pn = ::strtol(name.c_str() + 1, 0, 0);
+ long pn = ::strtol(name.c_str() + 1, 0, 10);
if (pn == 0 && errno) {
return 0;
} else {
@@ -195,12 +157,42 @@
// --- protected functions ---
+EmptyFilePool* EmptyFilePoolPartition::createEmptyFilePool(const efpDataSize_kib_t efpDataSize_kib) {
+ std::string fqEfpDirectoryName(partitionDir_ + "/" + EmptyFilePoolPartition::s_efpTopLevelDir_ + "/" + EmptyFilePool::dirNameFromDataSize(efpDataSize_kib));
+ return createEmptyFilePool(fqEfpDirectoryName);
+}
+
+EmptyFilePool* EmptyFilePoolPartition::createEmptyFilePool(const std::string fqEfpDirectoryName) {
+ EmptyFilePool* efpp = 0;
+ try {
+ efpp = new EmptyFilePool(fqEfpDirectoryName, this, overwriteBeforeReturnFlag_, truncateFlag_, journalLogRef_);
+ {
+ slock l(efpMapMutex_);
+ efpMap_[efpp->dataSize_kib()] = efpp;
+ }
+ }
+ catch (const std::exception& e) {
+ if (efpp != 0) {
+ delete efpp;
+ efpp = 0;
+ }
+ std::ostringstream oss;
+ oss << "EmptyFilePool create failed: " << e.what();
+ journalLogRef_.log(JournalLog::LOG_WARN, oss.str());
+ }
+ if (efpp != 0) {
+ efpp->initialize();
+ }
+ return efpp;
+}
+
void EmptyFilePoolPartition::validatePartitionDir() {
+ std::ostringstream ss;
if (!jdir::is_dir(partitionDir_)) {
- std::ostringstream ss;
ss << "Invalid partition directory: \'" << partitionDir_ << "\' is not a directory";
throw jexception(jerrno::JERR_EFP_BADPARTITIONDIR, ss.str(), "EmptyFilePoolPartition", "validatePartitionDir");
}
+
// TODO: other validity checks here
}
diff --git a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolPartition.h b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolPartition.h
index c653c6b..570e2b0 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolPartition.h
+++ b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolPartition.h
@@ -37,6 +37,8 @@
class EmptyFilePoolPartition
{
+public:
+ static const std::string s_efpTopLevelDir_;
protected:
typedef std::map<efpDataSize_kib_t, EmptyFilePool*> efpMap_t;
typedef efpMap_t::iterator efpMapItr_t;
@@ -59,7 +61,7 @@
virtual ~EmptyFilePoolPartition();
void findEmptyFilePools();
- EmptyFilePool* getEmptyFilePool(const efpDataSize_kib_t efpDataSize_kib);
+ EmptyFilePool* getEmptyFilePool(const efpDataSize_kib_t efpDataSize_kib, const bool createIfNonExistent);
void getEmptyFilePools(std::vector<EmptyFilePool*>& efpList);
void getEmptyFilePoolSizes_kib(std::vector<efpDataSize_kib_t>& efpDataSizesList) const;
std::string getPartitionDirectory() const;
@@ -70,6 +72,8 @@
static efpPartitionNumber_t getPartitionNumber(const std::string& name);
protected:
+ EmptyFilePool* createEmptyFilePool(const efpDataSize_kib_t efpDataSize_kib);
+ EmptyFilePool* createEmptyFilePool(const std::string fqEfpDirectoryName);
void validatePartitionDir();
};
diff --git a/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.cpp b/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.cpp
index 3f39913..73a16f0 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.cpp
+++ b/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.cpp
@@ -43,6 +43,7 @@
#include "qpid/linearstore/journal/utils/file_hdr.h"
#include <sstream>
#include <string>
+#include <unistd.h>
#include <vector>
namespace qpid {
@@ -101,7 +102,11 @@
analyzeJournalFileHeaders(efpIdentity);
if (journalEmptyFlag_) {
- *emptyFilePoolPtrPtr = emptyFilePoolManager->getEmptyFilePool(0, 0); // Use default EFP
+ if (uninitFileList_.empty()) {
+ *emptyFilePoolPtrPtr = emptyFilePoolManager->getEmptyFilePool(0, 0); // Use default EFP
+ } else {
+ *emptyFilePoolPtrPtr = emptyFilePoolManager->getEmptyFilePool(efpIdentity);
+ }
} else {
*emptyFilePoolPtrPtr = emptyFilePoolManager->getEmptyFilePool(efpIdentity);
if (! *emptyFilePoolPtrPtr) {
@@ -294,6 +299,7 @@
LinearFileController* lfcPtr) {
if (journalEmptyFlag_) {
if (uninitFileList_.size() > 0) {
+ // TODO: Handle case if uninitFileList_.size() > 1, but this should not happen in normal operation. Here we assume only one item in the list.
std::string uninitFile = uninitFileList_.back();
uninitFileList_.pop_back();
lfcPtr->restoreEmptyFile(uninitFile);
@@ -377,11 +383,28 @@
jdir::read_dir(journalDirectory_, directoryList, false, true, false, true);
for (stringListConstItr_t i = directoryList.begin(); i != directoryList.end(); ++i) {
bool hdrOk = readJournalFileHeader(*i, fileHeader, headerQueueName);
- if (!hdrOk || headerQueueName.empty()) {
+ bool hdrEmpty = ::is_file_hdr_reset(&fileHeader);
+ if (!hdrOk) {
std::ostringstream oss;
- oss << "Journal file " << (*i) << " is uninitialized or corrupted";
+ oss << "Journal file " << (*i) << " is corrupted or invalid";
journalLogRef_.log(JournalLog::LOG_WARN, queueName_, oss.str());
+ } else if (hdrEmpty) {
+ // Read symlink, find efp directory name which is efp size in KiB
+ // TODO: place this bit into a common function as it is also used in EmptyFilePool.cpp::deleteSymlink()
+ char buff[1024];
+ ssize_t len = ::readlink((*i).c_str(), buff, 1024);
+ if (len < 0) {
+ std::ostringstream oss;
+ oss << "symlink=\"" << (*i) << "\"" << FORMAT_SYSERR(errno);
+ throw jexception(jerrno::JERR__SYMLINK, oss.str(), "RecoveryManager", "analyzeJournalFileHeaders");
+ }
+ // Find second and third '/' from back of string, which contains the EFP directory name
+ *(::strrchr(buff, '/')) = '\0';
+ *(::strrchr(buff, '/')) = '\0';
+ int efpDataSize_kib = atoi(::strrchr(buff, '/') + 1);
uninitFileList_.push_back(*i);
+ efpIdentity.pn_ = fileHeader._efp_partition;
+ efpIdentity.ds_ = efpDataSize_kib;
} else if (headerQueueName.compare(queueName_) != 0) {
std::ostringstream oss;
oss << "Journal file " << (*i) << " belongs to queue \"" << headerQueueName << "\": ignoring";
@@ -406,6 +429,7 @@
}
}
+//std::cerr << "*** RecoveryManager::analyzeJournalFileHeaders() fileNumberMap_.size()=" << fileNumberMap_.size() << std::endl; // DEBUG
if (fileNumberMap_.empty()) {
journalEmptyFlag_ = true;
} else {
@@ -905,7 +929,9 @@
}
ifs.close();
::memcpy(&fileHeaderRef, buffer, sizeof(::file_hdr_t));
- if (::file_hdr_check(&fileHeaderRef, QLS_FILE_MAGIC, QLS_JRNL_VERSION, 0, QLS_MAX_QUEUE_NAME_LEN)) return false;
+ if (::file_hdr_check(&fileHeaderRef, QLS_FILE_MAGIC, QLS_JRNL_VERSION, 0, QLS_MAX_QUEUE_NAME_LEN)) {
+ return false;
+ }
queueName.assign(buffer + sizeof(::file_hdr_t), fileHeaderRef._queue_name_len);
return true;
}
diff --git a/qpid/cpp/src/qpid/linearstore/journal/jerrno.cpp b/qpid/cpp/src/qpid/linearstore/journal/jerrno.cpp
index 9d59039..ce88e78 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/jerrno.cpp
+++ b/qpid/cpp/src/qpid/linearstore/journal/jerrno.cpp
@@ -42,6 +42,7 @@
const uint32_t jerrno::JERR__RECNFOUND = 0x0109;
const uint32_t jerrno::JERR__NOTIMPL = 0x010a;
const uint32_t jerrno::JERR__NULL = 0x010b;
+const uint32_t jerrno::JERR__SYMLINK = 0x010c;
// class jcntl
const uint32_t jerrno::JERR_JCNTL_STOPPED = 0x0200;
@@ -112,10 +113,11 @@
const uint32_t jerrno::JERR_EFP_BADEFPDIRNAME = 0x0d03;
const uint32_t jerrno::JERR_EFP_NOEFP = 0x0d04;
const uint32_t jerrno::JERR_EFP_EMPTY = 0x0d05;
-const uint32_t jerrno::JERR_EFP_SYMLINK = 0x0d06;
-const uint32_t jerrno::JERR_EFP_LSTAT = 0x0d07;
-const uint32_t jerrno::JERR_EFP_BADFILETYPE = 0x0d08;
-const uint32_t jerrno::JERR_EFP_FOPEN = 0x0d09;
+const uint32_t jerrno::JERR_EFP_LSTAT = 0x0d06;
+const uint32_t jerrno::JERR_EFP_BADFILETYPE = 0x0d07;
+const uint32_t jerrno::JERR_EFP_FOPEN = 0x0d08;
+const uint32_t jerrno::JERR_EFP_FWRITE = 0x0d09;
+const uint32_t jerrno::JERR_EFP_MKDIR = 0x0d0a;
// Negative returns for some functions
const int32_t jerrno::AIO_TIMEOUT = -1;
@@ -140,6 +142,7 @@
_err_map[JERR__RECNFOUND] = "JERR__RECNFOUND: Record not found.";
_err_map[JERR__NOTIMPL] = "JERR__NOTIMPL: Not implemented";
_err_map[JERR__NULL] = "JERR__NULL: Operation on null pointer";
+ _err_map[JERR__SYMLINK] = "JERR__SYMLINK: Symbolic link operation failed";
// class jcntl
_err_map[JERR_JCNTL_STOPPED] = "JERR_JCNTL_STOPPED: Operation on stopped journal.";
@@ -210,10 +213,11 @@
_err_map[JERR_EFP_BADPARTITIONDIR] = "JERR_EFP_BADPARTITIONDIR: Invalid partition directory";
_err_map[JERR_EFP_NOEFP] = "JERR_EFP_NOEFP: No Empty File Pool found for given partition and empty file size";
_err_map[JERR_EFP_EMPTY] = "JERR_EFP_EMPTY: Empty File Pool is empty";
- _err_map[JERR_EFP_SYMLINK] = "JERR_EFP_SYMLINK: Symbolic link operation failed";
_err_map[JERR_EFP_LSTAT] = "JERR_EFP_LSTAT: lstat() operation failed";
_err_map[JERR_EFP_BADFILETYPE] = "JERR_EFP_BADFILETYPE: File type incorrect for operation";
_err_map[JERR_EFP_FOPEN] = "JERR_EFP_FOPEN: Unable to fopen file for write";
+ _err_map[JERR_EFP_FWRITE] = "JERR_EFP_FWRITE: Write failed";
+ _err_map[JERR_EFP_MKDIR] = "JERR_EFP_MKDIR: Directory creation failed";
//_err_map[] = "";
diff --git a/qpid/cpp/src/qpid/linearstore/journal/jerrno.h b/qpid/cpp/src/qpid/linearstore/journal/jerrno.h
index 77b18b1..6e81768 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/jerrno.h
+++ b/qpid/cpp/src/qpid/linearstore/journal/jerrno.h
@@ -60,6 +60,7 @@
static const uint32_t JERR__RECNFOUND; ///< Record not found
static const uint32_t JERR__NOTIMPL; ///< Not implemented
static const uint32_t JERR__NULL; ///< Operation on null pointer
+ static const uint32_t JERR__SYMLINK; ///< Symbolic Link operation failed
// class jcntl
static const uint32_t JERR_JCNTL_STOPPED; ///< Operation on stopped journal
@@ -130,10 +131,11 @@
static const uint32_t JERR_EFP_BADPARTITIONDIR; ///< Invalid partition directory
static const uint32_t JERR_EFP_NOEFP; ///< No EFP found for given partition and file size
static const uint32_t JERR_EFP_EMPTY; ///< EFP empty
- static const uint32_t JERR_EFP_SYMLINK; ///< Symbolic Link operation failed
static const uint32_t JERR_EFP_LSTAT; ///< lstat operation failed
static const uint32_t JERR_EFP_BADFILETYPE; ///< Bad file type
static const uint32_t JERR_EFP_FOPEN; ///< Unable to fopen file for write
+ static const uint32_t JERR_EFP_FWRITE; ///< Write failed
+ static const uint32_t JERR_EFP_MKDIR; ///< Directory creation failed
// Negative returns for some functions
static const int32_t AIO_TIMEOUT; ///< Timeout waiting for AIO return
diff --git a/qpid/cpp/src/qpid/linearstore/management-schema.xml b/qpid/cpp/src/qpid/linearstore/management-schema.xml
index a55883a..ebd3885 100644
--- a/qpid/cpp/src/qpid/linearstore/management-schema.xml
+++ b/qpid/cpp/src/qpid/linearstore/management-schema.xml
@@ -21,38 +21,24 @@
<class name="Store">
<property name="brokerRef" type="objId" access="RO" references="qpid.Broker" index="y" parentRef="y"/>
- <property name="location" type="sstr" access="RO" desc="Logical directory on disk"/>
- <!--property name="defaultInitialFileCount" type="uint16" access="RO" unit="file" desc="Default number of files initially allocated to each journal"/-->
- <!--property name="defaultDataFileSize" type="uint32" access="RO" unit="RdPg" desc="Default size of each journal data file"/-->
+ <property name="storeDir" type="sstr" access="RO" desc="Logical directory on disk"/>
<property name="tplIsInitialized" type="bool" access="RO" desc="Transaction prepared list has been initialized by a transactional prepare"/>
<property name="tplDirectory" type="sstr" access="RO" desc="Transaction prepared list directory"/>
<property name="tplWritePageSize" type="uint32" access="RO" unit="byte" desc="Page size in transaction prepared list write-page-cache"/>
<property name="tplWritePages" type="uint32" access="RO" unit="wpage" desc="Number of pages in transaction prepared list write-page-cache"/>
- <!--property name="tplInitialFileCount" type="uint16" access="RO" unit="file" desc="Number of files initially allocated to transaction prepared list journal"/-->
- <!--property name="tplDataFileSize" type="uint32" access="RO" unit="byte" desc="Size of each journal data file in transaction prepared list journal"/-->
- <!--property name="tplCurrentFileCount" type="uint32" access="RO" unit="file" desc="Number of files currently allocated to transaction prepared list journal"/-->
<statistic name="tplTransactionDepth" type="hilo32" unit="txn" desc="Number of currently enqueued prepared transactions"/>
<statistic name="tplTxnPrepares" type="count64" unit="record" desc="Total transaction prepares on transaction prepared list"/>
<statistic name="tplTxnCommits" type="count64" unit="record" desc="Total transaction commits on transaction prepared list"/>
<statistic name="tplTxnAborts" type="count64" unit="record" desc="Total transaction aborts on transaction prepared list"/>
- <statistic name="tplOutstandingAIOs" type="hilo32" unit="aio_op" desc="Deprecated"/>
</class>
<class name="Journal">
<property name="queueRef" type="objId" access="RO" references="qpid.Queue" isGeneralReference="y"/>
- <property name="name" type="sstr" access="RC" index="y"/>
+ <property name="queueName" type="sstr" access="RC" index="y"/>
<property name="directory" type="sstr" access="RO" desc="Directory containing journal files"/>
- <property name="baseFileName" type="sstr" access="RO" desc="Deprecated"/>
<property name="writePageSize" type="uint32" access="RO" unit="byte" desc="Deprecated"/>
<property name="writePages" type="uint32" access="RO" unit="wpage" desc="Deprecated"/>
- <property name="readPageSize" type="uint32" access="RO" unit="byte" desc="Deprecated"/>
- <property name="readPages" type="uint32" access="RO" unit="rpage" desc="Deprecated"/>
- <!--property name="initialFileCount" type="uint16" access="RO" unit="file" desc="Number of files initially allocated to this journal"/-->
- <!--property name="autoExpand" type="bool" access="RO" desc="Auto-expand enabled"/-->
- <!--property name="currentFileCount" type="uint16" access="RO" unit="file" desc="Number of files currently allocated to this journal"/-->
- <!--property name="maxFileCount" type="uint16" access="RO" unit="file" desc="Max number of files allowed for this journal"/-->
- <!--property name="dataFileSize" type="uint32" access="RO" unit="byte" desc="Size of each journal data file"/-->
<statistic name="recordDepth" type="hilo32" unit="record" desc="Number of currently enqueued records (durable messages)"/>
<statistic name="enqueues" type="count64" unit="record" desc="Total enqueued records on journal"/>
@@ -64,36 +50,5 @@
<statistic name="txnAborts" type="count64" unit="record" desc="Total transactional abort records on journal"/>
<statistic name="outstandingAIOs" type="hilo32" unit="aio_op" desc="Number of currently outstanding AIO requests in Async IO system"/>
-<!--
- The following are not yet "wired up" in JournalImpl.cpp
--->
- <statistic name="freeFileCount" type="hilo32" unit="file" desc="Deprecated"/>
- <statistic name="availableFileCount" type="hilo32" unit="file" desc="Deprecated"/>
- <statistic name="writeWaitFailures" type="count64" unit="record" desc="Deprecated"/>
- <statistic name="writeBusyFailures" type="count64" unit="record" desc="Deprecated"/>
- <statistic name="readRecordCount" type="count64" unit="record" desc="Deprecated"/>
- <statistic name="readBusyFailures" type="count64" unit="record" desc="Deprecated"/>
- <statistic name="writePageCacheDepth" type="hilo32" unit="wpage" desc="Deprecated"/>
- <statistic name="readPageCacheDepth" type="hilo32" unit="rpage" desc="Deprecated"/>
-
- <!--method name="expand" desc="Increase number of files allocated for this journal">
- <arg name="by" type="uint32" dir="I" desc="Number of files to increase journal size by"/>
- </method-->
</class>
-
- <eventArguments>
- <!--arg name="autoExpand" type="bool" desc="Journal auto-expand enabled"/-->
- <arg name="fileSize" type="uint32" desc="Journal file size in bytes"/>
- <arg name="jrnlId" type="sstr" desc="Journal Id"/>
- <arg name="numEnq" type="uint32" desc="Number of recovered enqueues"/>
- <arg name="numFiles" type="uint16" desc="Number of journal files"/>
- <arg name="numTxn" type="uint32" desc="Number of recovered transactions"/>
- <arg name="numTxnDeq" type="uint32" desc="Number of recovered transactional dequeues"/>
- <arg name="numTxnEnq" type="uint32" desc="Number of recovered transactional enqueues"/>
- <arg name="what" type="sstr" desc="Description of event"/>
- </eventArguments>
- <event name="enqThresholdExceeded" sev="warn" args="jrnlId, what"/>
- <event name="created" sev="notice" args="jrnlId, fileSize, numFiles"/>
- <event name="full" sev="error" args="jrnlId, what"/>
- <event name="recovered" sev="notice" args="jrnlId, fileSize, numFiles, numEnq, numTxn, numTxnEnq, numTxnDeq"/>
</schema>
diff --git a/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.cpp b/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.cpp
index 763deb3..7f19ca7 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.cpp
@@ -242,7 +242,7 @@
}
}
-const uint32_t DEFAULT_DURABLE_TIMEOUT(15*60);//15 minutes
+const uint32_t DEFAULT_DURABLE_TIMEOUT(2*60);//2 minutes
const uint32_t DEFAULT_TIMEOUT(0);
}
@@ -267,7 +267,7 @@
bind(link, RELIABILITY, reliability);
durableNode = test(node, DURABLE);
durableLink = test(link, DURABLE);
- timeout = get(link, TIMEOUT, durableLink ? DEFAULT_DURABLE_TIMEOUT : DEFAULT_TIMEOUT);
+ timeout = get(link, TIMEOUT, durableLink && reliability != AT_LEAST_ONCE ? DEFAULT_DURABLE_TIMEOUT : DEFAULT_TIMEOUT);
std::string mode;
if (bind(address, MODE, mode)) {
if (mode == BROWSE) {
@@ -571,7 +571,8 @@
bool AddressHelper::isUnreliable() const
{
- return reliability == AT_MOST_ONCE || reliability == UNRELIABLE;
+ return reliability == AT_MOST_ONCE || reliability == UNRELIABLE ||
+ (reliability.empty() && browse); // A browser defaults to unreliable.
}
const qpid::types::Variant::Map& AddressHelper::getNodeProperties() const
diff --git a/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.h b/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.h
index 66aee1a..3ee58ca 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.h
+++ b/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.h
@@ -44,7 +44,6 @@
const qpid::types::Variant::Map& getNodeProperties() const;
bool getLinkSource(std::string& out) const;
bool getLinkTarget(std::string& out) const;
- bool getBrowse() const { return browse; }
const qpid::types::Variant::Map& getLinkProperties() const;
static std::string getLinkName(const Address& address);
private:
diff --git a/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp b/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp
index 9e3f957..fedab42 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp
@@ -292,7 +292,7 @@
QPID_LOG(debug, "Received message of " << encoded->getSize() << " bytes: ");
encoded->init(impl);
impl.setEncoded(encoded);
- impl.setInternalId(ssn->record(current, lnk->getBrowse()));
+ impl.setInternalId(ssn->record(current));
pn_link_advance(lnk->receiver);
if (lnk->capacity) {
pn_link_flow(lnk->receiver, 1);
diff --git a/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.cpp b/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.cpp
index 4541061..5e07070 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.cpp
@@ -36,12 +36,10 @@
address(a),
helper(address),
receiver(pn_receiver(session, name.c_str())),
- capacity(0), used(0)
-{}
-
+ capacity(0), used(0) {}
ReceiverContext::~ReceiverContext()
{
- //pn_link_free(receiver);
+ pn_link_free(receiver);
}
void ReceiverContext::setCapacity(uint32_t c)
diff --git a/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.h b/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.h
index 8ded487..2b4e8e1 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.h
+++ b/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.h
@@ -60,8 +60,6 @@
void verify();
Address getAddress() const;
bool hasCurrent();
- bool getBrowse() const { return helper.getBrowse(); }
-
private:
friend class ConnectionContext;
const std::string name;
diff --git a/qpid/cpp/src/qpid/messaging/amqp/SenderContext.cpp b/qpid/cpp/src/qpid/messaging/amqp/SenderContext.cpp
index 1a254c1..2a48b22 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/SenderContext.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/SenderContext.cpp
@@ -30,6 +30,7 @@
#include "qpid/messaging/Message.h"
#include "qpid/messaging/MessageImpl.h"
#include "qpid/log/Statement.h"
+#include "config.h"
extern "C" {
#include <proton/engine.h>
}
@@ -49,7 +50,7 @@
SenderContext::~SenderContext()
{
- //pn_link_free(sender);
+ pn_link_free(sender);
}
void SenderContext::close()
@@ -510,7 +511,11 @@
{
pn_delivery_tag_t tag;
tag.size = sizeof(id);
+#ifdef NO_PROTON_DELIVERY_TAG_T
+ tag.start = reinterpret_cast<const char*>(&id);
+#else
tag.bytes = reinterpret_cast<const char*>(&id);
+#endif
token = pn_delivery(sender, tag);
pn_link_send(sender, encoded.getData(), encoded.getSize());
if (unreliable) {
diff --git a/qpid/cpp/src/qpid/messaging/amqp/SessionContext.cpp b/qpid/cpp/src/qpid/messaging/amqp/SessionContext.cpp
index f2b7b24..824b958 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/SessionContext.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/SessionContext.cpp
@@ -110,10 +110,11 @@
return 0;//TODO
}
-qpid::framing::SequenceNumber SessionContext::record(pn_delivery_t* delivery, bool browse)
+qpid::framing::SequenceNumber SessionContext::record(pn_delivery_t* delivery)
{
qpid::framing::SequenceNumber id = next++;
- if (!browse) unacked[id] = delivery;
+ if (!pn_delivery_settled(delivery))
+ unacked[id] = delivery;
QPID_LOG(debug, "Recorded delivery " << id << " -> " << delivery);
return id;
}
diff --git a/qpid/cpp/src/qpid/messaging/amqp/SessionContext.h b/qpid/cpp/src/qpid/messaging/amqp/SessionContext.h
index b347c32..8c2bb04 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/SessionContext.h
+++ b/qpid/cpp/src/qpid/messaging/amqp/SessionContext.h
@@ -75,7 +75,7 @@
qpid::framing::SequenceNumber next;
std::string name;
- qpid::framing::SequenceNumber record(pn_delivery_t*, bool browse);
+ qpid::framing::SequenceNumber record(pn_delivery_t*);
void acknowledge();
void acknowledge(const qpid::framing::SequenceNumber& id, bool cummulative);
void acknowledge(DeliveryMap::iterator begin, DeliveryMap::iterator end);
diff --git a/qpid/cpp/src/qpid/sys/AsynchIOHandler.cpp b/qpid/cpp/src/qpid/sys/AsynchIOHandler.cpp
index bb59530..7be625a 100644
--- a/qpid/cpp/src/qpid/sys/AsynchIOHandler.cpp
+++ b/qpid/cpp/src/qpid/sys/AsynchIOHandler.cpp
@@ -150,7 +150,7 @@
if (!codec) {
//TODO: may still want to revise this...
//send valid version header & close connection.
- write(framing::ProtocolInitiation(framing::highestProtocolVersion));
+ write(framing::ProtocolInitiation(factory->supportedVersion()));
readError = true;
aio->queueWriteClose();
} else {
diff --git a/qpid/cpp/src/qpid/sys/ConnectionCodec.h b/qpid/cpp/src/qpid/sys/ConnectionCodec.h
index 969a387..8b5b69c 100644
--- a/qpid/cpp/src/qpid/sys/ConnectionCodec.h
+++ b/qpid/cpp/src/qpid/sys/ConnectionCodec.h
@@ -60,6 +60,8 @@
virtual ConnectionCodec* create(
OutputControl&, const std::string& id, const SecuritySettings&
) = 0;
+
+ virtual framing::ProtocolVersion supportedVersion() const = 0;
};
};
diff --git a/qpid/cpp/src/tests/assertions.py b/qpid/cpp/src/tests/assertions.py
index f1db21b..930afd1 100644
--- a/qpid/cpp/src/tests/assertions.py
+++ b/qpid/cpp/src/tests/assertions.py
@@ -177,3 +177,18 @@
assert False, "Expected assertion to fail on unspecified option"
except AssertionFailed: None
except MessagingError: None
+
+ def test_queue_autodelete_timeout(self):
+ name = str(uuid4())
+ # create subscription queue with 0-10 to be sure of name
+ ssn_0_10 = self.create_connection("amqp0-10", True).session()
+ ssn_0_10.receiver("amq.direct; {link:{name:%s,timeout:30}}" % name)
+ self.ssn.sender("%s; {assert:always, node:{x-declare:{arguments: {qpid.auto_delete_timeout: 30}}}}" % name)
+ ssn_0_10_other = self.create_connection("amqp0-10", True).session()
+ ssn_0_10_other.sender("%s; {assert:always, node:{x-declare:{arguments: {qpid.auto_delete_timeout: 30}}}}" % name)
+ try:
+ self.ssn.sender("%s; {assert:always, node:{x-declare:{arguments: {qpid.auto_delete_timeout: 60}}}}" % name)
+ ssn_0_10_other.sender("%s; {assert:always, node:{x-declare:{arguments: {qpid.auto_delete_timeout: 60}}}}" % name)
+ assert False, "Expected assertion to fail for auto_delete_timeout"
+ except AssertionFailed: None
+ except MessagingError: None
diff --git a/qpid/cpp/src/tests/txshift.cpp b/qpid/cpp/src/tests/txshift.cpp
index bf85bee..6ec28c7 100644
--- a/qpid/cpp/src/tests/txshift.cpp
+++ b/qpid/cpp/src/tests/txshift.cpp
@@ -40,7 +40,7 @@
struct Args : public qpid::TestOptions
{
std::string workQueue;
- size_t workers;
+ uint workers;
Args() : workQueue("txshift-control"), workers(1)
{
@@ -178,7 +178,7 @@
worker.run();
} else {
boost::ptr_vector<Worker> workers;
- for (size_t i = 0; i < opts.workers; i++) {
+ for (uint i = 0; i < opts.workers; i++) {
workers.push_back(new Worker(connection, opts.workQueue));
}
std::for_each(workers.begin(), workers.end(), boost::bind(&Worker::start, _1));
diff --git a/qpid/doc/book/src/java-broker/Java-Broker-Appendix-Operational-Logging-Messages.xml b/qpid/doc/book/src/java-broker/Java-Broker-Appendix-Operational-Logging-Messages.xml
index 0c0adff..dbc12dc 100644
--- a/qpid/doc/book/src/java-broker/Java-Broker-Appendix-Operational-Logging-Messages.xml
+++ b/qpid/doc/book/src/java-broker/Java-Broker-Appendix-Operational-Logging-Messages.xml
@@ -378,6 +378,15 @@
<para>Indicates that broker was shut down due to fatal error.</para>
</entry>
</row>
+ <row id="Java-Broker-Appendix-Operation-Logging-Message-BRK-1017">
+ <entry morerows="1">BRK-1017</entry>
+ <entry>Process : PID <replaceable>process identifier</replaceable></entry>
+ </row>
+ <row>
+ <entry>
+ <para>Process identifier (PID) of the Broker process.</para>
+ </entry>
+ </row>
</tbody>
</tgroup>
</table>
diff --git a/qpid/doc/book/src/java-broker/commonEntities.xml b/qpid/doc/book/src/java-broker/commonEntities.xml
index 10b6aa9..cdee906 100644
--- a/qpid/doc/book/src/java-broker/commonEntities.xml
+++ b/qpid/doc/book/src/java-broker/commonEntities.xml
@@ -43,7 +43,7 @@
<!ENTITY oracleBdbProductOverviewUrl "http://www.oracle.com/technetwork/products/berkeleydb/overview/index-093405.html">
<!ENTITY oracleBdbRepGuideUrl "http://oracle.com/cd/E17277_02/html/ReplicationGuide/">
<!ENTITY oracleBdbJavaDocUrl "http://docs.oracle.com/cd/E17277_02/html/java/">
-<!ENTITY oracleBdbProductVersion "5.0.97">
+<!ENTITY oracleBdbProductVersion "5.0.104">
<!ENTITY oracleJmxTutorial "http://docs.oracle.com/javase/tutorial/jmx/">
diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java
index b0b31d6..c463861 100644
--- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java
+++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java
@@ -25,6 +25,7 @@
import java.util.List;
import java.util.Map;
import java.util.UUID;
+
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.IllegalStateException;
@@ -32,19 +33,20 @@
import javax.jms.InvalidSelectorException;
import javax.jms.JMSException;
import javax.jms.MessageListener;
+
import org.apache.qpid.amqp_1_0.client.AcknowledgeMode;
import org.apache.qpid.amqp_1_0.client.ConnectionErrorException;
import org.apache.qpid.amqp_1_0.client.Message;
import org.apache.qpid.amqp_1_0.client.Receiver;
import org.apache.qpid.amqp_1_0.client.Transaction;
import org.apache.qpid.amqp_1_0.jms.MessageConsumer;
+import org.apache.qpid.amqp_1_0.jms.MessageConsumerException;
import org.apache.qpid.amqp_1_0.jms.Queue;
import org.apache.qpid.amqp_1_0.jms.QueueReceiver;
import org.apache.qpid.amqp_1_0.jms.Session;
import org.apache.qpid.amqp_1_0.jms.TemporaryDestination;
import org.apache.qpid.amqp_1_0.jms.Topic;
import org.apache.qpid.amqp_1_0.jms.TopicSubscriber;
-import org.apache.qpid.amqp_1_0.jms.MessageConsumerException;
import org.apache.qpid.amqp_1_0.type.Binary;
import org.apache.qpid.amqp_1_0.type.Symbol;
import org.apache.qpid.amqp_1_0.type.UnsignedInteger;
@@ -333,10 +335,23 @@
message.setFromTopic(_isTopicSubscriber);
if(redelivery)
{
+ UnsignedInteger failures = message.getDeliveryFailures();
+
if(!message.getJMSRedelivered())
{
message.setJMSRedelivered(true);
}
+
+ if(failures == null)
+ {
+ message.setDeliveryFailures(UnsignedInteger.ONE);
+ }
+ else
+ {
+ message.setDeliveryFailures(failures.add(UnsignedInteger.ONE));
+ }
+
+
}
return message;
diff --git a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receiver.java b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receiver.java
index 826a757..1d9ec0f 100644
--- a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receiver.java
+++ b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receiver.java
@@ -530,6 +530,7 @@
{
release(msg);
}
+ _session.removeReceiver(this);
}
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java
index 5d65d6e..90bb4b7 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java
@@ -20,7 +20,8 @@
*/
package org.apache.qpid.server.store.berkeleydb;
-import org.apache.qpid.server.BrokerOptions;
+import java.util.Map;
+
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.LogRecorder;
@@ -49,10 +50,10 @@
public BDBSystemConfigImpl(final TaskExecutor taskExecutor,
final EventLogger eventLogger,
final LogRecorder logRecorder,
- final BrokerOptions brokerOptions,
+ final Map<String,Object> attributes,
final BrokerShutdownProvider brokerShutdownProvider)
{
- super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);
+ super(taskExecutor, eventLogger, logRecorder, attributes, brokerShutdownProvider);
}
@Override
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CoalescingCommiter.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CoalescingCommiter.java
index ff383ec..9643358 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CoalescingCommiter.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CoalescingCommiter.java
@@ -50,14 +50,17 @@
public void stop()
{
_commitThread.close();
- try
+ if (Thread.currentThread() != _commitThread)
{
- _commitThread.join();
- }
- catch (InterruptedException ie)
- {
- Thread.currentThread().interrupt();
- throw new RuntimeException("Commit thread has not shutdown", ie);
+ try
+ {
+ _commitThread.join();
+ }
+ catch (InterruptedException ie)
+ {
+ Thread.currentThread().interrupt();
+ throw new RuntimeException("Commit thread has not shutdown", ie);
+ }
}
}
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java
index c1c0698..c151a59 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java
@@ -392,6 +392,13 @@
}
}
+ if (dbe instanceof UnknownMasterException)
+ {
+ // when Master transits into Unknown state ( for example, due to mastership transfer)
+ // we need to abort any ongoing je operation without halting the Broker or VHN/VH
+ return new ConnectionScopedRuntimeException(String.format("Environment '%s' cannot finish JE operation because master is unknown", getNodeName()), dbe);
+ }
+
boolean restart = (noMajority || dbe instanceof RestartRequiredException);
if (restart)
{
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHost.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHost.java
index e7c247f..6fdee44 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHost.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHost.java
@@ -19,456 +19,17 @@
package org.apache.qpid.server.virtualhost.berkeleydb;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.ScheduledFuture;
-
-import org.apache.qpid.server.connection.IConnectionRegistry;
import org.apache.qpid.server.exchange.ExchangeImpl;
-import org.apache.qpid.server.logging.EventLogger;
-import org.apache.qpid.server.message.MessageDestination;
-import org.apache.qpid.server.message.MessageSource;
-import org.apache.qpid.server.model.AbstractConfiguredObject;
-import org.apache.qpid.server.model.BrokerModel;
-import org.apache.qpid.server.model.ConfiguredObject;
-import org.apache.qpid.server.model.Connection;
-import org.apache.qpid.server.model.Exchange;
-import org.apache.qpid.server.model.ManagedAttributeField;
-import org.apache.qpid.server.model.ManagedObject;
-import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
-import org.apache.qpid.server.model.Queue;
-import org.apache.qpid.server.model.State;
-import org.apache.qpid.server.model.VirtualHost;
-import org.apache.qpid.server.model.VirtualHostAlias;
-import org.apache.qpid.server.model.VirtualHostNode;
-import org.apache.qpid.server.protocol.LinkRegistry;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.stats.StatisticsCounter;
-import org.apache.qpid.server.store.DurableConfigurationStore;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.txn.DtxRegistry;
-import org.apache.qpid.server.virtualhost.ExchangeIsAlternateException;
-import org.apache.qpid.server.virtualhost.HouseKeepingTask;
-import org.apache.qpid.server.virtualhost.RequiredExchangeException;
+import org.apache.qpid.server.virtualhost.NonStandardVirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostImpl;
/**
Object that represents the VirtualHost whilst the VirtualHostNode is in the replica role. The
real virtualhost will be elsewhere in the group.
*/
-@ManagedObject( category = false, type = "BDB_HA_REPLICA", register = false )
-public class BDBHAReplicaVirtualHost extends AbstractConfiguredObject<BDBHAReplicaVirtualHost>
- implements VirtualHostImpl<BDBHAReplicaVirtualHost, AMQQueue<?>, ExchangeImpl<?>>,
- VirtualHost<BDBHAReplicaVirtualHost,AMQQueue<?>, ExchangeImpl<?>>
+public interface BDBHAReplicaVirtualHost<X extends BDBHAReplicaVirtualHost<X>>
+ extends VirtualHostImpl<X, AMQQueue<?>, ExchangeImpl<?>>,
+ NonStandardVirtualHost<X,AMQQueue<?>,ExchangeImpl<?>>
{
- private final StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
-
- @ManagedAttributeField
- private boolean _queue_deadLetterQueueEnabled;
-
- @ManagedAttributeField
- private long _housekeepingCheckPeriod;
-
- @ManagedAttributeField
- private long _storeTransactionIdleTimeoutClose;
-
- @ManagedAttributeField
- private long _storeTransactionIdleTimeoutWarn;
-
- @ManagedAttributeField
- private long _storeTransactionOpenTimeoutClose;
-
- @ManagedAttributeField
- private long _storeTransactionOpenTimeoutWarn;
- @ManagedAttributeField
- private int _housekeepingThreadCount;
-
- @ManagedObjectFactoryConstructor
- public BDBHAReplicaVirtualHost(final Map<String, Object> attributes, VirtualHostNode<?> virtualHostNode)
- {
- super(parentsMap(virtualHostNode), attributes);
-
- _messagesDelivered = new StatisticsCounter("messages-delivered-" + getName());
- _dataDelivered = new StatisticsCounter("bytes-delivered-" + getName());
- _messagesReceived = new StatisticsCounter("messages-received-" + getName());
- _dataReceived = new StatisticsCounter("bytes-received-" + getName());
- setState(State.UNAVAILABLE);
- }
-
- @Override
- protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes)
- {
- super.validateChange(proxyForValidation, changedAttributes);
-
- throwUnsupportedForReplica();
- }
-
- @Override
- public String getModelVersion()
- {
- return BrokerModel.MODEL_VERSION;
- }
-
- @Override
- protected <C extends ConfiguredObject> C addChild(final Class<C> childClass,
- final Map<String, Object> attributes,
- final ConfiguredObject... otherParents)
- {
- throwUnsupportedForReplica();
- return null;
- }
-
- @Override
- public ExchangeImpl createExchange(final Map<String, Object> attributes)
- {
- throwUnsupportedForReplica();
- return null;
- }
-
- @Override
- public void removeExchange(final ExchangeImpl<?> exchange, final boolean force)
- throws ExchangeIsAlternateException, RequiredExchangeException
- {
- throwUnsupportedForReplica();
- }
-
- @Override
- public MessageDestination getMessageDestination(final String name)
- {
- return null;
- }
-
- @Override
- public ExchangeImpl<?> getExchange(final String name)
- {
- return null;
- }
-
- @Override
- public AMQQueue<?> createQueue(final Map<String, Object> attributes)
- {
- throwUnsupportedForReplica();
- return null;
- }
-
- @Override
- public void executeTransaction(final TransactionalOperation op)
- {
- throwUnsupportedForReplica();
- }
-
- @Override
- public Collection<String> getExchangeTypeNames()
- {
- return getObjectFactory().getSupportedTypes(Exchange.class);
- }
-
- @Override
- public Collection<String> getSupportedExchangeTypes()
- {
- return getObjectFactory().getSupportedTypes(Exchange.class);
- }
-
- @Override
- public Collection<String> getSupportedQueueTypes()
- {
- return getObjectFactory().getSupportedTypes(Queue.class);
- }
-
- @Override
- public boolean isQueue_deadLetterQueueEnabled()
- {
- return false;
- }
-
- @Override
- public long getHousekeepingCheckPeriod()
- {
- return 0;
- }
-
- @Override
- public long getStoreTransactionIdleTimeoutClose()
- {
- return 0;
- }
-
- @Override
- public long getStoreTransactionIdleTimeoutWarn()
- {
- return 0;
- }
-
- @Override
- public long getStoreTransactionOpenTimeoutClose()
- {
- return 0;
- }
-
- @Override
- public long getStoreTransactionOpenTimeoutWarn()
- {
- return 0;
- }
-
- @Override
- public int getHousekeepingThreadCount()
- {
- return 0;
- }
-
- @Override
- public long getQueueCount()
- {
- return 0;
- }
-
- @Override
- public long getExchangeCount()
- {
- return 0;
- }
-
- @Override
- public long getConnectionCount()
- {
- return 0;
- }
-
- @Override
- public long getBytesIn()
- {
- return 0;
- }
-
- @Override
- public long getBytesOut()
- {
- return 0;
- }
-
- @Override
- public long getMessagesIn()
- {
- return 0;
- }
-
- @Override
- public long getMessagesOut()
- {
- return 0;
- }
-
- @Override
- public Collection<VirtualHostAlias> getAliases()
- {
- return Collections.emptyList();
- }
-
- @Override
- public Collection<Connection> getConnections()
- {
- return Collections.emptyList();
- }
-
- @Override
- public IConnectionRegistry getConnectionRegistry()
- {
- return null;
- }
-
- @Override
- public AMQQueue<?> getQueue(final String name)
- {
- return null;
- }
-
- @Override
- public MessageSource getMessageSource(final String name)
- {
- return null;
- }
-
- @Override
- public AMQQueue<?> getQueue(final UUID id)
- {
- return null;
- }
-
- @Override
- public Collection<AMQQueue<?>> getQueues()
- {
- return Collections.emptyList();
- }
-
- @Override
- public int removeQueue(final AMQQueue<?> queue)
- {
- throwUnsupportedForReplica();
- return 0;
- }
-
- @Override
- public Collection<ExchangeImpl<?>> getExchanges()
- {
- return Collections.emptyList();
- }
-
- @Override
- public DurableConfigurationStore getDurableConfigurationStore()
- {
- return null;
- }
-
- @Override
- public ExchangeImpl<?> getExchange(final UUID id)
- {
- return null;
- }
-
- @Override
- public MessageDestination getDefaultDestination()
- {
- return null;
- }
-
- @Override
- public MessageStore getMessageStore()
- {
- return null;
- }
-
- @Override
- public void setTargetSize(final long targetSize)
- {
-
- }
-
- @Override
- public long getTotalQueueDepthBytes()
- {
- return 0l;
- }
-
- @Override
- public org.apache.qpid.server.security.SecurityManager getSecurityManager()
- {
- return null;
- }
-
- @Override
- public void scheduleHouseKeepingTask(final long period, final HouseKeepingTask task)
- {
- }
-
- @Override
- public long getHouseKeepingTaskCount()
- {
- return 0;
- }
-
- @Override
- public long getHouseKeepingCompletedTaskCount()
- {
- return 0;
- }
-
- @Override
- public int getHouseKeepingPoolSize()
- {
- return 0;
- }
-
- @Override
- public void setHouseKeepingPoolSize(final int newSize)
- {
- }
-
- @Override
- public int getHouseKeepingActiveCount()
- {
- return 0;
- }
-
- @Override
- public DtxRegistry getDtxRegistry()
- {
- return null;
- }
-
- @Override
- public LinkRegistry getLinkRegistry(final String remoteContainerId)
- {
- return null;
- }
-
- @Override
- public ScheduledFuture<?> scheduleTask(final long delay, final Runnable timeoutTask)
- {
- throwUnsupportedForReplica();
- return null;
- }
-
- @Override
- public boolean getDefaultDeadLetterQueueEnabled()
- {
- return false;
- }
-
- @Override
- public EventLogger getEventLogger()
- {
- return null;
- }
-
- @Override
- public void registerMessageReceived(final long messageSize, final long timestamp)
- {
- throwUnsupportedForReplica();
- }
-
- @Override
- public void registerMessageDelivered(final long messageSize)
- {
- throwUnsupportedForReplica();
- }
-
- @Override
- public StatisticsCounter getMessageDeliveryStatistics()
- {
- return _messagesDelivered;
- }
-
- @Override
- public StatisticsCounter getMessageReceiptStatistics()
- {
- return _messagesReceived;
- }
-
- @Override
- public StatisticsCounter getDataDeliveryStatistics()
- {
- return _dataDelivered;
- }
-
- @Override
- public StatisticsCounter getDataReceiptStatistics()
- {
- return _dataReceived;
- }
-
- @Override
- public void resetStatistics()
- {
- }
-
- private void throwUnsupportedForReplica()
- {
- throw new IllegalStateException("The virtual host state of " + getState()
- + " does not permit this operation.");
- }
-
}
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHostImpl.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHostImpl.java
new file mode 100644
index 0000000..57b1d84
--- /dev/null
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHostImpl.java
@@ -0,0 +1,457 @@
+/*
+ * 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.virtualhost.berkeleydb;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ScheduledFuture;
+
+import org.apache.qpid.server.connection.IConnectionRegistry;
+import org.apache.qpid.server.exchange.ExchangeImpl;
+import org.apache.qpid.server.logging.EventLogger;
+import org.apache.qpid.server.message.MessageDestination;
+import org.apache.qpid.server.message.MessageSource;
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.ManagedAttributeField;
+import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHostAlias;
+import org.apache.qpid.server.model.VirtualHostNode;
+import org.apache.qpid.server.protocol.LinkRegistry;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.stats.StatisticsCounter;
+import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.txn.DtxRegistry;
+import org.apache.qpid.server.virtualhost.ExchangeIsAlternateException;
+import org.apache.qpid.server.virtualhost.HouseKeepingTask;
+import org.apache.qpid.server.virtualhost.RequiredExchangeException;
+
+/**
+ Object that represents the VirtualHost whilst the VirtualHostNode is in the replica role. The
+ real virtualhost will be elsewhere in the group.
+ */
+@ManagedObject( category = false, type = "BDB_HA_REPLICA", register = false )
+public class BDBHAReplicaVirtualHostImpl extends AbstractConfiguredObject<BDBHAReplicaVirtualHostImpl> implements BDBHAReplicaVirtualHost<BDBHAReplicaVirtualHostImpl>
+{
+ private final StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
+
+ @ManagedAttributeField
+ private boolean _queue_deadLetterQueueEnabled;
+
+ @ManagedAttributeField
+ private long _housekeepingCheckPeriod;
+
+ @ManagedAttributeField
+ private long _storeTransactionIdleTimeoutClose;
+
+ @ManagedAttributeField
+ private long _storeTransactionIdleTimeoutWarn;
+
+ @ManagedAttributeField
+ private long _storeTransactionOpenTimeoutClose;
+
+ @ManagedAttributeField
+ private long _storeTransactionOpenTimeoutWarn;
+ @ManagedAttributeField
+ private int _housekeepingThreadCount;
+
+ @ManagedObjectFactoryConstructor
+ public BDBHAReplicaVirtualHostImpl(final Map<String, Object> attributes, VirtualHostNode<?> virtualHostNode)
+ {
+ super(parentsMap(virtualHostNode), attributes);
+
+ _messagesDelivered = new StatisticsCounter("messages-delivered-" + getName());
+ _dataDelivered = new StatisticsCounter("bytes-delivered-" + getName());
+ _messagesReceived = new StatisticsCounter("messages-received-" + getName());
+ _dataReceived = new StatisticsCounter("bytes-received-" + getName());
+ setState(State.UNAVAILABLE);
+ }
+
+ @Override
+ protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes)
+ {
+ super.validateChange(proxyForValidation, changedAttributes);
+
+ throwUnsupportedForReplica();
+ }
+
+ @Override
+ public String getModelVersion()
+ {
+ return BrokerModel.MODEL_VERSION;
+ }
+
+ @Override
+ protected <C extends ConfiguredObject> C addChild(final Class<C> childClass,
+ final Map<String, Object> attributes,
+ final ConfiguredObject... otherParents)
+ {
+ throwUnsupportedForReplica();
+ return null;
+ }
+
+ @Override
+ public ExchangeImpl createExchange(final Map<String, Object> attributes)
+ {
+ throwUnsupportedForReplica();
+ return null;
+ }
+
+ @Override
+ public void removeExchange(final ExchangeImpl<?> exchange, final boolean force)
+ throws ExchangeIsAlternateException, RequiredExchangeException
+ {
+ throwUnsupportedForReplica();
+ }
+
+ @Override
+ public MessageDestination getMessageDestination(final String name)
+ {
+ return null;
+ }
+
+ @Override
+ public ExchangeImpl<?> getExchange(final String name)
+ {
+ return null;
+ }
+
+ @Override
+ public AMQQueue<?> createQueue(final Map<String, Object> attributes)
+ {
+ throwUnsupportedForReplica();
+ return null;
+ }
+
+ @Override
+ public void executeTransaction(final TransactionalOperation op)
+ {
+ throwUnsupportedForReplica();
+ }
+
+ @Override
+ public Collection<String> getExchangeTypeNames()
+ {
+ return getObjectFactory().getSupportedTypes(Exchange.class);
+ }
+
+ @Override
+ public boolean isQueue_deadLetterQueueEnabled()
+ {
+ return false;
+ }
+
+ @Override
+ public long getHousekeepingCheckPeriod()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getStoreTransactionIdleTimeoutClose()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getStoreTransactionIdleTimeoutWarn()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getStoreTransactionOpenTimeoutClose()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getStoreTransactionOpenTimeoutWarn()
+ {
+ return 0;
+ }
+
+ @Override
+ public int getHousekeepingThreadCount()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getQueueCount()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getExchangeCount()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getConnectionCount()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getBytesIn()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getBytesOut()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getMessagesIn()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getMessagesOut()
+ {
+ return 0;
+ }
+
+ @Override
+ public Collection<VirtualHostAlias> getAliases()
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Collection<Connection> getConnections()
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public IConnectionRegistry getConnectionRegistry()
+ {
+ return null;
+ }
+
+ @Override
+ public AMQQueue<?> getQueue(final String name)
+ {
+ return null;
+ }
+
+ @Override
+ public MessageSource getMessageSource(final String name)
+ {
+ return null;
+ }
+
+ @Override
+ public AMQQueue<?> getQueue(final UUID id)
+ {
+ return null;
+ }
+
+ @Override
+ public Collection<AMQQueue<?>> getQueues()
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public int removeQueue(final AMQQueue<?> queue)
+ {
+ throwUnsupportedForReplica();
+ return 0;
+ }
+
+ @Override
+ public Collection<ExchangeImpl<?>> getExchanges()
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public DurableConfigurationStore getDurableConfigurationStore()
+ {
+ return null;
+ }
+
+ @Override
+ public ExchangeImpl<?> getExchange(final UUID id)
+ {
+ return null;
+ }
+
+ @Override
+ public MessageDestination getDefaultDestination()
+ {
+ return null;
+ }
+
+ @Override
+ public MessageStore getMessageStore()
+ {
+ return null;
+ }
+
+ @Override
+ public void setTargetSize(final long targetSize)
+ {
+
+ }
+
+ @Override
+ public long getTotalQueueDepthBytes()
+ {
+ return 0l;
+ }
+
+ @Override
+ public org.apache.qpid.server.security.SecurityManager getSecurityManager()
+ {
+ return null;
+ }
+
+ @Override
+ public void scheduleHouseKeepingTask(final long period, final HouseKeepingTask task)
+ {
+ }
+
+ @Override
+ public long getHouseKeepingTaskCount()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getHouseKeepingCompletedTaskCount()
+ {
+ return 0;
+ }
+
+ @Override
+ public int getHouseKeepingPoolSize()
+ {
+ return 0;
+ }
+
+ @Override
+ public void setHouseKeepingPoolSize(final int newSize)
+ {
+ }
+
+ @Override
+ public int getHouseKeepingActiveCount()
+ {
+ return 0;
+ }
+
+ @Override
+ public DtxRegistry getDtxRegistry()
+ {
+ return null;
+ }
+
+ @Override
+ public LinkRegistry getLinkRegistry(final String remoteContainerId)
+ {
+ return null;
+ }
+
+ @Override
+ public ScheduledFuture<?> scheduleTask(final long delay, final Runnable timeoutTask)
+ {
+ throwUnsupportedForReplica();
+ return null;
+ }
+
+ @Override
+ public boolean getDefaultDeadLetterQueueEnabled()
+ {
+ return false;
+ }
+
+ @Override
+ public EventLogger getEventLogger()
+ {
+ return null;
+ }
+
+ @Override
+ public void registerMessageReceived(final long messageSize, final long timestamp)
+ {
+ throwUnsupportedForReplica();
+ }
+
+ @Override
+ public void registerMessageDelivered(final long messageSize)
+ {
+ throwUnsupportedForReplica();
+ }
+
+ @Override
+ public StatisticsCounter getMessageDeliveryStatistics()
+ {
+ return _messagesDelivered;
+ }
+
+ @Override
+ public StatisticsCounter getMessageReceiptStatistics()
+ {
+ return _messagesReceived;
+ }
+
+ @Override
+ public StatisticsCounter getDataDeliveryStatistics()
+ {
+ return _dataDelivered;
+ }
+
+ @Override
+ public StatisticsCounter getDataReceiptStatistics()
+ {
+ return _dataReceived;
+ }
+
+ @Override
+ public void resetStatistics()
+ {
+ }
+
+ private void throwUnsupportedForReplica()
+ {
+ throw new IllegalStateException("The virtual host state of " + getState()
+ + " does not permit this operation.");
+ }
+
+}
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHost.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHost.java
index 04ac1cf..2f31384 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHost.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHost.java
@@ -20,16 +20,18 @@
*/
package org.apache.qpid.server.virtualhost.berkeleydb;
-import java.util.List;
-
import org.apache.qpid.server.exchange.ExchangeImpl;
import org.apache.qpid.server.model.DerivedAttribute;
import org.apache.qpid.server.model.ManagedAttribute;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.store.SizeMonitoringSettings;
+import org.apache.qpid.server.virtualhost.NonStandardVirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostImpl;
-public interface BDBHAVirtualHost<X extends BDBHAVirtualHost<X>> extends VirtualHostImpl<X, AMQQueue<?>, ExchangeImpl<?>>, SizeMonitoringSettings
+public interface BDBHAVirtualHost<X extends BDBHAVirtualHost<X>>
+ extends VirtualHostImpl<X, AMQQueue<?>, ExchangeImpl<?>>,
+ SizeMonitoringSettings,
+ NonStandardVirtualHost<X,AMQQueue<?>,ExchangeImpl<?>>
{
String REMOTE_TRANSACTION_SYNCHRONIZATION_POLICY = "remoteTransactionSynchronizationPolicy";
String LOCAL_TRANSACTION_SYNCHRONIZATION_POLICY = "localTransactionSynchronizationPolicy";
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
index 8701708..2000897 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
@@ -21,15 +21,14 @@
package org.apache.qpid.server.virtualhostnode.berkeleydb;
import java.io.File;
-import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
-import java.nio.file.Files;
import java.security.PrivilegedAction;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -62,7 +61,6 @@
import org.apache.qpid.server.logging.messages.HighAvailabilityMessages;
import org.apache.qpid.server.logging.subjects.BDBHAVirtualHostNodeLogSubject;
import org.apache.qpid.server.logging.subjects.GroupLogSubject;
-import org.apache.qpid.server.model.AbstractConfiguredObject;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.BrokerModel;
import org.apache.qpid.server.model.ConfiguredObject;
@@ -88,7 +86,8 @@
import org.apache.qpid.server.virtualhost.berkeleydb.BDBHAVirtualHostImpl;
import org.apache.qpid.server.virtualhostnode.AbstractVirtualHostNode;
-@ManagedObject( category = false, type = BDBHAVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE )
+@ManagedObject( category = false, type = BDBHAVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE,
+ validChildTypes = "org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNodeImpl#getSupportedChildTypes()" )
public class BDBHAVirtualHostNodeImpl extends AbstractVirtualHostNode<BDBHAVirtualHostNodeImpl> implements
BDBHAVirtualHostNode<BDBHAVirtualHostNodeImpl>
{
@@ -637,12 +636,6 @@
createReplicaVirtualHost();
}
-
- private void onDetached()
- {
- closeVirtualHostIfExist();
- }
-
private void createReplicaVirtualHost()
{
try
@@ -694,9 +687,10 @@
onReplica();
break;
case DETACHED:
- onDetached();
+ closeVirtualHostIfExist();
break;
case UNKNOWN:
+ closeVirtualHostIfExist();
break;
default:
LOGGER.error("Unexpected state change: " + state);
@@ -1205,4 +1199,8 @@
abstract void perform();
}
+ public static Map<String, Collection<String>> getSupportedChildTypes()
+ {
+ return Collections.singletonMap(VirtualHost.class.getSimpleName(), (Collection<String>) Collections.singleton(BDBHAVirtualHostImpl.VIRTUAL_HOST_TYPE));
+ }
}
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeImpl.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeImpl.java
index e9edf9f..7e88ba2 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeImpl.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeImpl.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.server.virtualhostnode.berkeleydb;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Map;
import org.apache.qpid.server.logging.messages.ConfigStoreMessages;
@@ -32,7 +34,8 @@
import org.apache.qpid.server.store.berkeleydb.BDBConfigurationStore;
import org.apache.qpid.server.virtualhostnode.AbstractStandardVirtualHostNode;
-@ManagedObject(type = BDBVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE, category = false)
+@ManagedObject(type = BDBVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE, category = false,
+ validChildTypes = "org.apache.qpid.server.virtualhostnode.berkeleydb.BDBVirtualHostNodeImpl#getSupportedChildTypes()")
public class BDBVirtualHostNodeImpl extends AbstractStandardVirtualHostNode<BDBVirtualHostNodeImpl> implements BDBVirtualHostNode<BDBVirtualHostNodeImpl>
{
public static final String VIRTUAL_HOST_NODE_TYPE = "BDB";
@@ -70,4 +73,8 @@
return getClass().getSimpleName() + " [id=" + getId() + ", name=" + getName() + ", storePath=" + getStorePath() + "]";
}
+ public static Map<String, Collection<String>> getSupportedChildTypes()
+ {
+ return Collections.singletonMap(VirtualHost.class.getSimpleName(), getSupportedVirtualHostTypes(true));
+ }
}
diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/existinggroup/add.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/existinggroup/add.js
index ee467e6..532c37f 100644
--- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/existinggroup/add.js
+++ b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/existinggroup/add.js
@@ -39,6 +39,9 @@
registry.byId("addVirtualHostNode.helperNodeName").set("regExpGen", util.nameOrContextVarRegexp);
registry.byId("addVirtualHostNode.helperAddress").set("regExpGen", util.nodeAddressOrContextVarRegexp);
registry.byId("addVirtualHostNode.address").set("regExpGen", util.nodeAddressOrContextVarRegexp);
+
+ dom.byId("addVirtualHostNode.uploadFields").style.display = "none";
+
}
};
}
diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js
index 464a01b..c1aa9ff 100644
--- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js
+++ b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js
@@ -70,6 +70,9 @@
this.addVirtualHostNodePermittedNodes = registry.byId("addVirtualHostNode.permittedNodes");
registry.byId("addVirtualHostNode.groupName").set("regExpGen", util.nameOrContextVarRegexp);
+
+ dom.byId("addVirtualHostNode.uploadFields").style.display = "block";
+
},
_updatePermittedNodesJson: function ()
{
diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeTest.java
index 1f7a6ed..f2ed48d 100644
--- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeTest.java
+++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeTest.java
@@ -803,7 +803,7 @@
_replicaRolledback.countDown();
}
});
- assertTrue("Node 1 did not go into desired state",
+ assertTrue("Node 1 did not go into desired state and remained in state " + node1.getNodeState(),
node1StateChangeListener.awaitForStateChange(LISTENER_TIMEOUT, TimeUnit.SECONDS));
assertTrue("Node 1 did not experience rollback within timeout",
_replicaRolledback.await(LISTENER_TIMEOUT, TimeUnit.SECONDS));
diff --git a/qpid/java/bdbstore/systests/pom.xml b/qpid/java/bdbstore/systests/pom.xml
index b56488b..a5e9e2c 100644
--- a/qpid/java/bdbstore/systests/pom.xml
+++ b/qpid/java/bdbstore/systests/pom.xml
@@ -80,6 +80,16 @@
</dependencies>
<build>
+
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>${test.resource.directory}/test-profiles/test_resources</directory>
+ </resource>
+ </resources>
+
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
diff --git a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java
index fab889a..874b5eb 100644
--- a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java
+++ b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java
@@ -31,6 +31,7 @@
import javax.jms.Session;
import org.apache.log4j.Logger;
+import org.apache.qpid.server.configuration.BrokerProperties;
import org.apache.qpid.server.model.VirtualHostNode;
import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBVirtualHostNode;
import org.apache.qpid.test.utils.Piper;
@@ -151,15 +152,15 @@
Process backupProcess = null;
try
{
- String qpidHome = System.getProperty(QPID_HOME);
+ String qpidHome = QPID_HOME;
ProcessBuilder pb = new ProcessBuilder(qpidHome + BACKUP_SCRIPT, "-todir", backupToDir.getAbsolutePath(), "-fromdir", backupFromDir.getAbsolutePath());
pb.redirectErrorStream(true);
Map<String, String> env = pb.environment();
- env.put(QPID_HOME, qpidHome);
+ env.put(BrokerProperties.PROPERTY_QPID_HOME, qpidHome);
LOGGER.debug("Backup command is " + pb.command());
backupProcess = pb.start();
- Piper piper = new Piper(backupProcess.getInputStream(), _testcaseOutputStream, null, BACKUP_COMPLETE_MESSAGE);
+ Piper piper = new Piper(backupProcess.getInputStream(), null, BACKUP_COMPLETE_MESSAGE, "BACKUP", "");
piper.start();
piper.await(2, TimeUnit.SECONDS);
backupProcess.waitFor();
diff --git a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/GroupCreator.java b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/GroupCreator.java
index a209b47..97d380b 100644
--- a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/GroupCreator.java
+++ b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/GroupCreator.java
@@ -73,9 +73,9 @@
private static final String MANY_BROKER_URL_FORMAT = "amqp://guest:guest@/%s?brokerlist='%s'&failover='roundrobin?cyclecount='%d''";
private static final String BROKER_PORTION_FORMAT = "tcp://localhost:%d?connectdelay='%d',retries='%d'";
- private static final int FAILOVER_CYCLECOUNT = 20;
+ private static final int FAILOVER_CYCLECOUNT = 40;
private static final int FAILOVER_RETRIES = 0;
- private static final int FAILOVER_CONNECTDELAY = 500;
+ private static final int FAILOVER_CONNECTDELAY = 250;
private static final String SINGLE_BROKER_URL_WITH_RETRY_FORMAT = "amqp://guest:guest@/%s?brokerlist='tcp://localhost:%d?connectdelay='%d',retries='%d''";
private static final String SINGLE_BROKER_URL_WITHOUT_RETRY_FORMAT = "amqp://guest:guest@/%s?brokerlist='tcp://localhost:%d'";
@@ -209,7 +209,7 @@
{
try
{
- _testcase.startBroker(brokerPortNumber, brokerConfig);
+ _testcase.startBroker(brokerPortNumber, brokerConfig, null);
return "OK";
}
catch (Exception e)
diff --git a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/JMXManagementTest.java b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/JMXManagementTest.java
index 4fd3540..8933297 100644
--- a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/JMXManagementTest.java
+++ b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/JMXManagementTest.java
@@ -45,6 +45,7 @@
import org.apache.qpid.server.store.berkeleydb.jmx.ManagedBDBHAMessageStore;
import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNode;
import org.apache.qpid.systest.rest.RestTestHelper;
+import org.apache.qpid.test.utils.BrokerHolder;
import org.apache.qpid.test.utils.JMXTestUtils;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
import org.junit.Assert;
@@ -72,7 +73,7 @@
@Override
protected void setUp() throws Exception
{
- _brokerType = BrokerType.SPAWNED;
+ _brokerType = BrokerHolder.BrokerType.SPAWNED;
setTestClientSystemProperty("log4j.configuration", getBrokerCommandLog4JFile().toURI().toString());
diff --git a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java
index 50ca39c..7ec28bd 100644
--- a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java
+++ b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java
@@ -48,6 +48,7 @@
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNode;
+import org.apache.qpid.test.utils.BrokerHolder;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
import org.apache.qpid.test.utils.TestUtils;
@@ -75,7 +76,7 @@
@Override
protected void setUp() throws Exception
{
- _brokerType = BrokerType.SPAWNED;
+ _brokerType = BrokerHolder.BrokerType.SPAWNED;
assertTrue(isJavaBroker());
assertTrue(isBrokerStorePersistent());
diff --git a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/TwoNodeTest.java b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/TwoNodeTest.java
index 49ce60d..b06eaf9 100644
--- a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/TwoNodeTest.java
+++ b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/TwoNodeTest.java
@@ -28,6 +28,7 @@
import org.apache.qpid.jms.ConnectionURL;
import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNode;
+import org.apache.qpid.test.utils.BrokerHolder;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
public class TwoNodeTest extends QpidBrokerTestCase
@@ -47,7 +48,7 @@
@Override
protected void setUp() throws Exception
{
- _brokerType = BrokerType.SPAWNED;
+ _brokerType = BrokerHolder.BrokerType.SPAWNED;
setTestClientSystemProperty("log4j.configuration", getBrokerCommandLog4JFile().toURI().toString());
diff --git a/qpid/java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java b/qpid/java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java
index 317e0f7..52c1276 100644
--- a/qpid/java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java
+++ b/qpid/java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java
@@ -113,7 +113,8 @@
pw.println(";");
pw.println();
- pw.println("import org.apache.qpid.server.BrokerOptions;");
+ pw.println("import java.util.Map;");
+ pw.println();
pw.println("import org.apache.qpid.server.configuration.updater.TaskExecutor;");
pw.println("import org.apache.qpid.server.logging.EventLogger;");
pw.println("import org.apache.qpid.server.logging.LogRecorder;");
@@ -140,10 +141,10 @@
pw.println(" public "+objectSimpleName+" newInstance(final TaskExecutor taskExecutor,");
pw.println(" final EventLogger eventLogger,");
pw.println(" final LogRecorder logRecorder,");
- pw.println(" final BrokerOptions brokerOptions,");
+ pw.println(" final Map<String,Object> attributes,");
pw.println(" final BrokerShutdownProvider brokerShutdownProvider)");
pw.println(" {");
- pw.println(" return new "+objectSimpleName+"(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);");
+ pw.println(" return new "+objectSimpleName+"(taskExecutor, eventLogger, logRecorder, attributes, brokerShutdownProvider);");
pw.println(" }");
pw.println("}");
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java
index 245edc0..c18923f 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java
@@ -33,10 +33,13 @@
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
+import org.apache.qpid.server.configuration.BrokerProperties;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.configuration.updater.TaskExecutorImpl;
import org.apache.qpid.server.logging.EventLogger;
+import org.apache.qpid.server.logging.Log4jMessageLogger;
import org.apache.qpid.server.logging.LogRecorder;
+import org.apache.qpid.server.logging.MessageLogger;
import org.apache.qpid.server.logging.SystemOutMessageLogger;
import org.apache.qpid.server.logging.log4j.LoggingManagementFacade;
import org.apache.qpid.server.logging.messages.BrokerMessages;
@@ -44,30 +47,31 @@
import org.apache.qpid.server.model.SystemConfig;
import org.apache.qpid.server.plugin.PluggableFactoryLoader;
import org.apache.qpid.server.plugin.SystemConfigFactory;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.server.util.Action;
public class Broker implements BrokerShutdownProvider
{
private static final Logger LOGGER = Logger.getLogger(Broker.class);
private volatile Thread _shutdownHookThread;
- private volatile IApplicationRegistry _applicationRegistry;
private EventLogger _eventLogger;
private boolean _configuringOwnLogging = false;
private final TaskExecutor _taskExecutor = new TaskExecutorImpl();
- private final boolean _exitJVMOnShutdownWithNonZeroExitCode;
+
+ private SystemConfig _systemConfig;
+
+ private final Action<Integer> _shutdownAction;
+
public Broker()
{
- this(false);
+ this(null);
}
- public Broker(boolean exitJVMOnShutdownWithNonZeroExitCode)
+ public Broker(Action<Integer> shutdownAction)
{
- this._exitJVMOnShutdownWithNonZeroExitCode = exitJVMOnShutdownWithNonZeroExitCode;
+ _shutdownAction = shutdownAction;
}
protected static class InitException extends RuntimeException
@@ -96,9 +100,9 @@
{
try
{
- if (_applicationRegistry != null)
+ if(_systemConfig != null)
{
- _applicationRegistry.close();
+ _systemConfig.close();
}
_taskExecutor.stop();
@@ -110,9 +114,9 @@
LogManager.shutdown();
}
- if (_exitJVMOnShutdownWithNonZeroExitCode && exitStatusCode != 0)
+ if (_shutdownAction != null)
{
- System.exit(exitStatusCode);
+ _shutdownAction.performAction(exitStatusCode);
}
}
}
@@ -146,15 +150,29 @@
String storeLocation = options.getConfigurationStoreLocation();
String storeType = options.getConfigurationStoreType();
- _eventLogger.message(BrokerMessages.CONFIG(storeLocation));
+ if (options.isStartupLoggedToSystemOut())
+ {
+ _eventLogger.message(BrokerMessages.CONFIG(storeLocation));
+ }
//Allow skipping the logging configuration for people who are
//embedding the broker and want to configure it themselves.
if(!options.isSkipLoggingConfiguration())
{
- configureLogging(new File(options.getLogConfigFileLocation()), options.getLogWatchFrequency());
+ configureLogging(new File(options.getLogConfigFileLocation()), options.getLogWatchFrequency(), options.isStartupLoggedToSystemOut());
+ }
+ // Create the RootLogger to be used during broker operation
+ boolean statusUpdatesEnabled = Boolean.parseBoolean(System.getProperty(BrokerProperties.PROPERTY_STATUS_UPDATES, "true"));
+ MessageLogger messageLogger = new Log4jMessageLogger(statusUpdatesEnabled);
+ _eventLogger.setMessageLogger(messageLogger);
+
+ // Additionally, report BRK-1006 and BRK-1007 into log4j appenders
+ if(!options.isSkipLoggingConfiguration())
+ {
+ _eventLogger.message(BrokerMessages.LOG_CONFIG(new File(options.getLogConfigFileLocation()).getAbsolutePath()));
}
+ _eventLogger.message(BrokerMessages.CONFIG(storeLocation));
PluggableFactoryLoader<SystemConfigFactory> configFactoryLoader = new PluggableFactoryLoader<>(SystemConfigFactory.class);
SystemConfigFactory configFactory = configFactoryLoader.get(storeType);
@@ -169,21 +187,17 @@
LogRecorder logRecorder = new LogRecorder();
_taskExecutor.start();
- SystemConfig systemConfig = configFactory.newInstance(_taskExecutor, _eventLogger, logRecorder, options, this);
- systemConfig.open();
- DurableConfigurationStore store = systemConfig.getConfigurationStore();
-
- _applicationRegistry = new ApplicationRegistry(store, systemConfig);
+ _systemConfig = configFactory.newInstance(_taskExecutor, _eventLogger, logRecorder, options.convertToSystemConfigAttributes(), this);
try
{
- _applicationRegistry.initialise(options);
+ _systemConfig.open();
}
- catch(Exception e)
+ catch(RuntimeException e)
{
LOGGER.fatal("Exception during startup", e);
try
{
- _applicationRegistry.close();
+ _systemConfig.close();
}
catch(Exception ce)
{
@@ -194,12 +208,15 @@
}
- private void configureLogging(File logConfigFile, int logWatchTime) throws InitException, IOException
+ private void configureLogging(File logConfigFile, int logWatchTime, boolean startupLoggedToSystemOutput) throws InitException, IOException
{
_configuringOwnLogging = true;
if (logConfigFile.exists() && logConfigFile.canRead())
{
- _eventLogger.message(BrokerMessages.LOG_CONFIG(logConfigFile.getAbsolutePath()));
+ if (startupLoggedToSystemOutput)
+ {
+ _eventLogger.message(BrokerMessages.LOG_CONFIG(logConfigFile.getAbsolutePath()));
+ }
if (logWatchTime > 0)
{
@@ -297,15 +314,6 @@
}
}
- public org.apache.qpid.server.model.Broker getBroker()
- {
- if (_applicationRegistry == null)
- {
- return null;
- }
- return _applicationRegistry.getBroker();
- }
-
private class ShutdownService implements Runnable
{
public void run()
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java
index 9b3f290..c7cceb3 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java
@@ -29,6 +29,7 @@
import org.apache.qpid.server.configuration.BrokerProperties;
import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.SystemConfig;
import org.apache.qpid.server.util.StringUtil;
public class BrokerOptions
@@ -79,13 +80,23 @@
private boolean _overwriteConfigurationStore;
private Map<String, String> _configProperties = new HashMap<String,String>();
private String _initialSystemProperties;
+ private boolean _startupLoggedToSystemOut = true;
- public Map<String, Object> convertToSystemAttributes()
+ public Map<String, Object> convertToSystemConfigAttributes()
{
Map<String,Object> attributes = new HashMap<String, Object>();
attributes.put("storePath", getConfigurationStoreLocation());
attributes.put(ConfiguredObject.CONTEXT, getConfigProperties());
+
+ attributes.put(SystemConfig.MANAGEMENT_MODE, _managementMode);
+ attributes.put(SystemConfig.MANAGEMENT_MODE_QUIESCE_VIRTUAL_HOSTS, _managementModeQuiesceVhosts);
+ attributes.put(SystemConfig.MANAGEMENT_MODE_RMI_PORT_OVERRIDE, _managementModeRmiPortOverride);
+ attributes.put(SystemConfig.MANAGEMENT_MODE_JMX_PORT_OVERRIDE, _managementModeJmxPortOverride);
+ attributes.put(SystemConfig.MANAGEMENT_MODE_HTTP_PORT_OVERRIDE, _managementModeHttpPortOverride);
+ attributes.put(SystemConfig.MANAGEMENT_MODE_PASSWORD, _managementModePassword);
+ attributes.put(SystemConfig.INITIAL_CONFIGURATION_LOCATION, getInitialConfigurationLocation());
+ attributes.put(SystemConfig.STARTUP_LOGGED_TO_SYSTEM_OUT, isStartupLoggedToSystemOut());
return attributes;
}
@@ -372,4 +383,19 @@
return _configProperties.get(QPID_HOME_DIR);
}
+ /*
+ * Temporary method for test purposes
+ */
+ public boolean isStartupLoggedToSystemOut()
+ {
+ return _startupLoggedToSystemOut;
+ }
+
+ /*
+ * Temporary method for test purposes
+ */
+ public void setStartupLoggedToSystemOut(boolean startupLoggedToSystemOut)
+ {
+ this._startupLoggedToSystemOut = startupLoggedToSystemOut;
+ }
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java
index 4032ae2..bf45268 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java
@@ -30,7 +30,6 @@
import org.apache.log4j.Logger;
-import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfiguredObject;
@@ -40,6 +39,7 @@
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.Protocol;
import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.SystemConfig;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.model.adapter.BrokerAdapter;
import org.apache.qpid.server.store.ConfiguredObjectRecord;
@@ -62,14 +62,14 @@
private final DurableConfigurationStore _store;
private Map<UUID, ConfiguredObjectRecord> _cliEntries;
private Map<UUID, Object> _quiescedEntriesOriginalState;
- private final BrokerOptions _options;
+ private final SystemConfig<?> _systemConfig;
private ConfiguredObject<?> _parent;
private HashMap<UUID, ConfiguredObjectRecord> _records;
public ManagementModeStoreHandler(DurableConfigurationStore store,
- BrokerOptions options)
+ SystemConfig<?> systemConfig)
{
- _options = options;
+ _systemConfig = systemConfig;
_store = store;
}
@@ -82,16 +82,16 @@
_parent = parent;
_store.openConfigurationStore(parent, overwrite, initialRecords);
- _quiescedEntriesOriginalState = quiesceEntries(_options);
+ _quiescedEntriesOriginalState = quiesceEntries(_systemConfig);
_records = new HashMap<UUID, ConfiguredObjectRecord>();
final ConfiguredObjectRecordHandler localRecoveryHandler = new ConfiguredObjectRecordHandler()
{
private int _version;
- private boolean _quiesceRmiPort = _options.getManagementModeRmiPortOverride() > 0;
- private boolean _quiesceJmxPort = _options.getManagementModeJmxPortOverride() > 0;
- private boolean _quiesceHttpPort = _options.getManagementModeHttpPortOverride() > 0;
+ private boolean _quiesceRmiPort = _systemConfig.getManagementModeRmiPortOverride() > 0;
+ private boolean _quiesceJmxPort = _systemConfig.getManagementModeJmxPortOverride() > 0;
+ private boolean _quiesceHttpPort = _systemConfig.getManagementModeHttpPortOverride() > 0;
@Override
public void begin()
@@ -104,7 +104,7 @@
String entryType = object.getType();
Map<String, Object> attributes = object.getAttributes();
boolean quiesce = false;
- if (VIRTUAL_HOST_TYPE.equals(entryType) && _options.isManagementModeQuiesceVirtualHosts())
+ if (VIRTUAL_HOST_TYPE.equals(entryType) && _systemConfig.isManagementModeQuiesceVirtualHosts())
{
quiesce = true;
}
@@ -174,7 +174,7 @@
_store.visitConfiguredObjectRecords(localRecoveryHandler);
- _cliEntries = createPortsFromCommandLineOptions(_options);
+ _cliEntries = createPortsFromCommandLineOptions(_systemConfig);
for(ConfiguredObjectRecord entry : _cliEntries.values())
{
@@ -293,7 +293,7 @@
}
}
- private Map<UUID, ConfiguredObjectRecord> createPortsFromCommandLineOptions(BrokerOptions options)
+ private Map<UUID, ConfiguredObjectRecord> createPortsFromCommandLineOptions(SystemConfig<?> options)
{
int managementModeRmiPortOverride = options.getManagementModeRmiPortOverride();
if (managementModeRmiPortOverride < 0)
@@ -369,7 +369,7 @@
}
- private Map<UUID, Object> quiesceEntries(final BrokerOptions options)
+ private Map<UUID, Object> quiesceEntries(final SystemConfig<?> options)
{
final Map<UUID, Object> quiescedEntries = new HashMap<UUID, Object>();
final int managementModeRmiPortOverride = options.getManagementModeRmiPortOverride();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/EventLogger.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/EventLogger.java
index 70d1db7..ed97e14 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/EventLogger.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/EventLogger.java
@@ -59,4 +59,9 @@
{
_messageLogger = messageLogger;
}
+
+ public MessageLogger getMessageLogger()
+ {
+ return _messageLogger;
+ }
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/BrokerMessages.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/BrokerMessages.java
index cd21f53..58f7dfe 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/BrokerMessages.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/BrokerMessages.java
@@ -54,6 +54,7 @@
public static final String FLOW_TO_DISK_ACTIVE_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.flow_to_disk_active";
public static final String MAX_MEMORY_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.max_memory";
public static final String PLATFORM_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.platform";
+ public static final String PROCESS_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.process";
public static final String SHUTTING_DOWN_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.shutting_down";
public static final String MANAGEMENT_MODE_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.management_mode";
public static final String STARTUP_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.startup";
@@ -73,6 +74,7 @@
Logger.getLogger(FLOW_TO_DISK_ACTIVE_LOG_HIERARCHY);
Logger.getLogger(MAX_MEMORY_LOG_HIERARCHY);
Logger.getLogger(PLATFORM_LOG_HIERARCHY);
+ Logger.getLogger(PROCESS_LOG_HIERARCHY);
Logger.getLogger(SHUTTING_DOWN_LOG_HIERARCHY);
Logger.getLogger(MANAGEMENT_MODE_LOG_HIERARCHY);
Logger.getLogger(STARTUP_LOG_HIERARCHY);
@@ -399,6 +401,38 @@
/**
* Log a Broker message of the Format:
+ * <pre>BRK-1017 : Process : PID : {0}</pre>
+ * Optional values are contained in [square brackets] and are numbered
+ * sequentially in the method call.
+ *
+ */
+ public static LogMessage PROCESS(String param1)
+ {
+ String rawMessage = _messages.getString("PROCESS");
+
+ final Object[] messageArguments = {param1};
+ // Create a new MessageFormat to ensure thread safety.
+ // Sharing a MessageFormat and using applyPattern is not thread safe
+ MessageFormat formatter = new MessageFormat(rawMessage, _currentLocale);
+
+ final String message = formatter.format(messageArguments);
+
+ return new LogMessage()
+ {
+ public String toString()
+ {
+ return message;
+ }
+
+ public String getLogHierarchy()
+ {
+ return PROCESS_LOG_HIERARCHY;
+ }
+ };
+ }
+
+ /**
+ * Log a Broker message of the Format:
* <pre>BRK-1003 : Shutting down : {0} port {1,number,#}</pre>
* Optional values are contained in [square brackets] and are numbered
* sequentially in the method call.
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties
index 322335a..92417b6 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties
@@ -54,4 +54,7 @@
FLOW_TO_DISK_ACTIVE = BRK-1014 : Message flow to disk active : Message memory use {0,number,#}KB exceeds threshold {1,number,#.##}KB
FLOW_TO_DISK_INACTIVE = BRK-1015 : Message flow to disk inactive : Message memory use {0,number,#}KB within threshold {1,number,#.##}KB
-FATAL_ERROR = BRK-1016 : Fatal error : {0} : See log file for more information
\ No newline at end of file
+FATAL_ERROR = BRK-1016 : Fatal error : {0} : See log file for more information
+
+# 0 - pid
+PROCESS = BRK-1017 : Process : PID : {0}
\ No newline at end of file
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
index a2f4f4e..b9a4b32 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
@@ -556,9 +556,14 @@
{
}
+ protected boolean rethrowRuntimeExceptionsOnOpen()
+ {
+ return false;
+ }
+
protected final void handleExceptionOnOpen(RuntimeException e)
{
- if (e instanceof ServerScopedRuntimeException)
+ if (rethrowRuntimeExceptionsOnOpen() || e instanceof ServerScopedRuntimeException)
{
throw e;
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
index f8dac7c..b421c5a 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
@@ -31,16 +31,21 @@
import java.util.Map;
import java.util.UUID;
-import org.apache.qpid.server.BrokerOptions;
+import org.apache.qpid.common.QpidProperties;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.configuration.store.ManagementModeStoreHandler;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.logging.CompositeStartupMessageLogger;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.LogRecorder;
+import org.apache.qpid.server.logging.MessageLogger;
+import org.apache.qpid.server.logging.SystemOutMessageLogger;
import org.apache.qpid.server.logging.messages.BrokerMessages;
+import org.apache.qpid.server.store.BrokerStoreUpgraderAndRecoverer;
import org.apache.qpid.server.store.ConfiguredObjectRecord;
import org.apache.qpid.server.store.ConfiguredObjectRecordConverter;
import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.util.SystemUtils;
public abstract class AbstractSystemConfig<X extends SystemConfig<X>>
extends AbstractConfiguredObject<X> implements SystemConfig<X>
@@ -48,24 +53,47 @@
private static final UUID SYSTEM_ID = new UUID(0l, 0l);
private final EventLogger _eventLogger;
private final LogRecorder _logRecorder;
- private final BrokerOptions _brokerOptions;
private final BrokerShutdownProvider _brokerShutdownProvider;
private DurableConfigurationStore _configurationStore;
+ @ManagedAttributeField
+ private boolean _managementMode;
+
+ @ManagedAttributeField
+ private int _managementModeRmiPortOverride;
+
+ @ManagedAttributeField
+ private int _managementModeJmxPortOverride;
+
+ @ManagedAttributeField
+ private int _managementModeHttpPortOverride;
+
+ @ManagedAttributeField
+ private boolean _managementModeQuiesceVirtualHosts;
+
+ @ManagedAttributeField
+ private String _managementModePassword;
+
+ @ManagedAttributeField
+ private String _initialConfigurationLocation;
+
+ @ManagedAttributeField
+ private boolean _startupLoggedToSystemOut;
+
+
public AbstractSystemConfig(final TaskExecutor taskExecutor,
final EventLogger eventLogger,
final LogRecorder logRecorder,
- final BrokerOptions brokerOptions,
+ final Map<String,Object> attributes,
final BrokerShutdownProvider brokerShutdownProvider)
{
super(parentsMap(),
- updateAttributes(brokerOptions.convertToSystemAttributes()),
+ updateAttributes(attributes),
taskExecutor, BrokerModel.getInstance());
_eventLogger = eventLogger;
getTaskExecutor().start();
_logRecorder = logRecorder;
- _brokerOptions = brokerOptions;
_brokerShutdownProvider = brokerShutdownProvider;
}
@@ -84,12 +112,6 @@
}
@Override
- public State getState()
- {
- return State.ACTIVE;
- }
-
- @Override
public EventLogger getEventLogger()
{
return _eventLogger;
@@ -101,12 +123,6 @@
}
@Override
- public BrokerOptions getBrokerOptions()
- {
- return _brokerOptions;
- }
-
- @Override
protected void onClose()
{
try
@@ -155,17 +171,17 @@
super.onOpen();
_configurationStore = createStoreObject();
- if (_brokerOptions.isManagementMode())
+ if (isManagementMode())
{
- _configurationStore = new ManagementModeStoreHandler(_configurationStore, _brokerOptions);
+ _configurationStore = new ManagementModeStoreHandler(_configurationStore, this);
}
try
{
_configurationStore.openConfigurationStore(this,
- false,
- convertToConfigurationRecords(_brokerOptions.getInitialConfigurationLocation(),
- this));
+ false,
+ convertToConfigurationRecords(getInitialConfigurationLocation(),
+ this));
_configurationStore.upgradeStoreStructure();
}
catch (IOException e)
@@ -173,6 +189,66 @@
throw new IllegalArgumentException(e);
}
+
+
+ }
+
+ @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE)
+ protected void activate()
+ {
+ final EventLogger eventLogger = _eventLogger;
+
+ EventLogger startupLogger;
+ if (isStartupLoggedToSystemOut())
+ {
+ //Create the composite (logging+SystemOut MessageLogger to be used during startup
+ MessageLogger[] messageLoggers = {new SystemOutMessageLogger(), eventLogger.getMessageLogger()};
+
+ CompositeStartupMessageLogger startupMessageLogger = new CompositeStartupMessageLogger(messageLoggers);
+ startupLogger = new EventLogger(startupMessageLogger);
+ }
+ else
+ {
+ startupLogger = eventLogger;
+ }
+
+ startupLogger.message(BrokerMessages.STARTUP(QpidProperties.getReleaseVersion(),
+ QpidProperties.getBuildVersion()));
+
+ startupLogger.message(BrokerMessages.PLATFORM(System.getProperty("java.vendor"),
+ System.getProperty("java.runtime.version",
+ System.getProperty("java.version")),
+ SystemUtils.getOSName(),
+ SystemUtils.getOSVersion(),
+ SystemUtils.getOSArch()));
+
+ startupLogger.message(BrokerMessages.MAX_MEMORY(Runtime.getRuntime().maxMemory()));
+
+ if (SystemUtils.getProcessPid() != null)
+ {
+ startupLogger.message(BrokerMessages.PROCESS(SystemUtils.getProcessPid()));
+ }
+
+ BrokerStoreUpgraderAndRecoverer upgrader = new BrokerStoreUpgraderAndRecoverer(this);
+ upgrader.perform();
+
+ Broker broker = getBroker();
+
+ broker.setEventLogger(startupLogger);
+ broker.open();
+
+ if (broker.getState() == State.ACTIVE)
+ {
+ startupLogger.message(BrokerMessages.READY());
+ broker.setEventLogger(eventLogger);
+ }
+
+ }
+
+ @Override
+ protected final boolean rethrowRuntimeExceptionsOnOpen()
+ {
+ return true;
}
abstract protected DurableConfigurationStore createStoreObject();
@@ -216,8 +292,56 @@
}
@Override
+ public boolean isManagementMode()
+ {
+ return _managementMode;
+ }
+
+ @Override
+ public int getManagementModeRmiPortOverride()
+ {
+ return _managementModeRmiPortOverride;
+ }
+
+ @Override
+ public int getManagementModeJmxPortOverride()
+ {
+ return _managementModeJmxPortOverride;
+ }
+
+ @Override
+ public int getManagementModeHttpPortOverride()
+ {
+ return _managementModeHttpPortOverride;
+ }
+
+ @Override
+ public boolean isManagementModeQuiesceVirtualHosts()
+ {
+ return _managementModeQuiesceVirtualHosts;
+ }
+
+ @Override
+ public String getManagementModePassword()
+ {
+ return _managementModePassword;
+ }
+
+ @Override
+ public String getInitialConfigurationLocation()
+ {
+ return _initialConfigurationLocation;
+ }
+
+ @Override
public BrokerShutdownProvider getBrokerShutdownProvider()
{
return _brokerShutdownProvider;
}
+
+ @Override
+ public boolean isStartupLoggedToSystemOut()
+ {
+ return _startupLoggedToSystemOut;
+ }
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
index 9f15b23..6435124 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
@@ -40,10 +40,6 @@
String PLATFORM = "platform";
String PROCESS_PID = "processPid";
String PRODUCT_VERSION = "productVersion";
- String SUPPORTED_VIRTUALHOST_TYPES = "supportedVirtualHostTypes";
- String SUPPORTED_VIRTUALHOSTNODE_TYPES = "supportedVirtualHostNodeTypes";
- String SUPPORTED_AUTHENTICATION_PROVIDERS = "supportedAuthenticationProviders";
- String SUPPORTED_PREFERENCES_PROVIDER_TYPES = "supportedPreferencesProviderTypes";
String DEFAULT_VIRTUAL_HOST = "defaultVirtualHost";
String STATISTICS_REPORTING_PERIOD = "statisticsReportingPeriod";
String STATISTICS_REPORTING_RESET_ENABLED = "statisticsReportingResetEnabled";
@@ -110,18 +106,6 @@
@DerivedAttribute
String getProductVersion();
- @DerivedAttribute
- Collection<String> getSupportedVirtualHostNodeTypes();
-
- @DerivedAttribute
- Collection<String> getSupportedAuthenticationProviders();
-
- @DerivedAttribute
- Collection<String> getSupportedPreferencesProviderTypes();
-
- @DerivedAttribute
- Collection<String> getSupportedVirtualHostTypes();
-
@ManagedAttribute
String getDefaultVirtualHost();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java
index a1cbb0f..a9e9f26 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java
@@ -42,6 +42,9 @@
* 1.3 Truststore/Keystore type => trustStoreType / type => keyStoreType
* 1.4 Separate messageStoreSettings from virtualhost
* 2.0 Introduce VirtualHostNode as a child of a Broker instead of VirtualHost
+ * 2.1 Add VH aliases;
+ * Remove Broker#supportedVirtualHostNodeTypes, #supportedVirtualHostTypes, #supportedAuthenticationProviders,
+ * supportedPreferencesProviderTypes, VH#supportedExchangeTypes, VH#supportedQueueTypes
*/
public static final int MODEL_MAJOR_VERSION = 2;
public static final int MODEL_MINOR_VERSION = 1;
@@ -87,7 +90,6 @@
addRelationship(AuthenticationProvider.class, User.class);
addRelationship(AuthenticationProvider.class, PreferencesProvider.class);
- addRelationship(User.class, GroupMember.class);
addRelationship(GroupProvider.class, Group.class);
addRelationship(Group.class, GroupMember.class);
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java
index 8ca5ff3..d134c43 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java
@@ -21,8 +21,11 @@
package org.apache.qpid.server.model;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
import java.util.AbstractCollection;
import java.util.Arrays;
import java.util.Collection;
@@ -176,6 +179,9 @@
private final Map<Class<? extends ConfiguredObject>,Set<Class<? extends ManagedInterface>>> _allManagedInterfaces =
Collections.synchronizedMap(new HashMap<Class<? extends ConfiguredObject>, Set<Class<? extends ManagedInterface>>>());
+ private final Map<Class<? extends ConfiguredObject>, Map<String, Collection<String>>> _validChildTypes =
+ Collections.synchronizedMap(new HashMap<Class<? extends ConfiguredObject>, Map<String, Collection<String>>>());
+
public ConfiguredObjectTypeRegistry(Iterable<ConfiguredObjectRegistration> configuredObjectRegistrations, Collection<Class<? extends ConfiguredObject>> categoriesRestriction)
{
@@ -265,6 +271,96 @@
}
}
+
+ for(Class<? extends ConfiguredObject> type : types)
+ {
+ final ManagedObject annotation = type.getAnnotation(ManagedObject.class);
+ String validChildren = annotation.validChildTypes();
+ if(!"".equals(validChildren))
+ {
+ Method validChildTypesMethod = getValidChildTypesFunction(validChildren, type);
+ if(validChildTypesMethod != null)
+ {
+ try
+ {
+ _validChildTypes.put(type, (Map<String, Collection<String>>) validChildTypesMethod.invoke(null));
+ }
+ catch (IllegalAccessException | InvocationTargetException e)
+ {
+ throw new IllegalArgumentException("Exception while evaluating valid child types for " + type.getName(), e);
+ }
+ }
+
+ }
+ }
+ }
+
+ private static Method getValidChildTypesFunction(final String validValue, final Class<? extends ConfiguredObject> clazz)
+ {
+ if (validValue.matches("([\\w][\\w\\d_]+\\.)+[\\w][\\w\\d_\\$]*#[\\w\\d_]+\\s*\\(\\s*\\)"))
+ {
+ String function = validValue;
+ try
+ {
+ String className = function.split("#")[0].trim();
+ String methodName = function.split("#")[1].split("\\(")[0].trim();
+ Class<?> validValueCalculatingClass = Class.forName(className);
+ Method method = validValueCalculatingClass.getMethod(methodName);
+ if (Modifier.isStatic(method.getModifiers()) && Modifier.isPublic(method.getModifiers()))
+ {
+ if (Map.class.isAssignableFrom(method.getReturnType()))
+ {
+ if (method.getGenericReturnType() instanceof ParameterizedType)
+ {
+ Type keyType =
+ ((ParameterizedType) method.getGenericReturnType()).getActualTypeArguments()[0];
+ if (keyType == String.class)
+ {
+ Type valueType =
+ ((ParameterizedType) method.getGenericReturnType()).getActualTypeArguments()[1];
+ if (valueType instanceof ParameterizedType)
+ {
+ ParameterizedType paramType = (ParameterizedType) valueType;
+ final Type rawType = paramType.getRawType();
+ final Type[] args = paramType.getActualTypeArguments();
+ if (Collection.class.isAssignableFrom((Class<?>) rawType)
+ && args.length == 1
+ && args[0] == String.class)
+ {
+ return method;
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ throw new IllegalArgumentException("The validChildTypes of the class "
+ + clazz.getSimpleName()
+ + " has value '"
+ + validValue
+ + "' but the method does not meet the requirements - is it public and static");
+
+ }
+ catch (ClassNotFoundException | NoSuchMethodException e)
+ {
+ throw new IllegalArgumentException("The validChildTypes of the class "
+ + clazz.getSimpleName()
+ + " has value '"
+ + validValue
+ + "' which looks like it should be a method,"
+ + " but no such method could be used.", e);
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("The validChildTypes of the class "
+ + clazz.getSimpleName()
+ + " has value '"
+ + validValue
+ + "' which does not match the required <package>.<class>#<method>() format.");
+ }
}
public static Class<? extends ConfiguredObject> getCategory(final Class<?> clazz)
@@ -907,4 +1003,18 @@
}
}
+ public Collection<String> getValidChildTypes(Class<? extends ConfiguredObject> type, Class<? extends ConfiguredObject> childType)
+ {
+ final Map<String, Collection<String>> allValidChildTypes = _validChildTypes.get(getTypeClass(type));
+ if(allValidChildTypes != null)
+ {
+ final Collection<String> validTypesForSpecificChild = allValidChildTypes.get(getCategory(childType).getSimpleName());
+ return validTypesForSpecificChild == null ? null : Collections.unmodifiableCollection(validTypesForSpecificChild);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Group.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Group.java
index 4838336..2b2a436 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Group.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Group.java
@@ -19,7 +19,11 @@
*/
package org.apache.qpid.server.model;
-@ManagedObject
+import org.apache.qpid.server.security.group.GroupImpl;
+import org.apache.qpid.server.security.group.GroupPrincipal;
+
+@ManagedObject( defaultType = GroupImpl.CONFIG_TYPE )
public interface Group<X extends Group<X>> extends ConfiguredObject<X>
{
+ GroupPrincipal getGroupPrincipal();
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupMember.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupMember.java
index d1d2526..25b9dd0 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupMember.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupMember.java
@@ -19,7 +19,12 @@
*/
package org.apache.qpid.server.model;
-@ManagedObject
+import java.security.Principal;
+
+import org.apache.qpid.server.security.group.GroupMemberImpl;
+
+@ManagedObject( defaultType = GroupMemberImpl.CONFIG_TYPE )
public interface GroupMember<X extends GroupMember<X>> extends ConfiguredObject<X>
{
+ Principal getPrincipal();
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java
index c9a828e..440c7e3 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java
@@ -20,7 +20,8 @@
*/
package org.apache.qpid.server.model;
-import org.apache.qpid.server.BrokerOptions;
+import java.util.Map;
+
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.LogRecorder;
@@ -38,10 +39,10 @@
public JsonSystemConfigImpl(final TaskExecutor taskExecutor,
final EventLogger eventLogger,
final LogRecorder logRecorder,
- final BrokerOptions brokerOptions,
+ final Map<String,Object> attributes,
final BrokerShutdownProvider brokerShutdownProvider)
{
- super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);
+ super(taskExecutor, eventLogger, logRecorder, attributes, brokerShutdownProvider);
}
public String getStorePath()
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ManagedObject.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ManagedObject.java
index f18869b..483ddd4 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ManagedObject.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ManagedObject.java
@@ -35,5 +35,6 @@
boolean creatable() default true;
String defaultType() default ""; // in this case the class/interface itself is to be used
String type() default "";
+ String validChildTypes() default "";
boolean register() default true;
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java
index ec06314..a698081 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java
@@ -20,7 +20,6 @@
*/
package org.apache.qpid.server.model;
-import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.LogRecorder;
import org.apache.qpid.server.store.DurableConfigurationStore;
@@ -28,9 +27,41 @@
@ManagedObject (creatable = false)
public interface SystemConfig<X extends SystemConfig<X>> extends ConfiguredObject<X>
{
- EventLogger getEventLogger();
+ String MANAGEMENT_MODE = "managementMode";
+
+ String MANAGEMENT_MODE_QUIESCE_VIRTUAL_HOSTS = "managementModeQuiesceVirtualHosts";
+ String MANAGEMENT_MODE_RMI_PORT_OVERRIDE = "managementModeRmiPortOverride";
+ String MANAGEMENT_MODE_JMX_PORT_OVERRIDE = "managementModeJmxPortOverride";
+ String MANAGEMENT_MODE_HTTP_PORT_OVERRIDE = "managementModeHttpPortOverride";
+ String MANAGEMENT_MODE_PASSWORD = "managementModePassword";
+ String INITIAL_CONFIGURATION_LOCATION = "initialConfigurationLocation";
+ String STARTUP_LOGGED_TO_SYSTEM_OUT = "startupLoggedToSystemOut";
- BrokerOptions getBrokerOptions();
+ @ManagedAttribute(defaultValue = "false")
+ boolean isManagementMode();
+
+ @ManagedAttribute(defaultValue = "0")
+ int getManagementModeRmiPortOverride();
+
+ @ManagedAttribute(defaultValue = "0")
+ int getManagementModeJmxPortOverride();
+
+ @ManagedAttribute(defaultValue = "0")
+ int getManagementModeHttpPortOverride();
+
+ @ManagedAttribute(defaultValue = "false")
+ boolean isManagementModeQuiesceVirtualHosts();
+
+ @ManagedAttribute(secure = true)
+ String getManagementModePassword();
+
+ @ManagedAttribute
+ String getInitialConfigurationLocation();
+
+ @ManagedAttribute(defaultValue = "true")
+ boolean isStartupLoggedToSystemOut();
+
+ EventLogger getEventLogger();
Broker getBroker();
@@ -39,4 +70,5 @@
DurableConfigurationStore getConfigurationStore();
BrokerShutdownProvider getBrokerShutdownProvider();
+
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
index c0e907b..79f37b6 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
@@ -40,19 +40,9 @@
String STORE_TRANSACTION_IDLE_TIMEOUT_WARN = "storeTransactionIdleTimeoutWarn";
String STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE = "storeTransactionOpenTimeoutClose";
String STORE_TRANSACTION_OPEN_TIMEOUT_WARN = "storeTransactionOpenTimeoutWarn";
- String SUPPORTED_EXCHANGE_TYPES = "supportedExchangeTypes";
- String SUPPORTED_QUEUE_TYPES = "supportedQueueTypes";
String HOUSE_KEEPING_THREAD_COUNT = "houseKeepingThreadCount";
String MODEL_VERSION = "modelVersion";
- // TODO - this isn't really an attribute
- @DerivedAttribute
- Collection<String> getSupportedExchangeTypes();
-
- // TODO - this isn't really an attribute
- @DerivedAttribute
- Collection<String> getSupportedQueueTypes();
-
@ManagedContextDefault( name = "queue.deadLetterQueueEnabled")
public static final boolean DEFAULT_DEAD_LETTER_QUEUE_ENABLED = false;
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
index 313fd50..28eea21 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
@@ -71,13 +71,13 @@
CONNECTION_HEART_BEAT_DELAY, STATISTICS_REPORTING_PERIOD };
+ private SystemConfig<?> _parent;
private EventLogger _eventLogger;
private final LogRecorder _logRecorder;
private final SecurityManager _securityManager;
private AuthenticationProvider<?> _managementModeAuthenticationProvider;
- private BrokerOptions _brokerOptions;
private Timer _reportingTimer;
private final StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
@@ -108,18 +108,17 @@
SystemConfig parent)
{
super(parentsMap(parent), attributes);
-
+ _parent = parent;
_logRecorder = parent.getLogRecorder();
_eventLogger = parent.getEventLogger();
- _brokerOptions = parent.getBrokerOptions();
- _securityManager = new SecurityManager(this, _brokerOptions.isManagementMode());
- if (_brokerOptions.isManagementMode())
+ _securityManager = new SecurityManager(this, parent.isManagementMode());
+ if (parent.isManagementMode())
{
Map<String,Object> authManagerAttrs = new HashMap<String, Object>();
authManagerAttrs.put(NAME,"MANAGEMENT_MODE_AUTHENTICATION");
authManagerAttrs.put(ID, UUID.randomUUID());
SimpleAuthenticationManager authManager = new SimpleAuthenticationManager(authManagerAttrs, this);
- authManager.addUser(BrokerOptions.MANAGEMENT_MODE_USER_NAME, _brokerOptions.getManagementModePassword());
+ authManager.addUser(BrokerOptions.MANAGEMENT_MODE_USER_NAME, _parent.getManagementModePassword());
_managementModeAuthenticationProvider = authManager;
}
_messagesDelivered = new StatisticsCounter("messages-delivered");
@@ -181,6 +180,14 @@
deleted();
throw new IllegalArgumentException(getClass().getSimpleName() + " must be durable");
}
+
+ Collection<AccessControlProvider<?>> accessControlProviders = getAccessControlProviders();
+
+ if(accessControlProviders != null && accessControlProviders.size() > 1)
+ {
+ deleted();
+ throw new IllegalArgumentException("At most one AccessControlProvider can be defined");
+ }
}
@Override
@@ -230,7 +237,7 @@
@StateTransition( currentState = State.UNINITIALIZED, desiredState = State.ACTIVE )
private void activate()
{
- if(_brokerOptions.isManagementMode())
+ if(_parent.isManagementMode())
{
_managementModeAuthenticationProvider.open();
}
@@ -243,14 +250,7 @@
if (children != null) {
for (final ConfiguredObject<?> child : children) {
- if (child instanceof AccessControlProvider)
- {
- addAccessControlProvider((AccessControlProvider)child);
- }
- else
- {
- child.addChangeListener(this);
- }
+ child.addChangeListener(this);
if (child.getState() == State.ERRORED )
{
@@ -263,7 +263,7 @@
}
final boolean brokerShutdownOnErroredChild = getContextValue(Boolean.class, BROKER_FAIL_STARTUP_WITH_ERRORED_CHILD);
- if (!_brokerOptions.isManagementMode() && brokerShutdownOnErroredChild && hasBrokerAnyErroredChildren)
+ if (!_parent.isManagementMode() && brokerShutdownOnErroredChild && hasBrokerAnyErroredChildren)
{
throw new IllegalStateException(String.format("Broker context variable %s is set and the broker has %s children",
BROKER_FAIL_STARTUP_WITH_ERRORED_CHILD, State.ERRORED));
@@ -274,7 +274,7 @@
if (isManagementMode())
{
_eventLogger.message(BrokerMessages.MANAGEMENT_MODE(BrokerOptions.MANAGEMENT_MODE_USER_NAME,
- _brokerOptions.getManagementModePassword()));
+ _parent.getManagementModePassword()));
}
setState(State.ACTIVE);
}
@@ -317,8 +317,7 @@
@Override
public String getProcessPid()
{
- // TODO
- return null;
+ return SystemUtils.getProcessPid();
}
@Override
@@ -328,30 +327,6 @@
}
@Override
- public Collection<String> getSupportedVirtualHostNodeTypes()
- {
- return getObjectFactory().getSupportedTypes(VirtualHostNode.class);
- }
-
- @Override
- public Collection<String> getSupportedVirtualHostTypes()
- {
- return getObjectFactory().getSupportedTypes(VirtualHost.class);
- }
-
- @Override
- public Collection<String> getSupportedAuthenticationProviders()
- {
- return getObjectFactory().getSupportedTypes(AuthenticationProvider.class);
- }
-
- @Override
- public Collection<String> getSupportedPreferencesProviderTypes()
- {
- return getObjectFactory().getSupportedTypes(PreferencesProvider.class);
- }
-
- @Override
public String getDefaultVirtualHost()
{
return _defaultVirtualHost;
@@ -604,23 +579,18 @@
private AccessControlProvider<?> createAccessControlProvider(final Map<String, Object> attributes)
{
+ final Collection<AccessControlProvider<?>> currentProviders = getAccessControlProviders();
+ if(currentProviders != null && !currentProviders.isEmpty())
+ {
+ throw new IllegalConfigurationException("Cannot add a second AccessControlProvider");
+ }
AccessControlProvider<?> accessControlProvider = (AccessControlProvider<?>) createChild(AccessControlProvider.class, attributes);
- addAccessControlProvider(accessControlProvider);
+ accessControlProvider.addChangeListener(this);
return accessControlProvider;
}
- private void addAccessControlProvider(final AccessControlProvider<?> accessControlProvider)
- {
- accessControlProvider.addChangeListener(this);
- accessControlProvider.addChangeListener(_securityManager);
- if(accessControlProvider.getState() == State.ACTIVE)
- {
- _securityManager.addPlugin(accessControlProvider.getAccessControl());
- }
- }
-
private boolean deleteAccessControlProvider(AccessControlProvider<?> accessControlProvider)
{
accessControlProvider.removeChangeListener(this);
@@ -939,7 +909,7 @@
@Override
public boolean isManagementMode()
{
- return _brokerOptions.isManagementMode();
+ return _parent.isManagementMode();
}
@Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java
index 1b3d059..19aec41 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java
@@ -54,7 +54,6 @@
public class FileBasedGroupProviderImpl
extends AbstractConfiguredObject<FileBasedGroupProviderImpl> implements FileBasedGroupProvider<FileBasedGroupProviderImpl>
{
- public static final String RESOURCE_BUNDLE = "org.apache.qpid.server.security.group.FileGroupProviderAttributeDescriptions";
public static final String GROUP_FILE_PROVIDER_TYPE = "GroupFile";
private static Logger LOGGER = Logger.getLogger(FileBasedGroupProviderImpl.class);
@@ -357,7 +356,7 @@
private class GroupAdapter extends AbstractConfiguredObject<GroupAdapter> implements Group<GroupAdapter>
{
-
+ private GroupPrincipal _groupPrincipal;
public GroupAdapter(Map<String, Object> attributes)
{
super(parentsMap(FileBasedGroupProviderImpl.this), attributes);
@@ -396,6 +395,7 @@
groupMemberAdapter.open();
members.add(groupMemberAdapter);
}
+ _groupPrincipal = new GroupPrincipal(getName());
}
@Override
@@ -463,16 +463,30 @@
setState(State.DELETED);
}
+ @Override
+ public GroupPrincipal getGroupPrincipal()
+ {
+ return _groupPrincipal;
+ }
+
private class GroupMemberAdapter extends AbstractConfiguredObject<GroupMemberAdapter> implements
GroupMember<GroupMemberAdapter>
{
+ private Principal _principal;
+
public GroupMemberAdapter(Map<String, Object> attrMap)
{
// TODO - need to relate to the User object
super(parentsMap(GroupAdapter.this),attrMap);
}
+ @Override
+ protected void onOpen()
+ {
+ super.onOpen();
+ _principal = new UsernamePrincipal(getName());
+ }
@Override
public void onValidate()
@@ -484,6 +498,8 @@
}
}
+
+
@Override
protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes)
{
@@ -517,6 +533,11 @@
setState(State.DELETED);
}
+ @Override
+ public Principal getPrincipal()
+ {
+ return _principal;
+ }
}
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/Pluggable.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/Pluggable.java
index cc18e83..84e4e21 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/Pluggable.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/Pluggable.java
@@ -1,4 +1,4 @@
-package org.apache.qpid.server.plugin;/*
+/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -19,6 +19,8 @@
*
*/
+package org.apache.qpid.server.plugin;
+
public interface Pluggable
{
String getType();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/QpidServiceLoader.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/QpidServiceLoader.java
index 9f94e7d..f70afb1 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/QpidServiceLoader.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/QpidServiceLoader.java
@@ -84,7 +84,8 @@
private boolean isDisabledConfiguredType(final ConfiguredObjectTypeFactory<?> typeFactory)
{
- return Boolean.getBoolean("qpid.type.disabled:" + typeFactory.getCategoryClass().getSimpleName().toLowerCase()
+ String simpleName = typeFactory.getCategoryClass().getSimpleName().toLowerCase();
+ return Boolean.getBoolean("qpid.type.disabled:" + simpleName
+ "." + typeFactory.getType());
}
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java
index 885194d..6d4098a 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java
@@ -20,7 +20,8 @@
*/
package org.apache.qpid.server.plugin;
-import org.apache.qpid.server.BrokerOptions;
+import java.util.Map;
+
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.LogRecorder;
@@ -32,6 +33,6 @@
public X newInstance(final TaskExecutor taskExecutor,
final EventLogger eventLogger,
final LogRecorder logRecorder,
- final BrokerOptions brokerOptions,
+ final Map<String,Object> options,
final BrokerShutdownProvider brokerShutdownProvider);
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
index 9cfa7db..aa64d69 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
@@ -71,6 +71,8 @@
void decrementUnackedMsgCount(QueueEntry queueEntry);
+ void incrementUnackedMsgCount(QueueEntry entry);
+
boolean resend(final QueueEntry entry, final QueueConsumer<?> consumer);
List<? extends QueueEntry> getMessagesOnTheQueue();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
index f941112..26cbf37 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
@@ -1231,7 +1231,6 @@
setLastSeenEntry(sub, entry);
_deliveredMessages.incrementAndGet();
- incrementUnackedMsgCount(entry);
sub.send(entry, batch);
}
@@ -2462,13 +2461,15 @@
return _unackedMsgBytes.get();
}
+ @Override
public void decrementUnackedMsgCount(QueueEntry queueEntry)
{
_unackedMsgCount.decrementAndGet();
_unackedMsgBytes.addAndGet(-queueEntry.getSize());
}
- private void incrementUnackedMsgCount(QueueEntry entry)
+ @Override
+ public void incrementUnackedMsgCount(QueueEntry entry)
{
_unackedMsgCount.incrementAndGet();
_unackedMsgBytes.addAndGet(entry.getSize());
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
index a0f2dc7..452c5ff 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
@@ -214,6 +214,7 @@
if(acquired)
{
_deliveryCountUpdater.compareAndSet(this,-1,0);
+ getQueue().incrementUnackedMsgCount(this);
}
return acquired;
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
deleted file mode 100644
index d32f029..0000000
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- *
- * 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.registry;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.common.QpidProperties;
-import org.apache.qpid.server.BrokerOptions;
-import org.apache.qpid.server.configuration.BrokerProperties;
-import org.apache.qpid.server.logging.CompositeStartupMessageLogger;
-import org.apache.qpid.server.logging.EventLogger;
-import org.apache.qpid.server.logging.Log4jMessageLogger;
-import org.apache.qpid.server.logging.MessageLogger;
-import org.apache.qpid.server.logging.SystemOutMessageLogger;
-import org.apache.qpid.server.logging.messages.BrokerMessages;
-import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.model.State;
-import org.apache.qpid.server.model.SystemConfig;
-import org.apache.qpid.server.store.BrokerStoreUpgraderAndRecoverer;
-import org.apache.qpid.server.store.DurableConfigurationStore;
-import org.apache.qpid.util.SystemUtils;
-
-
-/**
- * An abstract application registry that provides access to configuration information and handles the
- * construction and caching of configurable objects.
- * <p>
- * Subclasses should handle the construction of the "registered objects" such as the exchange registry.
- */
-public class ApplicationRegistry implements IApplicationRegistry
-{
- private static final Logger _logger = Logger.getLogger(ApplicationRegistry.class);
-
- private final SystemConfig _systemConfig;
-
- private Broker _broker;
-
- private DurableConfigurationStore _store;
-
- public ApplicationRegistry(DurableConfigurationStore store, SystemConfig systemConfig)
- {
- _store = store;
- _systemConfig = systemConfig;
- }
-
- public void initialise(BrokerOptions brokerOptions) throws Exception
- {
- // Create the RootLogger to be used during broker operation
- boolean statusUpdatesEnabled = Boolean.parseBoolean(System.getProperty(BrokerProperties.PROPERTY_STATUS_UPDATES, "true"));
- MessageLogger messageLogger = new Log4jMessageLogger(statusUpdatesEnabled);
- final EventLogger eventLogger = _systemConfig.getEventLogger();
- eventLogger.setMessageLogger(messageLogger);
-
- //Create the composite (log4j+SystemOut MessageLogger to be used during startup
- MessageLogger[] messageLoggers = {new SystemOutMessageLogger(), messageLogger};
-
- CompositeStartupMessageLogger startupMessageLogger = new CompositeStartupMessageLogger(messageLoggers);
- EventLogger startupLogger = new EventLogger(startupMessageLogger);
-
- logStartupMessages(startupLogger);
-
- BrokerStoreUpgraderAndRecoverer upgrader = new BrokerStoreUpgraderAndRecoverer(_systemConfig);
- Broker broker = upgrader.perform(_store);
- _broker = broker;
-
- broker.setEventLogger(startupLogger);
- broker.open();
-
- if (broker.getState() == State.ACTIVE)
- {
- startupLogger.message(BrokerMessages.READY());
- broker.setEventLogger(eventLogger);
- }
- }
-
- public void close()
- {
- if (_logger.isInfoEnabled())
- {
- _logger.info("Shutting down ApplicationRegistry:" + this);
- }
- try
- {
- if (_broker != null)
- {
- _broker.close();
- }
- }
- finally
- {
- _systemConfig.close();
- }
- _store = null;
- _broker = null;
- }
-
-
- private void logStartupMessages(EventLogger eventLogger)
- {
- eventLogger.message(BrokerMessages.STARTUP(QpidProperties.getReleaseVersion(), QpidProperties.getBuildVersion()));
-
- eventLogger.message(BrokerMessages.PLATFORM(System.getProperty("java.vendor"),
- System.getProperty("java.runtime.version", System.getProperty("java.version")),
- SystemUtils.getOSName(),
- SystemUtils.getOSVersion(),
- SystemUtils.getOSArch()));
-
- eventLogger.message(BrokerMessages.MAX_MEMORY(Runtime.getRuntime().maxMemory()));
- }
-
- @Override
- public Broker getBroker()
- {
- return _broker;
- }
-
-}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java
deleted file mode 100644
index fb58887..0000000
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *
- * 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.registry;
-
-import org.apache.qpid.server.BrokerOptions;
-import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.stats.StatisticsGatherer;
-
-public interface IApplicationRegistry
-{
-
- void initialise(BrokerOptions brokerOptions) throws Exception;
-
- /**
- * Shutdown this Registry
- */
- void close();
-
- Broker getBroker();
-}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileKeyStoreImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileKeyStoreImpl.java
index 08fc815..31a4b47 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileKeyStoreImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileKeyStoreImpl.java
@@ -20,11 +20,15 @@
*/
package org.apache.qpid.server.security;
+import java.io.File;
import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.security.AccessControlException;
import java.security.GeneralSecurityException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Collection;
@@ -48,6 +52,7 @@
import org.apache.qpid.server.model.StateTransition;
import org.apache.qpid.server.security.access.Operation;
import org.apache.qpid.server.util.ServerScopedRuntimeException;
+import org.apache.qpid.server.util.urlstreamhandler.data.Handler;
import org.apache.qpid.transport.network.security.ssl.QpidClientX509KeyManager;
import org.apache.qpid.transport.network.security.ssl.SSLUtil;
@@ -69,7 +74,12 @@
private String _password;
- private Broker<?> _broker;
+ private final Broker<?> _broker;
+
+ static
+ {
+ Handler.register();
+ }
@ManagedObjectFactoryConstructor
public FileKeyStoreImpl(Map<String, Object> attributes, Broker<?> broker)
@@ -152,14 +162,25 @@
java.security.KeyStore keyStore;
try
{
- String path = fileKeyStore.getPath();
+ URL url = getUrlFromString(fileKeyStore.getPath());
String password = fileKeyStore.getPassword();
String keyStoreType = fileKeyStore.getKeyStoreType();
- keyStore = SSLUtil.getInitializedKeyStore(path, password, keyStoreType);
+ keyStore = SSLUtil.getInitializedKeyStore(url, password, keyStoreType);
}
+
catch (Exception e)
{
- throw new IllegalConfigurationException("Cannot instantiate key store at " + fileKeyStore.getPath(), e);
+ final String message;
+ if (e instanceof IOException && e.getCause() != null && e.getCause() instanceof UnrecoverableKeyException)
+ {
+ message = "Check key store password. Cannot instantiate key store from '" + fileKeyStore.getPath() + "'.";
+ }
+ else
+ {
+ message = "Cannot instantiate key store from '" + fileKeyStore.getPath() + "'.";
+ }
+
+ throw new IllegalConfigurationException(message, e);
}
if (fileKeyStore.getCertificateAlias() != null)
@@ -176,8 +197,8 @@
}
if (cert == null)
{
- throw new IllegalConfigurationException("Cannot find a certificate with alias " + fileKeyStore.getCertificateAlias()
- + "in key store : " + fileKeyStore.getPath());
+ throw new IllegalConfigurationException("Cannot find a certificate with alias '" + fileKeyStore.getCertificateAlias()
+ + "' in key store : " + fileKeyStore.getPath());
}
}
@@ -237,17 +258,18 @@
try
{
+ URL url = getUrlFromString(_path);
if (_certificateAlias != null)
{
return new KeyManager[] {
- new QpidClientX509KeyManager( _certificateAlias, _path, _keyStoreType, getPassword(),
+ new QpidClientX509KeyManager( _certificateAlias, url, _keyStoreType, getPassword(),
_keyManagerFactoryAlgorithm)
};
}
else
{
- final java.security.KeyStore ks = SSLUtil.getInitializedKeyStore(_path, getPassword(), _keyStoreType);
+ final java.security.KeyStore ks = SSLUtil.getInitializedKeyStore(url, getPassword(), _keyStoreType);
char[] keyStoreCharPassword = getPassword() == null ? null : getPassword().toCharArray();
@@ -263,4 +285,20 @@
throw new GeneralSecurityException(e);
}
}
+
+ private static URL getUrlFromString(String urlString) throws MalformedURLException
+ {
+ URL url;
+ try
+ {
+ url = new URL(urlString);
+ }
+ catch (MalformedURLException e)
+ {
+ File file = new File(urlString);
+ url = file.toURI().toURL();
+
+ }
+ return url;
+ }
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileTrustStoreImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileTrustStoreImpl.java
index 044f15f..66ae6fd 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileTrustStoreImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileTrustStoreImpl.java
@@ -20,11 +20,15 @@
*/
package org.apache.qpid.server.security;
+import java.io.File;
import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.security.AccessControlException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
@@ -48,6 +52,7 @@
import org.apache.qpid.server.model.TrustStore;
import org.apache.qpid.server.security.access.Operation;
import org.apache.qpid.server.security.auth.manager.SimpleLDAPAuthenticationManager;
+import org.apache.qpid.server.util.urlstreamhandler.data.Handler;
import org.apache.qpid.transport.network.security.ssl.QpidMultipleTrustManager;
import org.apache.qpid.transport.network.security.ssl.QpidPeersOnlyTrustManager;
import org.apache.qpid.transport.network.security.ssl.SSLUtil;
@@ -66,7 +71,12 @@
@ManagedAttributeField
private String _password;
- private Broker<?> _broker;
+ private final Broker<?> _broker;
+
+ static
+ {
+ Handler.register();
+ }
@ManagedObjectFactoryConstructor
public FileTrustStoreImpl(Map<String, Object> attributes, Broker<?> broker)
@@ -114,12 +124,10 @@
Collection<AuthenticationProvider> authenticationProviders = new ArrayList<AuthenticationProvider>(_broker.getAuthenticationProviders());
for (AuthenticationProvider authProvider : authenticationProviders)
{
- if(authProvider.getAttributeNames().contains(SimpleLDAPAuthenticationManager.TRUST_STORE))
+ if (authProvider instanceof SimpleLDAPAuthenticationManager)
{
- Object attributeType = authProvider.getAttribute(AuthenticationProvider.TYPE);
- Object attributeValue = authProvider.getAttribute(SimpleLDAPAuthenticationManager.TRUST_STORE);
- if (SimpleLDAPAuthenticationManager.PROVIDER_TYPE.equals(attributeType)
- && storeName.equals(attributeValue))
+ SimpleLDAPAuthenticationManager simpleLdap = (SimpleLDAPAuthenticationManager) authProvider;
+ if (simpleLdap.getTrustStore() == this)
{
throw new IntegrityViolationException("Trust store '"
+ storeName
@@ -185,11 +193,22 @@
{
try
{
- SSLUtil.getInitializedKeyStore(trustStore.getPath(), trustStore.getPassword(), trustStore.getTrustStoreType());
+ URL trustStoreUrl = getUrlFromString(trustStore.getPath());
+ SSLUtil.getInitializedKeyStore(trustStoreUrl, trustStore.getPassword(), trustStore.getTrustStoreType());
}
catch (Exception e)
{
- throw new IllegalConfigurationException("Cannot instantiate trust store at " + trustStore.getPath(), e);
+ final String message;
+ if (e instanceof IOException && e.getCause() != null && e.getCause() instanceof UnrecoverableKeyException)
+ {
+ message = "Check trust store password. Cannot instantiate trust store from '" + trustStore.getPath() + "'.";
+ }
+ else
+ {
+ message = "Cannot instantiate trust store from '" + trustStore.getPath() + "'.";
+ }
+
+ throw new IllegalConfigurationException(message, e);
}
try
@@ -238,14 +257,15 @@
}
public TrustManager[] getTrustManagers() throws GeneralSecurityException
{
- String trustStorePath = _path;
String trustStorePassword = getPassword();
String trustStoreType = _trustStoreType;
String trustManagerFactoryAlgorithm = _trustManagerFactoryAlgorithm;
try
{
- KeyStore ts = SSLUtil.getInitializedKeyStore(trustStorePath, trustStorePassword, trustStoreType);
+ URL trustStoreUrl = getUrlFromString(_path);
+
+ KeyStore ts = SSLUtil.getInitializedKeyStore(trustStoreUrl, trustStorePassword, trustStoreType);
final TrustManagerFactory tmf = TrustManagerFactory
.getInstance(trustManagerFactoryAlgorithm);
tmf.init(ts);
@@ -291,4 +311,21 @@
throw new GeneralSecurityException(e);
}
}
+
+ private static URL getUrlFromString(String urlString) throws MalformedURLException
+ {
+ URL url;
+ try
+ {
+ url = new URL(urlString);
+ }
+ catch (MalformedURLException e)
+ {
+ File file = new File(urlString);
+ url = file.toURI().toURL();
+
+ }
+ return url;
+ }
+
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java
index 96bd9ee..71878dc 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java
@@ -44,7 +44,6 @@
import org.apache.qpid.server.exchange.ExchangeImpl;
import org.apache.qpid.server.model.AccessControlProvider;
import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.model.ConfigurationChangeListener;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.protocol.AMQConnectionModel;
@@ -57,18 +56,17 @@
import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
import org.apache.qpid.server.security.auth.TaskPrincipal;
-public class SecurityManager implements ConfigurationChangeListener
+public class SecurityManager
{
private static final Subject SYSTEM = new Subject(true,
Collections.singleton(new SystemPrincipal()),
Collections.emptySet(),
Collections.emptySet());
- private final ConcurrentMap<String, AccessControl> _plugins = new ConcurrentHashMap<String, AccessControl>();
private final boolean _managementMode;
private final Broker<?> _broker;
- private final ConcurrentMap<PublishAccessCheckCacheEntry, PublishAccessCheck> _publishAccessCheckCache = new ConcurrentHashMap<SecurityManager.PublishAccessCheckCacheEntry, SecurityManager.PublishAccessCheck>();
+ private final ConcurrentMap<PublishAccessCheckCacheEntry, PublishAccessCheck> _publishAccessCheckCache = new ConcurrentHashMap<PublishAccessCheckCacheEntry, SecurityManager.PublishAccessCheck>();
public SecurityManager(Broker<?> broker, boolean managementMode)
{
@@ -135,16 +133,6 @@
return user;
}
- public void addPlugin(final AccessControl accessControl)
- {
-
- synchronized (_plugins)
- {
- String pluginTypeName = getPluginTypeName(accessControl);
-
- _plugins.put(pluginTypeName, accessControl);
- }
- }
private static final class SystemPrincipal implements Principal
{
@@ -167,24 +155,31 @@
private boolean checkAllPlugins(AccessCheck checker)
{
// If we are running as SYSTEM then no ACL checking
- if(isSystemProcess())
+ if(isSystemProcess() || _managementMode)
{
return true;
}
- for (AccessControl plugin : _plugins.values())
+
+ Collection<AccessControlProvider<?>> accessControlProviders = _broker.getAccessControlProviders();
+ if(accessControlProviders != null && !accessControlProviders.isEmpty())
{
- Result remaining = checker.allowed(plugin);
- if (remaining == Result.DEFER)
+ AccessControlProvider<?> accessControlProvider = accessControlProviders.iterator().next();
+ if (accessControlProvider != null
+ && accessControlProvider.getState() == State.ACTIVE
+ && accessControlProvider.getAccessControl() != null)
{
- remaining = plugin.getDefault();
- }
- if (remaining == Result.DENIED)
- {
- return false;
+ Result remaining = checker.allowed(accessControlProvider.getAccessControl());
+ if (remaining == Result.DEFER)
+ {
+ remaining = accessControlProvider.getAccessControl().getDefault();
+ }
+ if (remaining == Result.DENIED)
+ {
+ return false;
+ }
}
}
-
// getting here means either allowed or abstained from all plugins
return true;
}
@@ -486,92 +481,6 @@
}
}
- @Override
- public void stateChanged(ConfiguredObject object, State oldState, State newState)
- {
- if(_managementMode)
- {
- //AccessControl is disabled in ManagementMode
- return;
- }
-
- if(object instanceof AccessControlProvider)
- {
- if(newState == State.ACTIVE)
- {
- synchronized (_plugins)
- {
- AccessControl accessControl = ((AccessControlProvider)object).getAccessControl();
- String pluginTypeName = getPluginTypeName(accessControl);
-
- _plugins.put(pluginTypeName, accessControl);
- }
- }
- else if(newState == State.DELETED)
- {
- synchronized (_plugins)
- {
- AccessControl control = ((AccessControlProvider)object).getAccessControl();
- String pluginTypeName = getPluginTypeName(control);
-
- // Remove the type->control mapping for this type key only if the
- // given control is actually referred to.
- if(_plugins.containsValue(control))
- {
- // If we are removing this control, check if another of the same
- // type already exists on the broker and use it in instead.
- AccessControl other = null;
- Collection<AccessControlProvider<?>> providers = _broker.getAccessControlProviders();
- for(AccessControlProvider p : providers)
- {
- if(p == object || p.getState() != State.ACTIVE)
- {
- //we don't count ourself as another
- continue;
- }
-
- AccessControl ac = p.getAccessControl();
- if(pluginTypeName.equals(getPluginTypeName(ac)))
- {
- other = ac;
- break;
- }
- }
-
- if(other != null)
- {
- //Another control of this type was found, use it instead
- _plugins.replace(pluginTypeName, control, other);
- }
- else
- {
- //No other was found, remove the type entirely
- _plugins.remove(pluginTypeName);
- }
- }
- }
- }
- }
- }
-
- @Override
- public void childAdded(ConfiguredObject object, ConfiguredObject child)
- {
- // no op
- }
-
- @Override
- public void childRemoved(ConfiguredObject object, ConfiguredObject child)
- {
- // no op
- }
-
- @Override
- public void attributeSet(ConfiguredObject object, String attributeName, Object oldAttributeValue, Object newAttributeValue)
- {
- // no op
- }
-
public boolean authoriseConfiguringBroker(String configuredObjectName, Class<? extends ConfiguredObject> configuredObjectType, Operation configuredObjectOperation)
{
String description = String.format("%s %s '%s'",
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupImpl.java
new file mode 100644
index 0000000..98607d2
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupImpl.java
@@ -0,0 +1,92 @@
+/*
+ *
+ * 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.security.group;
+
+import java.util.Map;
+
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Group;
+import org.apache.qpid.server.model.GroupMember;
+import org.apache.qpid.server.model.GroupProvider;
+import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.StateTransition;
+
+@ManagedObject(category = false, type = GroupImpl.CONFIG_TYPE)
+public class GroupImpl extends AbstractConfiguredObject<GroupImpl> implements Group<GroupImpl>
+{
+
+ public static final String CONFIG_TYPE = "ManagedGroup";
+
+ private GroupPrincipal _groupPrincipal;
+
+ @ManagedObjectFactoryConstructor
+ public GroupImpl(Map<String, Object> attributes,
+ GroupProvider<?> provider)
+ {
+ super(parentsMap(provider), attributes);
+ }
+
+ @Override
+ protected void onOpen()
+ {
+ super.onOpen();
+ _groupPrincipal = new GroupPrincipal(getName());
+ }
+
+ @Override
+ protected <C extends ConfiguredObject> C addChild(final Class<C> childClass,
+ final Map<String, Object> attributes,
+ final ConfiguredObject... otherParents)
+ {
+ if(childClass == GroupMember.class)
+ {
+ return (C) getObjectFactory().create(childClass, attributes, this);
+ }
+ else
+ {
+ return super.addChild(childClass, attributes, otherParents);
+ }
+ }
+
+ @Override
+ public GroupPrincipal getGroupPrincipal()
+ {
+ return _groupPrincipal;
+ }
+
+
+ @StateTransition( currentState = { State.UNINITIALIZED, State.QUIESCED, State.ERRORED }, desiredState = State.ACTIVE )
+ private void activate()
+ {
+ setState(State.ACTIVE);
+ }
+
+
+ @StateTransition(currentState = {State.ACTIVE}, desiredState = State.DELETED)
+ private void doDelete()
+ {
+ deleted();
+ }
+
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupMemberImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupMemberImpl.java
new file mode 100644
index 0000000..ea17db6
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupMemberImpl.java
@@ -0,0 +1,75 @@
+/*
+ *
+ * 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.security.group;
+
+import java.security.Principal;
+import java.util.Map;
+
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.Group;
+import org.apache.qpid.server.model.GroupMember;
+import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.StateTransition;
+import org.apache.qpid.server.security.auth.UsernamePrincipal;
+
+@ManagedObject(category = false, type = GroupMemberImpl.CONFIG_TYPE)
+public class GroupMemberImpl extends AbstractConfiguredObject<GroupMemberImpl> implements GroupMember<GroupMemberImpl>
+{
+ public static final String CONFIG_TYPE = "ManagedGroupMember";
+ private UsernamePrincipal _principal;
+
+
+ @ManagedObjectFactoryConstructor
+ public GroupMemberImpl(Map<String, Object> attributes,
+ Group group)
+ {
+ super(parentsMap(group), attributes);
+ }
+
+ @Override
+ protected void onOpen()
+ {
+ super.onOpen();
+ _principal = new UsernamePrincipal(getName());
+ }
+
+ @Override
+ public Principal getPrincipal()
+ {
+ return _principal;
+ }
+
+
+ @StateTransition( currentState = { State.UNINITIALIZED, State.QUIESCED, State.ERRORED }, desiredState = State.ACTIVE )
+ private void activate()
+ {
+ setState(State.ACTIVE);
+ }
+
+
+ @StateTransition(currentState = {State.ACTIVE}, desiredState = State.DELETED)
+ private void doDelete()
+ {
+ deleted();
+ }
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupProviderImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupProviderImpl.java
new file mode 100644
index 0000000..6728ba2
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupProviderImpl.java
@@ -0,0 +1,103 @@
+/*
+ *
+ * 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.security.group;
+
+import java.security.Principal;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Group;
+import org.apache.qpid.server.model.GroupMember;
+import org.apache.qpid.server.model.GroupProvider;
+import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.StateTransition;
+
+@ManagedObject(category = false, type = GroupProviderImpl.CONFIG_TYPE)
+public class GroupProviderImpl extends AbstractConfiguredObject<GroupProviderImpl> implements GroupProvider<GroupProviderImpl>
+{
+
+ public static final String CONFIG_TYPE = "ManagedGroupProvider";
+
+ @ManagedObjectFactoryConstructor
+ public GroupProviderImpl(Map<String, Object> attributes,
+ Broker broker)
+ {
+ super(parentsMap(broker), attributes);
+ }
+
+
+ @Override
+ public Set<Principal> getGroupPrincipalsForUser(final String username)
+ {
+ Set<Principal> principals = new HashSet<>();
+
+ final Collection<Group> groups = getChildren(Group.class);
+ for(Group<?> group : groups)
+ {
+ for(GroupMember<?> member : group.getChildren(GroupMember.class))
+ {
+ if(member.getPrincipal().getName().equals(username))
+ {
+ principals.add(group.getGroupPrincipal());
+ }
+ }
+ }
+ return principals;
+ }
+
+ @Override
+ protected <C extends ConfiguredObject> C addChild(final Class<C> childClass,
+ final Map<String, Object> attributes,
+ final ConfiguredObject... otherParents)
+ {
+ if(childClass == Group.class)
+ {
+ C child = (C) getObjectFactory().create(childClass, attributes, this);
+
+ return child;
+ }
+ else
+ {
+ return super.addChild(childClass, attributes, otherParents);
+ }
+ }
+
+ @StateTransition( currentState = { State.UNINITIALIZED, State.QUIESCED, State.ERRORED }, desiredState = State.ACTIVE )
+ private void activate()
+ {
+ setState(State.ACTIVE);
+ }
+
+
+ @StateTransition(currentState = {State.ACTIVE}, desiredState = State.DELETED)
+ private void doDelete()
+ {
+ deleted();
+ }
+
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java
index 2be2bbb..a2d8d21 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java
@@ -604,8 +604,9 @@
return brokerRecord;
}
- public Broker<?> perform(final DurableConfigurationStore store)
+ public Broker<?> perform()
{
+ final DurableConfigurationStore store = _systemConfig.getConfigurationStore();
List<ConfiguredObjectRecord> upgradedRecords = upgrade(store);
new GenericRecoverer(_systemConfig).recover(upgradedRecords);
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
index 4dc975a..4086a67 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
@@ -1087,18 +1087,6 @@
}
@Override
- public Collection<String> getSupportedExchangeTypes()
- {
- return getObjectFactory().getSupportedTypes(Exchange.class);
- }
-
- @Override
- public Collection<String> getSupportedQueueTypes()
- {
- return getObjectFactory().getSupportedTypes(Queue.class);
- }
-
- @Override
public boolean isQueue_deadLetterQueueEnabled()
{
return _queue_deadLetterQueueEnabled;
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface3.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/NonStandardVirtualHost.java
similarity index 70%
copy from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface3.java
copy to qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/NonStandardVirtualHost.java
index d1d0a1b..3137ea2 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface3.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/NonStandardVirtualHost.java
@@ -18,12 +18,12 @@
* under the License.
*
*/
-package org.apache.qpid.server.model.testmodel;
+package org.apache.qpid.server.virtualhost;
-import org.apache.qpid.server.model.ManagedAnnotation;
-import org.apache.qpid.server.model.ManagedInterface;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.VirtualHost;
-@ManagedAnnotation
-public interface TestManagedInterface3 extends ManagedInterface
+public interface NonStandardVirtualHost<X extends NonStandardVirtualHost<X, Q, E>, Q extends Queue<?>, E extends Exchange<?> > extends VirtualHost<X, Q, E>
{
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ProvidedStoreVirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ProvidedStoreVirtualHost.java
index deb4f1d..475d859 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ProvidedStoreVirtualHost.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ProvidedStoreVirtualHost.java
@@ -24,7 +24,10 @@
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.store.SizeMonitoringSettings;
-public interface ProvidedStoreVirtualHost<X extends ProvidedStoreVirtualHost<X>> extends VirtualHostImpl<X,AMQQueue<?>,ExchangeImpl<?>>, SizeMonitoringSettings
+public interface ProvidedStoreVirtualHost<X extends ProvidedStoreVirtualHost<X>>
+ extends VirtualHostImpl<X,AMQQueue<?>,ExchangeImpl<?>>,
+ SizeMonitoringSettings,
+ NonStandardVirtualHost<X,AMQQueue<?>,ExchangeImpl<?>>
{
@ManagedAttribute(mandatory = true, defaultValue = "0")
Long getStoreUnderfullSize();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
index f4c0576..bcfd0ff 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
@@ -31,6 +31,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -47,14 +48,18 @@
import org.apache.qpid.server.model.AbstractConfiguredObject;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObjectTypeRegistry;
import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.LifetimePolicy;
import org.apache.qpid.server.model.ManagedAttributeField;
+import org.apache.qpid.server.model.ManagedObject;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.StateTransition;
import org.apache.qpid.server.model.SystemConfig;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.model.VirtualHostNode;
+import org.apache.qpid.server.plugin.ConfiguredObjectRegistration;
+import org.apache.qpid.server.plugin.QpidServiceLoader;
import org.apache.qpid.server.security.access.Operation;
import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
import org.apache.qpid.server.store.ConfiguredObjectRecord;
@@ -62,6 +67,8 @@
import org.apache.qpid.server.store.ConfiguredObjectRecordImpl;
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.util.urlstreamhandler.data.Handler;
+import org.apache.qpid.server.virtualhost.NonStandardVirtualHost;
+import org.apache.qpid.server.virtualhost.ProvidedStoreVirtualHostImpl;
public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode<X>> extends AbstractConfiguredObject<X> implements VirtualHostNode<X>
{
@@ -442,4 +449,34 @@
return initialConfigReader;
}
+ protected static Collection<String> getSupportedVirtualHostTypes(boolean includeProvided)
+ {
+
+ final Iterable<ConfiguredObjectRegistration> registrations =
+ (new QpidServiceLoader()).instancesOf(ConfiguredObjectRegistration.class);
+
+ Set<String> supportedTypes = new HashSet<>();
+
+ for(ConfiguredObjectRegistration registration : registrations)
+ {
+ for(Class<? extends ConfiguredObject> typeClass : registration.getConfiguredObjectClasses())
+ {
+ if(VirtualHost.class.isAssignableFrom(typeClass))
+ {
+ ManagedObject annotation = typeClass.getAnnotation(ManagedObject.class);
+
+ if (annotation.creatable() && annotation.defaultType().equals("") && !NonStandardVirtualHost.class.isAssignableFrom(typeClass))
+ {
+ supportedTypes.add(ConfiguredObjectTypeRegistry.getType(typeClass));
+ }
+ }
+ }
+ }
+ if(includeProvided)
+ {
+ supportedTypes.add(ProvidedStoreVirtualHostImpl.VIRTUAL_HOST_TYPE);
+ }
+ return Collections.unmodifiableCollection(supportedTypes);
+ }
+
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/JsonVirtualHostNodeImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/JsonVirtualHostNodeImpl.java
index d97d290..b8a7b3f 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/JsonVirtualHostNodeImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/JsonVirtualHostNodeImpl.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.server.virtualhostnode;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Map;
import org.apache.qpid.server.logging.messages.ConfigStoreMessages;
@@ -31,7 +33,7 @@
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.JsonFileConfigStore;
-@ManagedObject(type=JsonVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE, category=false)
+@ManagedObject(type=JsonVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE, category=false, validChildTypes = "org.apache.qpid.server.virtualhostnode.JsonVirtualHostNodeImpl#getSupportedChildTypes()")
public class JsonVirtualHostNodeImpl extends AbstractStandardVirtualHostNode<JsonVirtualHostNodeImpl> implements JsonVirtualHostNode<JsonVirtualHostNodeImpl>
{
public static final String VIRTUAL_HOST_NODE_TYPE = "JSON";
@@ -68,4 +70,9 @@
{
return getClass().getSimpleName() + " [id=" + getId() + ", name=" + getName() + ", storePath=" + getStorePath() + "]";
}
+
+ public static Map<String, Collection<String>> getSupportedChildTypes()
+ {
+ return Collections.singletonMap(VirtualHost.class.getSimpleName(), getSupportedVirtualHostTypes(false));
+ }
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/FileKeyStoreCreationTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/FileKeyStoreCreationTest.java
deleted file mode 100644
index b4f9299..0000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/FileKeyStoreCreationTest.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- *
- * 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.configuration.startup;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.security.PrivilegedAction;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-
-import javax.net.ssl.KeyManagerFactory;
-import javax.security.auth.Subject;
-
-import junit.framework.TestCase;
-
-import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
-import org.apache.qpid.server.configuration.updater.TaskExecutor;
-import org.apache.qpid.server.model.AbstractConfiguredObject;
-import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.model.BrokerModel;
-import org.apache.qpid.server.model.ConfiguredObject;
-import org.apache.qpid.server.model.ConfiguredObjectFactory;
-import org.apache.qpid.server.model.ConfiguredObjectFactoryImpl;
-import org.apache.qpid.server.model.KeyStore;
-import org.apache.qpid.server.security.FileKeyStore;
-import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.test.utils.TestSSLConstants;
-
-public class FileKeyStoreCreationTest extends TestCase
-{
-
- private ConfiguredObjectFactory _factory;
-
- public void setUp() throws Exception
- {
- super.setUp();
- _factory = new ConfiguredObjectFactoryImpl(BrokerModel.getInstance());
- }
-
- public void testCreateWithAllAttributesProvided()
- {
- Map<String, Object> attributes = getKeyStoreAttributes();
- Map<String, Object> attributesCopy = new HashMap<String, Object>(attributes);
-
- Broker broker = mock(Broker.class);
- TaskExecutor executor = CurrentThreadTaskExecutor.newStartedInstance();
- when(broker.getObjectFactory()).thenReturn(_factory);
- when(broker.getModel()).thenReturn(_factory.getModel());
- when(broker.getTaskExecutor()).thenReturn(executor);
-
- final FileKeyStore keyStore =
- createKeyStore(attributes, broker);
-
-
- assertNotNull("Key store configured object is not created", keyStore);
- assertEquals(attributes.get(ConfiguredObject.ID), keyStore.getId());
-
- //verify we can retrieve the actual password using the method
- Subject.doAs(SecurityManager.getSubjectWithAddedSystemRights(), new PrivilegedAction<Object>()
- {
- @Override
- public Object run()
- {
- assertNotNull(keyStore.getPassword());
- assertEquals(TestSSLConstants.BROKER_TRUSTSTORE_PASSWORD, keyStore.getPassword());
- //verify that we haven't configured the key store with the actual dummy password value
- assertFalse(AbstractConfiguredObject.SECURED_STRING_VALUE.equals(keyStore.getPassword()));
- return null;
- }
- });
-
-
- // Verify the remaining attributes, including that the password value returned
- // via getAttribute is actually the dummy value and not the real password
- attributesCopy.put(FileKeyStore.PASSWORD, AbstractConfiguredObject.SECURED_STRING_VALUE);
- for (Map.Entry<String, Object> attribute : attributesCopy.entrySet())
- {
- Object attributeValue = keyStore.getAttribute(attribute.getKey());
- assertEquals("Unexpected value of attribute '" + attribute.getKey() + "'", attribute.getValue(), attributeValue);
- }
- }
-
- protected FileKeyStore createKeyStore(final Map<String, Object> attributes, final Broker broker)
- {
- return (FileKeyStore) _factory.create(KeyStore.class,attributes, broker);
- }
-
- public void testCreateWithMissedRequiredAttributes()
- {
- Map<String, Object> attributes = getKeyStoreAttributes();
-
- Broker broker = mock(Broker.class);
- when(broker.getObjectFactory()).thenReturn(_factory);
- when(broker.getModel()).thenReturn(_factory.getModel());
- when(broker.getTaskExecutor()).thenReturn(CurrentThreadTaskExecutor.newStartedInstance());
- String[] mandatoryProperties = {KeyStore.NAME, FileKeyStore.PATH, FileKeyStore.PASSWORD};
- for (int i = 0; i < mandatoryProperties.length; i++)
- {
- Map<String, Object> properties = new HashMap<String, Object>(attributes);
- properties.remove(mandatoryProperties[i]);
- try
- {
- createKeyStore(properties, broker);
- fail("Cannot create key store without a " + mandatoryProperties[i]);
- }
- catch(IllegalArgumentException e)
- {
- // pass
- }
- }
- }
-
- private Map<String, Object> getKeyStoreAttributes()
- {
- Map<String, Object> attributes = new HashMap<String, Object>();
- attributes.put(KeyStore.ID, UUID.randomUUID());
- attributes.put(KeyStore.NAME, getName());
- attributes.put(FileKeyStore.PATH, TestSSLConstants.BROKER_KEYSTORE);
- attributes.put(FileKeyStore.PASSWORD, TestSSLConstants.BROKER_KEYSTORE_PASSWORD);
- attributes.put(FileKeyStore.KEY_STORE_TYPE, "jks");
- attributes.put(FileKeyStore.KEY_MANAGER_FACTORY_ALGORITHM, KeyManagerFactory.getDefaultAlgorithm());
- attributes.put(FileKeyStore.CERTIFICATE_ALIAS, "java-broker");
- return attributes;
- }
-
-
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/FileTrustStoreCreationTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/FileTrustStoreCreationTest.java
deleted file mode 100644
index 1baad01..0000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/FileTrustStoreCreationTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- *
- * 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.configuration.startup;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.security.PrivilegedAction;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-
-import javax.net.ssl.TrustManagerFactory;
-import javax.security.auth.Subject;
-
-import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
-import org.apache.qpid.server.configuration.updater.TaskExecutor;
-import org.apache.qpid.server.model.AbstractConfiguredObject;
-import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.model.BrokerModel;
-import org.apache.qpid.server.model.ConfiguredObjectFactoryImpl;
-import org.apache.qpid.server.model.TrustStore;
-import org.apache.qpid.server.security.FileTrustStore;
-import org.apache.qpid.server.security.FileTrustStoreImpl;
-import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.test.utils.QpidTestCase;
-import org.apache.qpid.test.utils.TestSSLConstants;
-
-public class FileTrustStoreCreationTest extends QpidTestCase
-{
- public void testCreateWithAllAttributesProvided()
- {
- UUID id = UUID.randomUUID();
- Map<String, Object> attributes = getTrustStoreAttributes(id);
- Map<String, Object> attributesCopy = new HashMap<String, Object>(attributes);
-
- ConfiguredObjectFactoryImpl factory = new ConfiguredObjectFactoryImpl(BrokerModel.getInstance());
-
- Broker broker = mock(Broker.class);
- when(broker.getObjectFactory()).thenReturn(factory);
- when(broker.getModel()).thenReturn(factory.getModel());
- TaskExecutor executor = new CurrentThreadTaskExecutor();
- when(broker.getTaskExecutor()).thenReturn(executor);
-
- final FileTrustStore trustStore = new FileTrustStoreImpl(attributes, broker);
- trustStore.open();
- assertNotNull("Trust store configured object is not created", trustStore);
- assertEquals(id, trustStore.getId());
-
- Subject.doAs(SecurityManager.getSubjectWithAddedSystemRights(), new PrivilegedAction<Object>()
- {
- @Override
- public Object run()
- {
- //verify we can retrieve the actual password using the method
- assertEquals(TestSSLConstants.BROKER_TRUSTSTORE_PASSWORD, trustStore.getPassword());
- assertNotNull(trustStore.getPassword());
- //verify that we haven't configured the trust store with the actual dummy password value
- assertFalse(AbstractConfiguredObject.SECURED_STRING_VALUE.equals(trustStore.getPassword()));
- return null;
- }
- });
-
-
- // Verify the remaining attributes, including that the password value returned
- // via getAttribute is actually the dummy value and not the real password
- attributesCopy.put(FileTrustStore.PASSWORD, AbstractConfiguredObject.SECURED_STRING_VALUE);
- for (Map.Entry<String, Object> attribute : attributesCopy.entrySet())
- {
- Object attributeValue = trustStore.getAttribute(attribute.getKey());
- assertEquals("Unexpected value of attribute '" + attribute.getKey() + "'", attribute.getValue(), attributeValue);
- }
- }
-
- public void testCreateWithMissedRequiredAttributes()
- {
- UUID id = UUID.randomUUID();
- Map<String, Object> attributes = getTrustStoreAttributes(id);
-
- ConfiguredObjectFactoryImpl factory = new ConfiguredObjectFactoryImpl(BrokerModel.getInstance());
- Broker broker = mock(Broker.class);
- when(broker.getObjectFactory()).thenReturn(factory);
- when(broker.getModel()).thenReturn(factory.getModel());
- when(broker.getTaskExecutor()).thenReturn(CurrentThreadTaskExecutor.newStartedInstance());
- String[] mandatoryProperties = {TrustStore.NAME, FileTrustStore.PATH, FileTrustStore.PASSWORD};
- for (int i = 0; i < mandatoryProperties.length; i++)
- {
- Map<String, Object> properties = new HashMap<String, Object>(attributes);
- properties.remove(mandatoryProperties[i]);
- try
- {
- TrustStore trustStore = new FileTrustStoreImpl(properties, broker);
- trustStore.open();
- fail("Cannot create key store without a " + mandatoryProperties[i]);
- }
- catch(IllegalArgumentException e)
- {
- // pass
- }
- }
- }
-
- private Map<String, Object> getTrustStoreAttributes(UUID id)
- {
- Map<String, Object> attributes = new HashMap<String, Object>();
- attributes.put(TrustStore.NAME, getName());
- attributes.put(TrustStore.ID, id);
- attributes.put(FileTrustStore.PATH, TestSSLConstants.BROKER_TRUSTSTORE);
- attributes.put(FileTrustStore.PASSWORD, TestSSLConstants.BROKER_TRUSTSTORE_PASSWORD);
- attributes.put(FileTrustStore.TRUST_STORE_TYPE, "jks");
- attributes.put(FileTrustStore.TRUST_MANAGER_FACTORY_ALGORITHM, TrustManagerFactory.getDefaultAlgorithm());
- attributes.put(FileTrustStore.PEERS_ONLY, Boolean.TRUE);
- return attributes;
- }
-
-
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java
index fbb08cd..0dee582 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java
@@ -34,7 +34,6 @@
import java.util.Map;
import java.util.UUID;
-import org.apache.qpid.server.model.BrokerShutdownProvider;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -45,7 +44,10 @@
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.AbstractSystemConfig;
import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
+import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.JsonSystemConfigImpl;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.Protocol;
@@ -79,7 +81,7 @@
_taskExecutor.start();
_systemConfig = new JsonSystemConfigImpl(_taskExecutor, mock(EventLogger.class),
- mock(LogRecorder.class), new BrokerOptions(),
+ mock(LogRecorder.class), new BrokerOptions().convertToSystemConfigAttributes(),
mock(BrokerShutdownProvider.class));
@@ -87,7 +89,8 @@
- _root = new ConfiguredObjectRecordImpl(_rootId, Broker.class.getSimpleName(), Collections.<String,Object>emptyMap(), Collections.singletonMap(SystemConfig.class.getSimpleName(), systemContextRecord.getId()));
+ _root = new ConfiguredObjectRecordImpl(_rootId, Broker.class.getSimpleName(), Collections.singletonMap(Broker.NAME,
+ (Object) "broker"), Collections.singletonMap(SystemConfig.class.getSimpleName(), systemContextRecord.getId()));
_portEntry = mock(ConfiguredObjectRecord.class);
when(_portEntry.getId()).thenReturn(_portEntryId);
@@ -111,15 +114,48 @@
}
).when(_store).visitConfiguredObjectRecords(recovererArgumentCaptor.capture());
_options = new BrokerOptions();
- _handler = new ManagementModeStoreHandler(_store, _options);
+
+ _handler = new ManagementModeStoreHandler(_store, _systemConfig);;
_handler.openConfigurationStore(_systemConfig, false);
}
+ private ManagementModeStoreHandler createManagementModeStoreHandler()
+ {
+ _systemConfig.close();
+ Map<String, Object> attributes = new HashMap<>(_options.convertToSystemConfigAttributes());
+ attributes.put(ConfiguredObject.DESIRED_STATE, State.QUIESCED);
+ _systemConfig = new AbstractSystemConfig(_taskExecutor,
+ mock(EventLogger.class),
+ mock(LogRecorder.class),
+ attributes,
+ mock(BrokerShutdownProvider.class))
+ {
+ @Override
+ protected void onOpen()
+ {
+ }
+
+ @Override
+ protected DurableConfigurationStore createStoreObject()
+ {
+ return _store;
+ }
+
+ @Override
+ protected void onClose()
+ {
+ }
+ };
+ _systemConfig.open();
+ return new ManagementModeStoreHandler(_store, _systemConfig);
+ }
+
@Override
public void tearDown() throws Exception
{
_taskExecutor.stop();
+ _systemConfig.close();
super.tearDown();
}
@@ -154,7 +190,7 @@
public void testGetRootEntryWithHttpPortOverriden()
{
_options.setManagementModeHttpPortOverride(9090);
- _handler = new ManagementModeStoreHandler(_store, _options);
+ _handler = createManagementModeStoreHandler();
_handler.openConfigurationStore(_systemConfig, false);
ConfiguredObjectRecord root = getRootEntry();
assertEquals("Unexpected root id", _rootId, root.getId());
@@ -166,7 +202,7 @@
public void testGetRootEntryWithRmiPortOverriden()
{
_options.setManagementModeRmiPortOverride(9090);
- _handler = new ManagementModeStoreHandler(_store, _options);
+ _handler = createManagementModeStoreHandler();
_handler.openConfigurationStore(_systemConfig, false);
ConfiguredObjectRecord root = getRootEntry();
@@ -179,7 +215,7 @@
public void testGetRootEntryWithConnectorPortOverriden()
{
_options.setManagementModeJmxPortOverride(9090);
- _handler = new ManagementModeStoreHandler(_store, _options);
+ _handler = createManagementModeStoreHandler();
_handler.openConfigurationStore(_systemConfig, false);
ConfiguredObjectRecord root = getRootEntry();
@@ -194,7 +230,7 @@
_options.setManagementModeHttpPortOverride(1000);
_options.setManagementModeRmiPortOverride(2000);
_options.setManagementModeJmxPortOverride(3000);
- _handler = new ManagementModeStoreHandler(_store, _options);
+ _handler = createManagementModeStoreHandler();
_handler.openConfigurationStore(_systemConfig, false);
ConfiguredObjectRecord root = getRootEntry();
@@ -222,7 +258,7 @@
public void testGetEntryByCLIConnectorPortId()
{
_options.setManagementModeJmxPortOverride(9090);
- _handler = new ManagementModeStoreHandler(_store, _options);
+ _handler = createManagementModeStoreHandler();
_handler.openConfigurationStore(_systemConfig, false);
@@ -234,7 +270,7 @@
public void testGetEntryByCLIHttpPortId()
{
_options.setManagementModeHttpPortOverride(9090);
- _handler = new ManagementModeStoreHandler(_store, _options);
+ _handler = createManagementModeStoreHandler();
_handler.openConfigurationStore(_systemConfig, false);
@@ -249,7 +285,7 @@
attributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.HTTP));
when(_portEntry.getAttributes()).thenReturn(attributes);
_options.setManagementModeHttpPortOverride(9090);
- _handler = new ManagementModeStoreHandler(_store, _options);
+ _handler = createManagementModeStoreHandler();
_handler.openConfigurationStore(_systemConfig, false);
@@ -263,7 +299,7 @@
attributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.RMI));
when(_portEntry.getAttributes()).thenReturn(attributes);
_options.setManagementModeRmiPortOverride(9090);
- _handler = new ManagementModeStoreHandler(_store, _options);
+ _handler = createManagementModeStoreHandler();
_handler.openConfigurationStore(_systemConfig, false);
@@ -277,7 +313,7 @@
attributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.JMX_RMI));
when(_portEntry.getAttributes()).thenReturn(attributes);
_options.setManagementModeRmiPortOverride(9090);
- _handler = new ManagementModeStoreHandler(_store, _options);
+ _handler = createManagementModeStoreHandler();
_handler.openConfigurationStore(_systemConfig, false);
@@ -328,7 +364,7 @@
_options.setManagementModeQuiesceVirtualHosts(mmQuiesceVhosts);
}
- _handler = new ManagementModeStoreHandler(_store, _options);
+ _handler = createManagementModeStoreHandler();
_handler.openConfigurationStore(_systemConfig, false);
ConfiguredObjectRecord hostEntry = getEntry(virtualHostId);
@@ -354,7 +390,7 @@
_options.setManagementModeHttpPortOverride(1000);
_options.setManagementModeRmiPortOverride(2000);
_options.setManagementModeJmxPortOverride(3000);
- _handler = new ManagementModeStoreHandler(_store, _options);
+ _handler = createManagementModeStoreHandler();
_handler.openConfigurationStore(_systemConfig, false);
Map<String, Object> attributes = new HashMap<String, Object>();
@@ -371,7 +407,7 @@
_options.setManagementModeHttpPortOverride(1000);
_options.setManagementModeRmiPortOverride(2000);
_options.setManagementModeJmxPortOverride(3000);
- _handler = new ManagementModeStoreHandler(_store, _options);
+ _handler = createManagementModeStoreHandler();
_handler.openConfigurationStore(_systemConfig, false);
ConfiguredObjectRecord root = getRootEntry();
@@ -386,7 +422,7 @@
public void testSaveCLIHttpPort()
{
_options.setManagementModeHttpPortOverride(1000);
- _handler = new ManagementModeStoreHandler(_store, _options);
+ _handler = createManagementModeStoreHandler();
_handler.openConfigurationStore(_systemConfig, false);
UUID portId = getOptionsPortId();
@@ -410,7 +446,7 @@
public void testRemove()
{
_options.setManagementModeHttpPortOverride(1000);
- _handler = new ManagementModeStoreHandler(_store, _options);
+ _handler = createManagementModeStoreHandler();
_handler.openConfigurationStore(_systemConfig, false);
ConfiguredObjectRecord record = new ConfiguredObjectRecord()
@@ -446,7 +482,7 @@
public void testRemoveCLIPort()
{
_options.setManagementModeHttpPortOverride(1000);
- _handler = new ManagementModeStoreHandler(_store, _options);
+ _handler = createManagementModeStoreHandler();
_handler.openConfigurationStore(_systemConfig, false);
UUID portId = getOptionsPortId();
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java
deleted file mode 100644
index 3ffb4c4..0000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- *
- * 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;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.qpid.server.configuration.IllegalConfigurationException;
-import org.apache.qpid.server.model.testmodel.TestChildCategory;
-import org.apache.qpid.server.model.testmodel.TestConfiguredObject;
-import org.apache.qpid.server.model.testmodel.TestEnum;
-import org.apache.qpid.server.model.testmodel.TestModel;
-import org.apache.qpid.server.model.testmodel.TestRootCategory;
-import org.apache.qpid.server.store.ConfiguredObjectRecord;
-import org.apache.qpid.test.utils.QpidTestCase;
-
-public class AbstractConfiguredObjectTest extends QpidTestCase
-{
- private final Model _model = TestModel.getInstance();
-
- public void testAttributePersistence()
- {
- final String objectName = "testNonPersistAttributes";
- TestRootCategory object =
- _model.getObjectFactory().create(TestRootCategory.class,
- Collections.<String, Object>singletonMap(ConfiguredObject.NAME,
- objectName)
- );
-
- assertEquals(objectName, object.getName());
- assertNull(object.getAutomatedNonPersistedValue());
- assertNull(object.getAutomatedPersistedValue());
-
- ConfiguredObjectRecord record = object.asObjectRecord();
-
- assertEquals(objectName, record.getAttributes().get(ConfiguredObject.NAME));
-
- assertFalse(record.getAttributes().containsKey(TestRootCategory.AUTOMATED_PERSISTED_VALUE));
- assertFalse(record.getAttributes().containsKey(TestRootCategory.AUTOMATED_NONPERSISTED_VALUE));
-
-
- Map<String, Object> updatedAttributes = new HashMap<>();
-
- final String newValue = "newValue";
-
- updatedAttributes.put(TestRootCategory.AUTOMATED_PERSISTED_VALUE, newValue);
- updatedAttributes.put(TestRootCategory.AUTOMATED_NONPERSISTED_VALUE, newValue);
- object.setAttributes(updatedAttributes);
-
- assertEquals(newValue, object.getAutomatedPersistedValue());
- assertEquals(newValue, object.getAutomatedNonPersistedValue());
-
- record = object.asObjectRecord();
- assertEquals(objectName, record.getAttributes().get(ConfiguredObject.NAME));
- assertEquals(newValue, record.getAttributes().get(TestRootCategory.AUTOMATED_PERSISTED_VALUE));
-
- assertFalse(record.getAttributes().containsKey(TestRootCategory.AUTOMATED_NONPERSISTED_VALUE));
-
- }
-
- public void testDefaultedAttributeValue()
- {
- final String objectName = "myName";
-
- Map<String, Object> attributes = Collections.<String, Object>singletonMap(ConfiguredObject.NAME, objectName);
-
- TestRootCategory object1 = _model.getObjectFactory().create(TestRootCategory.class,
- attributes);
-
- assertEquals(objectName, object1.getName());
- assertEquals(TestRootCategory.DEFAULTED_VALUE_DEFAULT, object1.getDefaultedValue());
- }
-
- public void testOverriddenDefaultedAttributeValue()
- {
- final String objectName = "myName";
-
- Map<String, Object> attributes = new HashMap<>();
- attributes.put(ConfiguredObject.NAME, objectName);
- attributes.put(TestRootCategory.DEFAULTED_VALUE, "override");
-
- TestRootCategory object = _model.getObjectFactory().create(TestRootCategory.class,
- attributes);
-
- assertEquals(objectName, object.getName());
- assertEquals("override", object.getDefaultedValue());
-
- }
-
- public void testOverriddenDefaultedAttributeValueRevertedToDefault()
- {
- final String objectName = "myName";
-
- Map<String, Object> attributes = new HashMap<>();
- attributes.put(ConfiguredObject.NAME, objectName);
- attributes.put(TestRootCategory.DEFAULTED_VALUE, "override");
-
- TestRootCategory object = _model.getObjectFactory().create(TestRootCategory.class,
- attributes);
-
- assertEquals(objectName, object.getName());
- assertEquals("override", object.getDefaultedValue());
-
- object.setAttributes(Collections.singletonMap(TestRootCategory.DEFAULTED_VALUE, null));
- assertEquals(TestRootCategory.DEFAULTED_VALUE_DEFAULT, object.getDefaultedValue());
- }
-
- public void testEnumAttributeValueFromString()
- {
- final String objectName = "myName";
-
- Map<String, Object> attributes = new HashMap<>();
- attributes.put(ConfiguredObject.NAME, objectName);
- attributes.put(TestRootCategory.ENUM_VALUE, TestEnum.TEST_ENUM1.name());
-
- TestRootCategory object1 = _model.getObjectFactory().create(TestRootCategory.class,
- attributes);
-
- assertEquals(objectName, object1.getName());
- assertEquals(TestEnum.TEST_ENUM1, object1.getEnumValue());
- }
-
- public void testEnumAttributeValueFromEnum()
- {
- final String objectName = "myName";
-
- Map<String, Object> attributes = new HashMap<>();
- attributes.put(ConfiguredObject.NAME, objectName);
- attributes.put(TestRootCategory.ENUM_VALUE, TestEnum.TEST_ENUM1);
-
- TestRootCategory object1 = _model.getObjectFactory().create(TestRootCategory.class,
- attributes);
-
- assertEquals(objectName, object1.getName());
- assertEquals(TestEnum.TEST_ENUM1, object1.getEnumValue());
- }
-
- public void testStringAttributeValueFromContextVariableProvidedBySystemProperty()
- {
- String sysPropertyName = "testStringAttributeValueFromContextVariableProvidedBySystemProperty";
- String contextToken = "${" + sysPropertyName + "}";
-
- System.setProperty(sysPropertyName, "myValue");
-
- final String objectName = "myName";
-
- Map<String, Object> attributes = new HashMap<>();
- attributes.put(ConfiguredObject.NAME, objectName);
- attributes.put(TestRootCategory.STRING_VALUE, contextToken);
-
- TestRootCategory object1 = _model.getObjectFactory().create(TestRootCategory.class,
- attributes);
-
- assertEquals(objectName, object1.getName());
- assertEquals("myValue", object1.getStringValue());
-
- // System property set empty string
-
- System.setProperty(sysPropertyName, "");
- TestRootCategory object2 = _model.getObjectFactory().create(TestRootCategory.class,
- attributes);
-
- assertEquals("", object2.getStringValue());
-
- // System property not set
- System.clearProperty(sysPropertyName);
-
- TestRootCategory object3 = _model.getObjectFactory().create(TestRootCategory.class,
- attributes);
-
- // yields the unexpanded token - not sure if this is really useful behaviour?
- assertEquals(contextToken, object3.getStringValue());
- }
-
- public void testMapAttributeValueFromContextVariableProvidedBySystemProperty()
- {
- String sysPropertyName = "testMapAttributeValueFromContextVariableProvidedBySystemProperty";
- String contextToken = "${" + sysPropertyName + "}";
-
- Map<String,String> expectedMap = new HashMap<>();
- expectedMap.put("field1", "value1");
- expectedMap.put("field2", "value2");
-
- System.setProperty(sysPropertyName, "{ \"field1\" : \"value1\", \"field2\" : \"value2\"}");
-
- final String objectName = "myName";
-
- Map<String, Object> attributes = new HashMap<>();
- attributes.put(ConfiguredObject.NAME, objectName);
- attributes.put(TestRootCategory.MAP_VALUE, contextToken);
-
- TestRootCategory object1 = _model.getObjectFactory().create(TestRootCategory.class,
- attributes);
-
- assertEquals(objectName, object1.getName());
- assertEquals(expectedMap, object1.getMapValue());
-
- // System property not set
- System.clearProperty(sysPropertyName);
- }
-
-
- public void testDefaultContextIsInContextKeys()
- {
- final String objectName = "myName";
-
- Map<String, Object> attributes = new HashMap<>();
- attributes.put(ConfiguredObject.NAME, objectName);
-
-
- TestRootCategory object = _model.getObjectFactory().create(TestRootCategory.class,
- attributes);
-
-
- assertTrue("context default not in contextKeys",
- object.getContextKeys(true).contains(TestRootCategory.TEST_CONTEXT_DEFAULT));
- assertEquals(object.getContextValue(String.class, TestRootCategory.TEST_CONTEXT_DEFAULT), "default");
-
- setTestSystemProperty(TestRootCategory.TEST_CONTEXT_DEFAULT, "notdefault");
- assertTrue("context default not in contextKeys",
- object.getContextKeys(true).contains(TestRootCategory.TEST_CONTEXT_DEFAULT));
- assertEquals(object.getContextValue(String.class, TestRootCategory.TEST_CONTEXT_DEFAULT), "notdefault");
- }
-
- public void testStringAttributeValueFromContextVariableProvidedObjectsContext()
- {
- String contextToken = "${myReplacement}";
-
- final String objectName = "myName";
-
- Map<String, Object> attributes = new HashMap<>();
- attributes.put(ConfiguredObject.NAME, objectName);
- attributes.put(ConfiguredObject.CONTEXT, Collections.singletonMap("myReplacement", "myValue"));
- attributes.put(TestRootCategory.STRING_VALUE, contextToken);
-
- TestRootCategory object1 = _model.getObjectFactory().create(TestRootCategory.class,
- attributes);
- // Check the object's context itself
- assertTrue(object1.getContext().containsKey("myReplacement"));
- assertEquals("myValue", object1.getContext().get("myReplacement"));
-
- assertEquals(objectName, object1.getName());
- assertEquals("myValue", object1.getStringValue());
- }
-
- public void testCreationOfObjectWithInvalidInterpolatedValues()
- {
- final String parentName = "parent";
- TestRootCategory parent =
- _model.getObjectFactory().create(TestRootCategory.class,
- Collections.<String, Object>singletonMap(ConfiguredObject.NAME,
- parentName)
- );
-
- parent.setAttributes(Collections.singletonMap(ConfiguredObject.CONTEXT,
- Collections.singletonMap("contextVal", "foo")));
-
- final Map<String, Object> attributes = new HashMap<>();
- attributes.put("intValue", "${contextVal}");
- attributes.put("name", "child");
- attributes.put("integerSet", "[ ]");
- attributes.put(ConfiguredObject.TYPE, "test");
-
- try
- {
- _model.getObjectFactory().create(TestChildCategory.class, attributes, parent);
- fail("creation of child object should have failed due to invalid value");
- }
- catch (IllegalArgumentException e)
- {
- // PASS
- String message = e.getMessage();
- assertTrue("Message does not contain the attribute name", message.contains("intValue"));
- assertTrue("Message does not contain the non-interpolated value", message.contains("contextVal"));
- assertTrue("Message does not contain the interpolated value", message.contains("foo"));
-
- }
-
- assertTrue("Child should not have been registered with parent",
- parent.getChildren(TestChildCategory.class).isEmpty());
- }
-
- public void testCreationOfObjectWithInvalidDefaultValues()
- {
- final String parentName = "parent";
- TestRootCategory parent =
- _model.getObjectFactory().create(TestRootCategory.class,
- Collections.<String, Object>singletonMap(ConfiguredObject.NAME,
- parentName)
- );
-
- final Map<String, Object> attributes = new HashMap<>();
- attributes.put("intValue", "1");
- attributes.put("name", "child");
- attributes.put(ConfiguredObject.TYPE, "test");
-
- try
- {
- _model.getObjectFactory().create(TestChildCategory.class, attributes, parent);
- fail("creation of child object should have failed due to invalid value");
- }
- catch (IllegalArgumentException e)
- {
- // PASS
- String message = e.getMessage();
- assertTrue("Message does not contain the attribute name", message.contains("integerSet"));
- assertTrue("Message does not contain the error value", message.contains("foo"));
-
- }
-
- assertTrue("Child should not have been registered with parent",
- parent.getChildren(TestChildCategory.class).isEmpty());
- }
-
- public void testOpeningResultsInErroredStateWhenResolutionFails() throws Exception
- {
- TestConfiguredObject object = new TestConfiguredObject(getName());
- object.setThrowExceptionOnPostResolve(true);
- object.open();
- assertFalse("Unexpected opened", object.isOpened());
- assertEquals("Unexpected state", State.ERRORED, object.getState());
-
- object.setThrowExceptionOnPostResolve(false);
- object.setAttributes(Collections.<String, Object>singletonMap(Port.DESIRED_STATE, State.ACTIVE));
- assertTrue("Unexpected opened", object.isOpened());
- assertEquals("Unexpected state", State.ACTIVE, object.getState());
- }
-
- public void testOpeningInERROREDStateAfterFailedOpenOnDesiredStateChangeToActive() throws Exception
- {
- TestConfiguredObject object = new TestConfiguredObject(getName());
- object.setThrowExceptionOnOpen(true);
- object.open();
- assertFalse("Unexpected opened", object.isOpened());
- assertEquals("Unexpected state", State.ERRORED, object.getState());
-
- object.setThrowExceptionOnOpen(false);
- object.setAttributes(Collections.<String, Object>singletonMap(Port.DESIRED_STATE, State.ACTIVE));
- assertTrue("Unexpected opened", object.isOpened());
- assertEquals("Unexpected state", State.ACTIVE, object.getState());
- }
-
- public void testOpeningInERROREDStateAfterFailedOpenOnStart() throws Exception
- {
- TestConfiguredObject object = new TestConfiguredObject(getName());
- object.setThrowExceptionOnOpen(true);
- object.open();
- assertFalse("Unexpected opened", object.isOpened());
- assertEquals("Unexpected state", State.ERRORED, object.getState());
-
- object.setThrowExceptionOnOpen(false);
- object.start();
- assertTrue("Unexpected opened", object.isOpened());
- assertEquals("Unexpected state", State.ACTIVE, object.getState());
- }
-
- public void testDeletionERROREDStateAfterFailedOpenOnDelete() throws Exception
- {
- TestConfiguredObject object = new TestConfiguredObject(getName());
- object.setThrowExceptionOnOpen(true);
- object.open();
- assertFalse("Unexpected opened", object.isOpened());
- assertEquals("Unexpected state", State.ERRORED, object.getState());
-
- object.delete();
- assertFalse("Unexpected opened", object.isOpened());
- assertEquals("Unexpected state", State.DELETED, object.getState());
- }
-
- public void testDeletionInERROREDStateAfterFailedOpenOnDesiredStateChangeToDelete() throws Exception
- {
- TestConfiguredObject object = new TestConfiguredObject(getName());
- object.setThrowExceptionOnOpen(true);
- object.open();
- assertFalse("Unexpected opened", object.isOpened());
- assertEquals("Unexpected state", State.ERRORED, object.getState());
-
- object.setAttributes(Collections.<String, Object>singletonMap(Port.DESIRED_STATE, State.DELETED));
- assertFalse("Unexpected opened", object.isOpened());
- assertEquals("Unexpected state", State.DELETED, object.getState());
- }
-
-
- public void testCreationWithExceptionThrownFromValidationOnCreate() throws Exception
- {
- TestConfiguredObject object = new TestConfiguredObject(getName());
- object.setThrowExceptionOnValidationOnCreate(true);
- try
- {
- object.create();
- fail("IllegalConfigurationException is expected to be thrown");
- }
- catch(IllegalConfigurationException e)
- {
- //pass
- }
- assertFalse("Unexpected opened", object.isOpened());
- }
-
- public void testCreationWithoutExceptionThrownFromValidationOnCreate() throws Exception
- {
- TestConfiguredObject object = new TestConfiguredObject(getName());
- object.setThrowExceptionOnValidationOnCreate(false);
- object.create();
- assertTrue("Unexpected opened", object.isOpened());
- assertEquals("Unexpected state", State.ACTIVE, object.getState());
- }
-
- public void testCreationWithExceptionThrownFromOnOpen() throws Exception
- {
- TestConfiguredObject object = new TestConfiguredObject(getName());
- object.setThrowExceptionOnOpen(true);
- try
- {
- object.create();
- fail("Exception should have been re-thrown");
- }
- catch (RuntimeException re)
- {
- // pass
- }
-
- assertFalse("Unexpected opened", object.isOpened());
- assertEquals("Unexpected state", State.DELETED, object.getState());
- }
-
- public void testCreationWithExceptionThrownFromOnCreate() throws Exception
- {
- TestConfiguredObject object = new TestConfiguredObject(getName());
- object.setThrowExceptionOnCreate(true);
- try
- {
- object.create();
- fail("Exception should have been re-thrown");
- }
- catch (RuntimeException re)
- {
- // pass
- }
-
- assertFalse("Unexpected opened", object.isOpened());
- assertEquals("Unexpected state", State.DELETED, object.getState());
- }
-
- public void testUnresolvedChildInERROREDStateIsNotValidatedOrOpenedOrAttainedDesiredStateOnParentOpen() throws Exception
- {
- TestConfiguredObject parent = new TestConfiguredObject("parent");
- TestConfiguredObject child1 = new TestConfiguredObject("child1", parent, parent.getTaskExecutor());
- child1.registerWithParents();
- TestConfiguredObject child2 = new TestConfiguredObject("child2", parent, parent.getTaskExecutor());
- child2.registerWithParents();
-
- child1.setThrowExceptionOnPostResolve(true);
-
- parent.open();
-
- assertTrue("Parent should be resolved", parent.isResolved());
- assertTrue("Parent should be validated", parent.isValidated());
- assertTrue("Parent should be opened", parent.isOpened());
- assertEquals("Unexpected parent state", State.ACTIVE, parent.getState());
-
- assertTrue("Child2 should be resolved", child2.isResolved());
- assertTrue("Child2 should be validated", child2.isValidated());
- assertTrue("Child2 should be opened", child2.isOpened());
- assertEquals("Unexpected child2 state", State.ACTIVE, child2.getState());
-
- assertFalse("Child2 should not be resolved", child1.isResolved());
- assertFalse("Child1 should not be validated", child1.isValidated());
- assertFalse("Child1 should not be opened", child1.isOpened());
- assertEquals("Unexpected child1 state", State.ERRORED, child1.getState());
- }
-
- public void testUnvalidatedChildInERROREDStateIsNotOpenedOrAttainedDesiredStateOnParentOpen() throws Exception
- {
- TestConfiguredObject parent = new TestConfiguredObject("parent");
- TestConfiguredObject child1 = new TestConfiguredObject("child1", parent, parent.getTaskExecutor());
- child1.registerWithParents();
- TestConfiguredObject child2 = new TestConfiguredObject("child2", parent, parent.getTaskExecutor());
- child2.registerWithParents();
-
- child1.setThrowExceptionOnValidate(true);
-
- parent.open();
-
- assertTrue("Parent should be resolved", parent.isResolved());
- assertTrue("Parent should be validated", parent.isValidated());
- assertTrue("Parent should be opened", parent.isOpened());
- assertEquals("Unexpected parent state", State.ACTIVE, parent.getState());
-
- assertTrue("Child2 should be resolved", child2.isResolved());
- assertTrue("Child2 should be validated", child2.isValidated());
- assertTrue("Child2 should be opened", child2.isOpened());
- assertEquals("Unexpected child2 state", State.ACTIVE, child2.getState());
-
- assertTrue("Child1 should be resolved", child1.isResolved());
- assertFalse("Child1 should not be validated", child1.isValidated());
- assertFalse("Child1 should not be opened", child1.isOpened());
- assertEquals("Unexpected child1 state", State.ERRORED, child1.getState());
- }
-
- public void testCreateEnforcesAttributeValidValues() throws Exception
- {
- final String objectName = getName();
- Map<String, Object> illegalCreateAttributes = new HashMap<>();
- illegalCreateAttributes.put(ConfiguredObject.NAME, objectName);
- illegalCreateAttributes.put(TestRootCategory.VALID_VALUE, "illegal");
-
- try
- {
- _model.getObjectFactory().create(TestRootCategory.class, illegalCreateAttributes);
- fail("Exception not thrown");
- }
- catch (IllegalConfigurationException ice)
- {
- // PASS
- }
-
- Map<String, Object> legalCreateAttributes = new HashMap<>();
- legalCreateAttributes.put(ConfiguredObject.NAME, objectName);
- legalCreateAttributes.put(TestRootCategory.VALID_VALUE, TestRootCategory.VALID_VALUE1);
-
- TestRootCategory object = _model.getObjectFactory().create(TestRootCategory.class, legalCreateAttributes);
- assertEquals(TestRootCategory.VALID_VALUE1, object.getValidValue());
- }
-
- public void testChangeEnforcesAttributeValidValues() throws Exception
- {
- final String objectName = getName();
- Map<String, Object> legalCreateAttributes = new HashMap<>();
- legalCreateAttributes.put(ConfiguredObject.NAME, objectName);
- legalCreateAttributes.put(TestRootCategory.VALID_VALUE, TestRootCategory.VALID_VALUE1);
-
- TestRootCategory object = _model.getObjectFactory().create(TestRootCategory.class, legalCreateAttributes);
- assertEquals(TestRootCategory.VALID_VALUE1, object.getValidValue());
-
- object.setAttributes(Collections.singletonMap(TestRootCategory.VALID_VALUE,TestRootCategory.VALID_VALUE2));
- assertEquals(TestRootCategory.VALID_VALUE2, object.getValidValue());
-
- try
- {
- object.setAttributes(Collections.singletonMap(TestRootCategory.VALID_VALUE, "illegal"));
- fail("Exception not thrown");
- }
- catch (IllegalConfigurationException iae)
- {
- // PASS
- }
-
- assertEquals(TestRootCategory.VALID_VALUE2, object.getValidValue());
-
- object.setAttributes(Collections.singletonMap(TestRootCategory.VALID_VALUE,null));
- assertNull(object.getValidValue());
-
- }
-
- public void testCreateEnforcesAttributeValidValuesWithSets() throws Exception
- {
- final String objectName = getName();
- final Map<String, Object> name = Collections.singletonMap(ConfiguredObject.NAME, (Object)objectName);
-
- Map<String, Object> illegalCreateAttributes = new HashMap<>(name);
- illegalCreateAttributes.put(TestRootCategory.ENUMSET_VALUES, Collections.singleton(TestEnum.TEST_ENUM3));
-
- try
- {
- _model.getObjectFactory().create(TestRootCategory.class, illegalCreateAttributes);
- fail("Exception not thrown");
- }
- catch (IllegalConfigurationException ice)
- {
- // PASS
- }
-
- {
- Map<String, Object> legalCreateAttributesEnums = new HashMap<>(name);
- legalCreateAttributesEnums.put(TestRootCategory.ENUMSET_VALUES,
- Arrays.asList(TestEnum.TEST_ENUM2, TestEnum.TEST_ENUM3));
-
- TestRootCategory obj = _model.getObjectFactory().create(TestRootCategory.class, legalCreateAttributesEnums);
- assertTrue(obj.getEnumSetValues().containsAll(Arrays.asList(TestEnum.TEST_ENUM2, TestEnum.TEST_ENUM3)));
- }
-
- {
- Map<String, Object> legalCreateAttributesStrings = new HashMap<>(name);
- legalCreateAttributesStrings.put(TestRootCategory.ENUMSET_VALUES,
- Arrays.asList(TestEnum.TEST_ENUM2.name(), TestEnum.TEST_ENUM3.name()));
-
- TestRootCategory obj = _model.getObjectFactory().create(TestRootCategory.class, legalCreateAttributesStrings);
- assertTrue(obj.getEnumSetValues().containsAll(Arrays.asList(TestEnum.TEST_ENUM2, TestEnum.TEST_ENUM3)));
- }
- }
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/AttributeValueConverterTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/AttributeValueConverterTest.java
index 8ddcb17..a257a7a 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/AttributeValueConverterTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/AttributeValueConverterTest.java
@@ -37,8 +37,8 @@
import junit.framework.TestCase;
-import org.apache.qpid.server.model.testmodel.TestModel;
-import org.apache.qpid.server.model.testmodel.TestRootCategory;
+import org.apache.qpid.server.model.testmodels.hierarchy.TestModel;
+import org.apache.qpid.server.model.testmodels.hierarchy.TestCar;
public class AttributeValueConverterTest extends TestCase
{
@@ -61,7 +61,7 @@
_context.put("mapWithInterpolatedContents", "{\"${mykey}\" : \"b\"}");
_context.put("mykey", "mykey1");
- ConfiguredObject object = _objectFactory.create(TestRootCategory.class, _attributes);
+ ConfiguredObject object = _objectFactory.create(TestCar.class, _attributes);
AttributeValueConverter<Map> mapConverter = getConverter(Map.class, Map.class);
@@ -96,7 +96,7 @@
{
_context.put("simpleCollection", "[\"a\", \"b\"]");
- ConfiguredObject object = _objectFactory.create(TestRootCategory.class, _attributes);
+ ConfiguredObject object = _objectFactory.create(TestCar.class, _attributes);
AttributeValueConverter<Collection> collectionConverter = getConverter(Collection.class, Collection.class);
@@ -131,7 +131,7 @@
{
_context.put("simpleList", "[\"a\", \"b\"]");
- ConfiguredObject object = _objectFactory.create(TestRootCategory.class, _attributes);
+ ConfiguredObject object = _objectFactory.create(TestCar.class, _attributes);
AttributeValueConverter<List> listConverter = getConverter(List.class, List.class);
@@ -164,7 +164,7 @@
{
_context.put("simpleSet", "[\"a\", \"b\"]");
- ConfiguredObject object = _objectFactory.create(TestRootCategory.class, _attributes);
+ ConfiguredObject object = _objectFactory.create(TestCar.class, _attributes);
AttributeValueConverter<Set> setConverter = getConverter(Set.class, Set.class);;
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistryTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistryTest.java
deleted file mode 100644
index 426526d..0000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistryTest.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- *
- * 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;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import junit.framework.TestCase;
-
-import org.apache.qpid.server.model.testmodel.Test2RootCategory;
-import org.apache.qpid.server.model.testmodel.Test2RootCategoryImpl;
-import org.apache.qpid.server.model.testmodel.TestChildCategory;
-import org.apache.qpid.server.model.testmodel.TestManagedClass0;
-import org.apache.qpid.server.model.testmodel.TestManagedClass1;
-import org.apache.qpid.server.model.testmodel.TestManagedClass2;
-import org.apache.qpid.server.model.testmodel.TestManagedClass3;
-import org.apache.qpid.server.model.testmodel.TestManagedClass4;
-import org.apache.qpid.server.model.testmodel.TestManagedClass5;
-import org.apache.qpid.server.model.testmodel.TestManagedInterface1;
-import org.apache.qpid.server.model.testmodel.TestManagedInterface3;
-import org.apache.qpid.server.model.testmodel.TestModel;
-import org.apache.qpid.server.model.testmodel.TestRootCategory;
-import org.apache.qpid.server.model.testmodel.TestRootCategoryImpl;
-import org.apache.qpid.server.plugin.ConfiguredObjectRegistration;
-
-public class ConfiguredObjectTypeRegistryTest extends TestCase
-{
- private ConfiguredObjectTypeRegistry _typeRegistry;
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
- Model model = TestModel.getInstance();
- _typeRegistry = model.getTypeRegistry();
- }
-
- public void testAllTypesRegistered()
- {
- Collection<Class<? extends ConfiguredObject>> types =
- _typeRegistry.getTypeSpecialisations(TestRootCategory.class);
-
- assertEquals(2, types.size());
- assertTrue(types.contains(TestRootCategoryImpl.class));
-
- assertTrue(types.contains(Test2RootCategoryImpl.class));
- }
-
- public void testTypeSpecificAttributes()
- {
- Collection<ConfiguredObjectAttribute<?, ?>> special =
- _typeRegistry.getTypeSpecificAttributes(Test2RootCategoryImpl.class);
- assertEquals(1, special.size());
- ConfiguredObjectAttribute attr = special.iterator().next();
- assertEquals("derivedAttribute",attr.getName());
- assertTrue(attr.isDerived());
-
- special = _typeRegistry.getTypeSpecificAttributes(TestRootCategoryImpl.class);
- assertEquals(0, special.size());
-
- }
-
- public void testDefaultedValues()
- {
- checkDefaultedValue(_typeRegistry.getAttributes((Class) TestRootCategoryImpl.class),
- TestRootCategory.DEFAULTED_VALUE_DEFAULT);
-
- checkDefaultedValue(_typeRegistry.getAttributes((Class) Test2RootCategoryImpl.class),
- Test2RootCategory.DEFAULTED_VALUE_DEFAULT);
- }
-
- public void testValidValues()
- {
- checkValidValues("validValue",_typeRegistry.getAttributes((Class) TestRootCategoryImpl.class),
- Arrays.asList( TestRootCategory.VALID_VALUE1, TestRootCategory.VALID_VALUE2 ) );
-
- checkValidValues("validValue", _typeRegistry.getAttributes((Class) Test2RootCategoryImpl.class),
- Test2RootCategoryImpl.functionGeneratedValidValues());
-
-
- checkValidValues("validValueNotInterpolated", _typeRegistry.getAttributes((Class) TestChildCategory.class),
- Arrays.asList(TestChildCategory.NON_INTERPOLATED_VALID_VALUE));
-
-
- }
-
- public void testGetManagedInterfacesForTypeNotImplementingManagedInterfaceAndNotHavingManagedAnnotation()
- {
- ConfiguredObjectTypeRegistry typeRegistry = createConfiguredObjectTypeRegistry(TestRootCategoryImpl.class);
- assertEquals("Unexpected interfaces from object not implementing Managed interfaces",
- Collections.emptySet(), typeRegistry.getManagedInterfaces(TestRootCategory.class));
- }
-
- public void testGetManagedInterfacesForTypeImplementingManagedInterfaceButNotHavingManagedAnnotation()
- {
- ConfiguredObjectTypeRegistry typeRegistry = createConfiguredObjectTypeRegistry(TestRootCategoryImpl.class, TestManagedClass5.class);
- assertEquals("Unexpected interfaces from object not implementing Managed interfaces",
- Collections.emptySet(), typeRegistry.getManagedInterfaces(TestManagedClass5.class));
- }
-
- public void testGetManagedInterfacesForTypesImplementingManagedInterfacesWithManagedAnnotation()
- {
- ConfiguredObjectTypeRegistry typeRegistry = createConfiguredObjectTypeRegistry(TestRootCategoryImpl.class, TestManagedClass0.class, TestManagedClass1.class, TestManagedClass4.class);
- Set<Class<?>> expected = Collections.<Class<?>>singleton(TestManagedInterface1.class);
- assertEquals("Unexpected interfaces on child class", expected, typeRegistry.getManagedInterfaces(TestManagedClass1.class));
- assertEquals("Unexpected interfaces on super class", expected, typeRegistry.getManagedInterfaces(TestManagedClass0.class));
- assertEquals("Unexpected interfaces on class implementing interface with annotation twice",
- expected, typeRegistry.getManagedInterfaces(TestManagedClass4.class));
- }
-
- public void testGetManagedInterfacesForTypeHavingDirectManagedAnnotation()
- {
- ConfiguredObjectTypeRegistry typeRegistry = createConfiguredObjectTypeRegistry(TestRootCategoryImpl.class, TestManagedClass2.class, TestManagedClass3.class);
-
- assertEquals("Unexpected interfaces on class implementing 1 interface with annotation",
- new HashSet<>(Arrays.asList(TestManagedInterface1.class)), typeRegistry.getManagedInterfaces(TestManagedClass2.class));
- assertEquals("Unexpected interfaces on class implementing 2 interfaces with annotation",
- new HashSet<>(Arrays.asList(TestManagedInterface3.class, TestManagedInterface1.class)), typeRegistry.getManagedInterfaces(TestManagedClass3.class));
-
- }
-
- private ConfiguredObjectTypeRegistry createConfiguredObjectTypeRegistry(Class<? extends ConfiguredObject>... supportedTypes)
- {
- ConfiguredObjectRegistration configuredObjectRegistration = createConfiguredObjectRegistration(supportedTypes);
-
- return new ConfiguredObjectTypeRegistry(Arrays.asList(configuredObjectRegistration), Arrays.asList(TestRootCategory.class, TestChildCategory.class));
- }
-
- private ConfiguredObjectRegistration createConfiguredObjectRegistration(final Class<? extends ConfiguredObject>... supportedTypes)
- {
- return new ConfiguredObjectRegistration()
- {
- @Override
- public Collection<Class<? extends ConfiguredObject>> getConfiguredObjectClasses()
- {
- return Arrays.asList(supportedTypes);
- }
-
- @Override
- public String getType()
- {
- return "test";
- }
- };
- }
-
- private void checkDefaultedValue(final Collection<ConfiguredObjectAttribute<?, ?>> attrs,
- final String defaultedValueDefault)
- {
- boolean found = false;
- for(ConfiguredObjectAttribute<?, ?> attr : attrs)
- {
- if(attr.getName().equals("defaultedValue"))
- {
- assertEquals(defaultedValueDefault, ((ConfiguredAutomatedAttribute)attr).defaultValue());
- found = true;
- break;
- }
-
- }
- assertTrue("Could not find attribute defaultedValue", found);
- }
-
- private void checkValidValues(final String attrName, final Collection<ConfiguredObjectAttribute<?, ?>> attrs,
- final Collection<String> validValues)
- {
- boolean found = false;
- for(ConfiguredObjectAttribute<?, ?> attr : attrs)
- {
- if(attr.getName().equals(attrName))
- {
- Collection<String> foundValues = ((ConfiguredAutomatedAttribute<?, ?>) attr).validValues();
- assertEquals("Valid values not as expected, counts differ", validValues.size(), foundValues.size());
- assertTrue("Valid values do not include all expected values", foundValues.containsAll(validValues));
- assertTrue("Valid values contain unexpected addtional values", validValues.containsAll(foundValues));
- found = true;
- break;
- }
-
- }
- assertTrue("Could not find attribute " + attrName, found);
- }
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/Test2RootCategory.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/Test2RootCategory.java
deleted file mode 100644
index 23f03db..0000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/Test2RootCategory.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *
- * 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.testmodel;
-
-import org.apache.qpid.server.model.DerivedAttribute;
-import org.apache.qpid.server.model.ManagedAttribute;
-
-public interface Test2RootCategory<X extends Test2RootCategory<X>> extends TestRootCategory<X>
-{
- String DEFAULTED_VALUE_DEFAULT = "differentDefault";
-
- @Override
- @ManagedAttribute( defaultValue = DEFAULTED_VALUE_DEFAULT)
- String getDefaultedValue();
-
- @Override
- @ManagedAttribute( validValues = {"org.apache.qpid.server.model.testmodel.Test2RootCategoryImpl#functionGeneratedValidValues()"})
- String getValidValue();
-
- @DerivedAttribute
- public int getDerivedAttribute();
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategory.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategory.java
deleted file mode 100644
index de4b1ae..0000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategory.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *
- * 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.testmodel;
-
-import java.util.Set;
-
-import org.apache.qpid.server.model.ConfiguredObject;
-import org.apache.qpid.server.model.ManagedAttribute;
-import org.apache.qpid.server.model.ManagedContextDefault;
-import org.apache.qpid.server.model.ManagedObject;
-
-@ManagedObject
-public interface TestChildCategory<X extends TestChildCategory<X>> extends ConfiguredObject<X>
-{
- String NON_INTERPOLATED_VALID_VALUE = "${file.separator}";
-
- @ManagedAttribute(validValues = { NON_INTERPOLATED_VALID_VALUE }, defaultValue = "")
- String getValidValueNotInterpolated();
-
- @ManagedAttribute( defaultValue = "3" )
- int getIntValue();
-
- @ManagedAttribute( defaultValue = "[ \"1\", \"2\", \"foo\" ]" )
- Set<Integer> getIntegerSet();
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategoryImpl.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategoryImpl.java
deleted file mode 100644
index e12da63..0000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategoryImpl.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *
- * 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.testmodel;
-
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.qpid.server.model.AbstractConfiguredObject;
-import org.apache.qpid.server.model.ManagedAttributeField;
-import org.apache.qpid.server.model.ManagedObject;
-import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
-import org.apache.qpid.server.model.State;
-
-@ManagedObject( category = false , type = "test" )
-public class TestChildCategoryImpl
- extends AbstractConfiguredObject<TestChildCategoryImpl> implements TestChildCategory<TestChildCategoryImpl>
-{
-
-
- @ManagedAttributeField
- private String _validValueNotInterpolated;
-
- @ManagedAttributeField
- private int _intValue;
-
- @ManagedAttributeField
- private Set<Integer> _integerSet;
-
-
- @ManagedObjectFactoryConstructor
- public TestChildCategoryImpl(final Map<String, Object> attributes, TestRootCategory<?> parent)
- {
- super(parentsMap(parent), attributes);
- }
-
- @Override
- public String getValidValueNotInterpolated()
- {
- return _validValueNotInterpolated;
- }
-
- @Override
- public int getIntValue()
- {
- return _intValue;
- }
-
- @Override
- public Set<Integer> getIntegerSet()
- {
- return _integerSet;
- }
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass0.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass0.java
deleted file mode 100644
index 1e53f2e..0000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass0.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *
- * 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.testmodel;
-
-import java.util.Map;
-
-import org.apache.qpid.server.model.ManagedInterface;
-import org.apache.qpid.server.model.ManagedObject;
-
-/**
- * This is a test managed type implementing TestManagedInterface1 which extends ManagedInterface.
- * Because TestManagedInterface1 already has ManagedAnnotation set, the instances of this class will be managed entities
- * of type TestManagedInterface1.
- */
-@ManagedObject( category = false , type = "SuperClass" )
-public class TestManagedClass0 extends TestChildCategoryImpl implements TestManagedInterface1
-{
- public TestManagedClass0(final Map<String, Object> attributes, TestRootCategory<?> parent)
- {
- super(attributes, parent);
- }
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass1.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass1.java
deleted file mode 100644
index c7aa648..0000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass1.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *
- * 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.testmodel;
-
-import java.util.Map;
-
-import org.apache.qpid.server.model.ManagedObject;
-
-/**
- * This is a test managed type extending TestManagedClass0.
- * Because TestManagedClass0 implements managed interface TestManagedInterface1 with ManagedAnnotation set,
- * the instances of this class will be managed entities of type TestManagedInterface1.
- */
-@ManagedObject( category = false , type = "ChildClass" )
-public class TestManagedClass1 extends TestManagedClass0
-{
- public TestManagedClass1(final Map<String, Object> attributes, TestRootCategory<?> parent)
- {
- super(attributes, parent);
- }
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass2.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass2.java
deleted file mode 100644
index 62cc0c0..0000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass2.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *
- * 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.testmodel;
-
-import java.util.Map;
-
-import org.apache.qpid.server.model.ManagedObject;
-
-/**
- * This is a test managed type implementing managed interface TestManagedInterface2 and having ManagedAnnotation set.
- * The instances of this class will be managed entities of type TestManagedInterface1
- */
-@ManagedObject( category = false , type = "ChildClass2" )
-public class TestManagedClass2 extends TestManagedClass0 implements TestManagedInterface2
-{
- public TestManagedClass2(final Map<String, Object> attributes, TestRootCategory<?> parent)
- {
- super(attributes, parent);
- }
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass3.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass3.java
deleted file mode 100644
index c78f740..0000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass3.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *
- * 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.testmodel;
-
-import java.util.Map;
-
-import org.apache.qpid.server.model.ManagedObject;
-
-/**
- * This is a test managed type implementing managed interface TestManagedInterface1 and TestManagedInterface3.
- * The instances of this class will be managed entities of types TestManagedInterface1 and TestManagedInterface3.
- */
-@ManagedObject( category = false , type = "ChildClass3" )
-public class TestManagedClass3 extends TestChildCategoryImpl implements TestManagedInterface1,TestManagedInterface3
-{
- public TestManagedClass3(final Map<String, Object> attributes, TestRootCategory<?> parent)
- {
- super(attributes, parent);
- }
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass4.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass4.java
deleted file mode 100644
index ff8f4b0..0000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass4.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *
- * 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.testmodel;
-
-import java.util.Map;
-
-import org.apache.qpid.server.model.ManagedObject;
-
-/**
- * This is a test managed type extending managed type TestManagedClass0 and implementing TestManagedInterface2
- * The instances of this class will be managed entities of types TestManagedInterface1 only
- * as it has no direct ManagedAnnotation set and no ManagedAnnotation declared in TestManagedInterface2.
- */
-@ManagedObject( category = false , type = "ChildClass4" )
-public class TestManagedClass4 extends TestManagedClass0 implements TestManagedInterface2
-{
- public TestManagedClass4(final Map<String, Object> attributes, TestRootCategory<?> parent)
- {
- super(attributes, parent);
- }
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass5.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass5.java
deleted file mode 100644
index 5894363..0000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedClass5.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *
- * 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.testmodel;
-
-import java.util.Map;
-
-import org.apache.qpid.server.model.ManagedObject;
-
-/**
- * This is a test type which has no ManagedAnnotation set and thus it should not expose any ManagedInterface
- */
-@ManagedObject( category = false , type = "ChildClass3" )
-public class TestManagedClass5 extends TestChildCategoryImpl implements TestManagedInterface2
-{
- public TestManagedClass5(final Map<String, Object> attributes, TestRootCategory<?> parent)
- {
- super(attributes, parent);
- }
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface1.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface1.java
deleted file mode 100644
index aac5ada..0000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface1.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *
- * 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.testmodel;
-
-import org.apache.qpid.server.model.ManagedAnnotation;
-import org.apache.qpid.server.model.ManagedInterface;
-
-/**
- * This is a test managed interface which has ManagedAnnotation.
- * All types implementing this interface will inherit the annotation and will be managed entities of type TestManagedInterface1
- */
-@ManagedAnnotation
-public interface TestManagedInterface1 extends ManagedInterface
-{
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface2.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface2.java
deleted file mode 100644
index 7ecb2d6..0000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface2.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *
- * 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.testmodel;
-
-import org.apache.qpid.server.model.ManagedInterface;
-
-/**
- * This is a test managed interface which has no ManagedAnnotation.
- * All types implementing this interface would need to have ManagedAnnotation declared in order to became managed entity.
- */
-public interface TestManagedInterface2 extends ManagedInterface
-{
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestRootCategoryImpl.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestRootCategoryImpl.java
deleted file mode 100644
index 7e92186..0000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestRootCategoryImpl.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- *
- * 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.testmodel;
-
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
-import org.apache.qpid.server.configuration.updater.TaskExecutor;
-import org.apache.qpid.server.model.AbstractConfiguredObject;
-import org.apache.qpid.server.model.ManagedAttributeField;
-import org.apache.qpid.server.model.ManagedObject;
-import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
-
-@ManagedObject( category = false , type = "test" )
-public class TestRootCategoryImpl extends AbstractConfiguredObject<TestRootCategoryImpl>
- implements TestRootCategory<TestRootCategoryImpl>
-{
- @ManagedAttributeField
- private String _automatedPersistedValue;
-
- @ManagedAttributeField
- private String _automatedNonPersistedValue;
-
- @ManagedAttributeField
- private String _defaultedValue;
-
- @ManagedAttributeField
- private String _stringValue;
-
- @ManagedAttributeField
- private Map<String,String> _mapValue;
-
- @ManagedAttributeField
- private String _validValue;
-
- @ManagedAttributeField
- private TestEnum _enumValue;
-
- @ManagedAttributeField
- private Set<TestEnum> _enumSetValues;
-
-
- @ManagedObjectFactoryConstructor
- public TestRootCategoryImpl(final Map<String, Object> attributes)
- {
- super(parentsMap(), attributes, newTaskExecutor(), TestModel.getInstance());
- }
-
- private static CurrentThreadTaskExecutor newTaskExecutor()
- {
- CurrentThreadTaskExecutor currentThreadTaskExecutor = new CurrentThreadTaskExecutor();
- currentThreadTaskExecutor.start();
- return currentThreadTaskExecutor;
- }
-
- public TestRootCategoryImpl(final Map<String, Object> attributes,
- final TaskExecutor taskExecutor)
- {
- super(parentsMap(), attributes, taskExecutor);
- }
-
-
- @Override
- public String getAutomatedPersistedValue()
- {
- return _automatedPersistedValue;
- }
-
- @Override
- public String getAutomatedNonPersistedValue()
- {
- return _automatedNonPersistedValue;
- }
-
- @Override
- public String getDefaultedValue()
- {
- return _defaultedValue;
- }
-
- @Override
- public String getStringValue()
- {
- return _stringValue;
- }
-
- @Override
- public Map<String, String> getMapValue()
- {
- return _mapValue;
- }
-
- @Override
- public TestEnum getEnumValue()
- {
- return _enumValue;
- }
-
- @Override
- public Set<TestEnum> getEnumSetValues()
- {
- return _enumSetValues;
- }
-
- @Override
- public String getValidValue()
- {
- return _validValue;
- }
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/AbstractConfiguredObjectTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/AbstractConfiguredObjectTest.java
new file mode 100644
index 0000000..474f7c4
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/AbstractConfiguredObjectTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.testmodels.hierarchy;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+/**
+ * Tests behaviour of AbstractConfiguredObjects when hierarchies of objects are used together.
+ * Responsibilities to include adding/removing of children and correct firing of listeners.
+ */
+public class AbstractConfiguredObjectTest extends QpidTestCase
+{
+ private final Model _model = TestModel.getInstance();
+
+ public void testCreateCategoryDefault()
+ {
+ final String objectName = "testCreateCategoryDefault";
+ Map<String, Object> attributes = Collections.<String, Object>singletonMap(ConfiguredObject.NAME, objectName);
+
+ TestCar object = _model.getObjectFactory().create(TestCar.class, attributes);
+
+ assertEquals(objectName, object.getName());
+ assertEquals(TestStandardCarImpl.TEST_STANDARD_CAR_TYPE, object.getType());
+ assertTrue(object instanceof TestStandardCar);
+ }
+
+ public void testCreateUnrecognisedType()
+ {
+ final String objectName = "testCreateCategoryDefault";
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(ConfiguredObject.NAME, objectName);
+ attributes.put(ConfiguredObject.TYPE, "notatype");
+
+ try
+ {
+ _model.getObjectFactory().create(TestCar.class, attributes);
+ fail("Exception not thrown");
+ }
+ catch (IllegalConfigurationException ice)
+ {
+ // PASS
+ }
+ }
+
+ public void testCreateCarWithEngine()
+ {
+ final String carName = "myCar";
+ Map<String, Object> carAttributes = new HashMap<>();
+ carAttributes.put(ConfiguredObject.NAME, carName);
+ carAttributes.put(ConfiguredObject.TYPE, TestKitCarImpl.TEST_KITCAR_TYPE);
+
+ TestCar car = _model.getObjectFactory().create(TestCar.class, carAttributes);
+
+ assertEquals(carName, car.getName());
+
+ assertEquals(0, car.getChildren(TestEngine.class).size());
+
+ String engineName = "myEngine";
+
+ Map<String, Object> engineAttributes = new HashMap<>();
+ engineAttributes.put(ConfiguredObject.NAME, engineName);
+ engineAttributes.put(ConfiguredObject.TYPE, TestElecEngineImpl.TEST_ELEC_ENGINE_TYPE);
+
+ TestEngine engine = (TestEngine) car.createChild(TestEngine.class, engineAttributes);
+
+ assertEquals(1, car.getChildren(TestEngine.class).size());
+
+ assertEquals(engineName, engine.getName());
+ assertEquals(TestElecEngineImpl.TEST_ELEC_ENGINE_TYPE, engine.getType());
+
+ }
+
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/ConfiguredObjectTypeRegistryTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/ConfiguredObjectTypeRegistryTest.java
new file mode 100644
index 0000000..ea17238
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/ConfiguredObjectTypeRegistryTest.java
@@ -0,0 +1,74 @@
+/*
+ *
+ * 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.testmodels.hierarchy;
+
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.Collection;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObjectTypeRegistry;
+import org.apache.qpid.server.model.ManagedInterface;
+
+public class ConfiguredObjectTypeRegistryTest extends TestCase
+{
+ private ConfiguredObjectTypeRegistry _typeRegistry = TestModel.getInstance().getTypeRegistry();
+
+ public void testTypeSpecialisations()
+ {
+ Collection<Class<? extends ConfiguredObject>> types = _typeRegistry.getTypeSpecialisations(TestEngine.class);
+
+ assertEquals("Unexpected number of specialisations for " + TestEngine.class + " Found : " + types, 3, types.size());
+ assertTrue(types.contains(TestPetrolEngineImpl.class));
+ assertTrue(types.contains(TestHybridEngineImpl.class));
+ assertTrue(types.contains(TestElecEngineImpl.class));
+ }
+
+ public void testGetValidChildTypes()
+ {
+ // The standard car restricts its engine type
+ Collection<String> standardCarValidEnginesTypes = _typeRegistry.getValidChildTypes(TestStandardCarImpl.class, TestEngine.class);
+ assertThat(standardCarValidEnginesTypes, hasItem(TestPetrolEngineImpl.TEST_PETROL_ENGINE_TYPE));
+ assertThat(standardCarValidEnginesTypes, hasItem(TestHybridEngineImpl.TEST_HYBRID_ENGINE_TYPE));
+ assertThat(standardCarValidEnginesTypes.size(), is(2));
+
+ Collection<String> kitCarValidEngineTypes = _typeRegistry.getValidChildTypes(TestKitCarImpl.class, TestEngine.class);
+ // Would it be more useful to producers of management UIs if this were populated with all possible types?
+ assertNull(kitCarValidEngineTypes);
+ }
+
+ public void testManagedInterfaces()
+ {
+ // The electric engine is recharable
+ Set<Class<? extends ManagedInterface>> elecEngIntfcs = _typeRegistry.getManagedInterfaces(TestElecEngine.class);
+ assertThat(elecEngIntfcs, hasItem(TestRechargeable.class));
+ assertThat(elecEngIntfcs.size(), is(1));
+
+ // The pertrol engine implements no additional interfaces
+ Set<Class<? extends ManagedInterface>> stdCarIntfcs = _typeRegistry.getManagedInterfaces(TestPetrolEngine.class);
+ assertThat(stdCarIntfcs.size(), is(0));
+ }
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestCar.java
similarity index 71%
copy from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
copy to qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestCar.java
index 75c6c19..e2c436e 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestCar.java
@@ -1,4 +1,5 @@
/*
+ *
* 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
@@ -15,18 +16,14 @@
* 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.testmodels.hierarchy;
-package org.apache.qpid.server.model.testmodel;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ManagedObject;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-public enum TestEnum
+@ManagedObject( defaultType = TestStandardCarImpl.TEST_STANDARD_CAR_TYPE)
+public interface TestCar<X extends TestCar<X>> extends ConfiguredObject<X>
{
- TEST_ENUM1,
- TEST_ENUM2,
- TEST_ENUM3;
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestElecCar.java
similarity index 78%
copy from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
copy to qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestElecCar.java
index 75c6c19..dc8f65d 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestElecCar.java
@@ -17,16 +17,11 @@
* under the License.
*/
-package org.apache.qpid.server.model.testmodel;
+package org.apache.qpid.server.model.testmodels.hierarchy;
+import org.apache.qpid.server.model.ManagedObject;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-public enum TestEnum
+@ManagedObject(category = false)
+public interface TestElecCar<X extends TestElecCar<X>> extends TestCar<X>
{
- TEST_ENUM1,
- TEST_ENUM2,
- TEST_ENUM3;
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestElecEngine.java
similarity index 76%
copy from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
copy to qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestElecEngine.java
index 75c6c19..7dc3d8d 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestElecEngine.java
@@ -17,16 +17,11 @@
* under the License.
*/
-package org.apache.qpid.server.model.testmodel;
+package org.apache.qpid.server.model.testmodels.hierarchy;
+import org.apache.qpid.server.model.ManagedObject;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-public enum TestEnum
+@ManagedObject (category = false)
+public interface TestElecEngine<X extends TestElecEngine<X>> extends TestEngine<X>, TestRechargeable
{
- TEST_ENUM1,
- TEST_ENUM2,
- TEST_ENUM3;
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestElecEngineImpl.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestElecEngineImpl.java
new file mode 100644
index 0000000..c875aea
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestElecEngineImpl.java
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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.testmodels.hierarchy;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+
+@ManagedObject( category = false, type = TestElecEngineImpl.TEST_ELEC_ENGINE_TYPE)
+public class TestElecEngineImpl
+ extends AbstractConfiguredObject<TestElecEngineImpl> implements TestElecEngine<TestElecEngineImpl>
+{
+ public static final String TEST_ELEC_ENGINE_TYPE = "ELEC";
+
+ @ManagedObjectFactoryConstructor
+ public TestElecEngineImpl(final Map<String, Object> attributes, TestCar<?> parent)
+ {
+ super(parentsMap(parent), attributes);
+ }
+
+ @SuppressWarnings("unused")
+ public static Map<String, Collection<String>> getSupportedChildTypes()
+ {
+ Collection<String> types = Arrays.asList(TestElecEngineImpl.TEST_ELEC_ENGINE_TYPE);
+ return Collections.singletonMap(TestEngine.class.getSimpleName(), types);
+ }
+
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface3.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestEngine.java
similarity index 74%
copy from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface3.java
copy to qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestEngine.java
index d1d0a1b..a6754b2 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface3.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestEngine.java
@@ -18,12 +18,12 @@
* under the License.
*
*/
-package org.apache.qpid.server.model.testmodel;
+package org.apache.qpid.server.model.testmodels.hierarchy;
-import org.apache.qpid.server.model.ManagedAnnotation;
-import org.apache.qpid.server.model.ManagedInterface;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ManagedObject;
-@ManagedAnnotation
-public interface TestManagedInterface3 extends ManagedInterface
+@ManagedObject(category = true)
+public interface TestEngine<X extends TestEngine<X>> extends ConfiguredObject<X>
{
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestHybridEngine.java
similarity index 76%
copy from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
copy to qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestHybridEngine.java
index 75c6c19..322a44e 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestHybridEngine.java
@@ -16,17 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.qpid.server.model.testmodels.hierarchy;
-package org.apache.qpid.server.model.testmodel;
+import org.apache.qpid.server.model.ManagedObject;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-public enum TestEnum
+@ManagedObject (category = false)
+public interface TestHybridEngine<X extends TestHybridEngine<X>> extends TestEngine<X>, TestRechargeable
{
- TEST_ENUM1,
- TEST_ENUM2,
- TEST_ENUM3;
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestHybridEngineImpl.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestHybridEngineImpl.java
new file mode 100644
index 0000000..dd6cd03
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestHybridEngineImpl.java
@@ -0,0 +1,38 @@
+/*
+ * 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.testmodels.hierarchy;
+
+import java.util.Map;
+
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+
+@ManagedObject( category = false, type = TestHybridEngineImpl.TEST_HYBRID_ENGINE_TYPE)
+public class TestHybridEngineImpl extends AbstractConfiguredObject<TestHybridEngineImpl> implements TestHybridEngine<TestHybridEngineImpl>
+{
+ public static final String TEST_HYBRID_ENGINE_TYPE = "HYBRID";
+
+ @ManagedObjectFactoryConstructor
+ public TestHybridEngineImpl(final Map<String, Object> attributes, TestCar<?> parent)
+ {
+ super(parentsMap(parent), attributes);
+ }
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestKitCar.java
similarity index 78%
copy from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
copy to qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestKitCar.java
index 75c6c19..742f957 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestKitCar.java
@@ -16,17 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.qpid.server.model.testmodels.hierarchy;
-package org.apache.qpid.server.model.testmodel;
+import org.apache.qpid.server.model.ManagedObject;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-public enum TestEnum
+@ManagedObject(category = false)
+public interface TestKitCar<X extends TestKitCar<X>> extends TestCar<X>
{
- TEST_ENUM1,
- TEST_ENUM2,
- TEST_ENUM3;
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestKitCarImpl.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestKitCarImpl.java
new file mode 100644
index 0000000..5785071
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestKitCarImpl.java
@@ -0,0 +1,56 @@
+/*
+ * 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.testmodels.hierarchy;
+
+import java.util.Map;
+
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+
+@ManagedObject( category = false,
+ type = TestKitCarImpl.TEST_KITCAR_TYPE)
+public class TestKitCarImpl extends AbstractConfiguredObject<TestKitCarImpl>
+ implements TestKitCar<TestKitCarImpl>
+{
+ public static final String TEST_KITCAR_TYPE = "testkitcar";
+
+ @ManagedObjectFactoryConstructor
+ public TestKitCarImpl(final Map<String, Object> attributes)
+ {
+ super(parentsMap(), attributes, newTaskExecutor(), TestModel.getInstance());
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(final Class<C> childClass,
+ final Map<String, Object> attributes,
+ final ConfiguredObject... otherParents)
+ {
+ return (C) getObjectFactory().create(childClass, attributes, this);
+ }
+
+ private static CurrentThreadTaskExecutor newTaskExecutor()
+ {
+ CurrentThreadTaskExecutor currentThreadTaskExecutor = new CurrentThreadTaskExecutor();
+ currentThreadTaskExecutor.start();
+ return currentThreadTaskExecutor;
+ }
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestModel.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestModel.java
similarity index 74%
copy from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestModel.java
copy to qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestModel.java
index ab9d753..31ee8c2 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestModel.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestModel.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpid.server.model.testmodel;
+package org.apache.qpid.server.model.testmodels.hierarchy;
import java.util.Arrays;
import java.util.Collection;
@@ -34,10 +34,10 @@
public class TestModel extends Model
{
private static final Model INSTANCE = new TestModel();
- private Class<? extends ConfiguredObject>[] _supportedClasses =
+ private Class<? extends ConfiguredObject>[] _supportedCategories =
new Class[] {
- TestRootCategory.class,
- TestChildCategory.class
+ TestCar.class,
+ TestEngine.class
};
private final ConfiguredObjectFactory _objectFactory;
@@ -51,49 +51,38 @@
public TestModel(final ConfiguredObjectFactory objectFactory)
{
_objectFactory = objectFactory == null ? new ConfiguredObjectFactoryImpl(this) : objectFactory;
- ConfiguredObjectRegistration configuredObjectRegistration = new ConfiguredObjectRegistration()
- {
- @Override
- public Collection<Class<? extends ConfiguredObject>> getConfiguredObjectClasses()
- {
- return Arrays.<Class<? extends ConfiguredObject>>asList(TestRootCategoryImpl.class, Test2RootCategoryImpl.class);
- }
- @Override
- public String getType()
- {
- return "test";
- }
- };
- _registry = new ConfiguredObjectTypeRegistry(Arrays.asList(configuredObjectRegistration), getSupportedCategories());
+ ConfiguredObjectRegistration configuredObjectRegistration = new ConfiguredObjectRegistrationImpl();
+
+ _registry = new ConfiguredObjectTypeRegistry(Collections.singletonList(configuredObjectRegistration), Collections.EMPTY_LIST);
}
@Override
public Collection<Class<? extends ConfiguredObject>> getSupportedCategories()
{
- return Arrays.asList(_supportedClasses);
+ return Arrays.asList(_supportedCategories);
}
@Override
public Collection<Class<? extends ConfiguredObject>> getChildTypes(final Class<? extends ConfiguredObject> parent)
{
- return TestRootCategory.class.isAssignableFrom(parent)
- ? Collections.<Class<? extends ConfiguredObject>>singleton(TestChildCategory.class)
+ return TestCar.class.isAssignableFrom(parent)
+ ? Collections.<Class<? extends ConfiguredObject>>singleton(TestEngine.class)
: Collections.<Class<? extends ConfiguredObject>>emptySet();
}
@Override
public Class<? extends ConfiguredObject> getRootCategory()
{
- return TestRootCategory.class;
+ return TestCar.class;
}
@Override
public Collection<Class<? extends ConfiguredObject>> getParentTypes(final Class<? extends ConfiguredObject> child)
{
- return TestChildCategory.class.isAssignableFrom(child)
- ? Collections.<Class<? extends ConfiguredObject>>singleton(TestRootCategory.class)
+ return TestEngine.class.isAssignableFrom(child)
+ ? Collections.<Class<? extends ConfiguredObject>>singleton(TestCar.class)
: Collections.<Class<? extends ConfiguredObject>>emptySet();
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestPetrolEngine.java
similarity index 77%
copy from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
copy to qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestPetrolEngine.java
index 75c6c19..7ca6953 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestPetrolEngine.java
@@ -17,16 +17,11 @@
* under the License.
*/
-package org.apache.qpid.server.model.testmodel;
+package org.apache.qpid.server.model.testmodels.hierarchy;
+import org.apache.qpid.server.model.ManagedObject;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-public enum TestEnum
+@ManagedObject (category = false)
+public interface TestPetrolEngine<X extends TestPetrolEngine<X>> extends TestEngine<X>
{
- TEST_ENUM1,
- TEST_ENUM2,
- TEST_ENUM3;
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestPetrolEngineImpl.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestPetrolEngineImpl.java
new file mode 100644
index 0000000..8047db3
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestPetrolEngineImpl.java
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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.testmodels.hierarchy;
+
+import java.util.Map;
+
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+
+@ManagedObject( category = false, type = TestPetrolEngineImpl.TEST_PETROL_ENGINE_TYPE)
+public class TestPetrolEngineImpl
+ extends AbstractConfiguredObject<TestPetrolEngineImpl> implements TestPetrolEngine<TestPetrolEngineImpl>
+{
+ public static final String TEST_PETROL_ENGINE_TYPE = "PETROL";
+
+ @ManagedObjectFactoryConstructor
+ public TestPetrolEngineImpl(final Map<String, Object> attributes, TestCar<?> parent)
+ {
+ super(parentsMap(parent), attributes);
+ }
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface3.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestRechargeable.java
similarity index 88%
rename from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface3.java
rename to qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestRechargeable.java
index d1d0a1b..26eed78 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestManagedInterface3.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestRechargeable.java
@@ -18,12 +18,13 @@
* under the License.
*
*/
-package org.apache.qpid.server.model.testmodel;
+package org.apache.qpid.server.model.testmodels.hierarchy;
import org.apache.qpid.server.model.ManagedAnnotation;
import org.apache.qpid.server.model.ManagedInterface;
+
@ManagedAnnotation
-public interface TestManagedInterface3 extends ManagedInterface
+public interface TestRechargeable extends ManagedInterface
{
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestStandardCar.java
similarity index 77%
copy from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
copy to qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestStandardCar.java
index 75c6c19..302eb41 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestStandardCar.java
@@ -17,16 +17,11 @@
* under the License.
*/
-package org.apache.qpid.server.model.testmodel;
+package org.apache.qpid.server.model.testmodels.hierarchy;
+import org.apache.qpid.server.model.ManagedObject;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-public enum TestEnum
+@ManagedObject(category = false)
+public interface TestStandardCar<X extends TestStandardCar<X>> extends TestCar<X>
{
- TEST_ENUM1,
- TEST_ENUM2,
- TEST_ENUM3;
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestStandardCarImpl.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestStandardCarImpl.java
new file mode 100644
index 0000000..83dfd73
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestStandardCarImpl.java
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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.testmodels.hierarchy;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+
+@ManagedObject( category = false,
+ type = TestStandardCarImpl.TEST_STANDARD_CAR_TYPE,
+ validChildTypes = "org.apache.qpid.server.model.testmodels.hierarchy.TestStandardCarImpl#getSupportedChildTypes()")
+public class TestStandardCarImpl extends AbstractConfiguredObject<TestStandardCarImpl>
+ implements TestStandardCar<TestStandardCarImpl>
+{
+ public static final String TEST_STANDARD_CAR_TYPE = "testpertrolcar";
+
+ @ManagedObjectFactoryConstructor
+ public TestStandardCarImpl(final Map<String, Object> attributes)
+ {
+ super(parentsMap(), attributes, newTaskExecutor(), TestModel.getInstance());
+ }
+
+ private static CurrentThreadTaskExecutor newTaskExecutor()
+ {
+ CurrentThreadTaskExecutor currentThreadTaskExecutor = new CurrentThreadTaskExecutor();
+ currentThreadTaskExecutor.start();
+ return currentThreadTaskExecutor;
+ }
+
+ @SuppressWarnings("unused")
+ public static Map<String, Collection<String>> getSupportedChildTypes()
+ {
+ Collection<String> types = Arrays.asList(TestPetrolEngineImpl.TEST_PETROL_ENGINE_TYPE, TestHybridEngineImpl.TEST_HYBRID_ENGINE_TYPE);
+ return Collections.singletonMap(TestEngine.class.getSimpleName(), types);
+ }
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/AbstractConfiguredObjectTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/AbstractConfiguredObjectTest.java
new file mode 100644
index 0000000..ea23692
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/AbstractConfiguredObjectTest.java
@@ -0,0 +1,217 @@
+/*
+ * 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.testmodels.lifecycle;
+
+import java.util.Collections;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class AbstractConfiguredObjectTest extends QpidTestCase
+{
+
+ public void testOpeningResultsInErroredStateWhenResolutionFails() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnPostResolve(true);
+ object.open();
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ERRORED, object.getState());
+
+ object.setThrowExceptionOnPostResolve(false);
+ object.setAttributes(Collections.<String, Object>singletonMap(Port.DESIRED_STATE, State.ACTIVE));
+ assertTrue("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ACTIVE, object.getState());
+ }
+
+ public void testOpeningInERROREDStateAfterFailedOpenOnDesiredStateChangeToActive() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnOpen(true);
+ object.open();
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ERRORED, object.getState());
+
+ object.setThrowExceptionOnOpen(false);
+ object.setAttributes(Collections.<String, Object>singletonMap(Port.DESIRED_STATE, State.ACTIVE));
+ assertTrue("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ACTIVE, object.getState());
+ }
+
+ public void testOpeningInERROREDStateAfterFailedOpenOnStart() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnOpen(true);
+ object.open();
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ERRORED, object.getState());
+
+ object.setThrowExceptionOnOpen(false);
+ object.start();
+ assertTrue("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ACTIVE, object.getState());
+ }
+
+ public void testDeletionERROREDStateAfterFailedOpenOnDelete() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnOpen(true);
+ object.open();
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ERRORED, object.getState());
+
+ object.delete();
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.DELETED, object.getState());
+ }
+
+ public void testDeletionInERROREDStateAfterFailedOpenOnDesiredStateChangeToDelete() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnOpen(true);
+ object.open();
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ERRORED, object.getState());
+
+ object.setAttributes(Collections.<String, Object>singletonMap(Port.DESIRED_STATE, State.DELETED));
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.DELETED, object.getState());
+ }
+
+
+ public void testCreationWithExceptionThrownFromValidationOnCreate() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnValidationOnCreate(true);
+ try
+ {
+ object.create();
+ fail("IllegalConfigurationException is expected to be thrown");
+ }
+ catch(IllegalConfigurationException e)
+ {
+ //pass
+ }
+ assertFalse("Unexpected opened", object.isOpened());
+ }
+
+ public void testCreationWithoutExceptionThrownFromValidationOnCreate() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnValidationOnCreate(false);
+ object.create();
+ assertTrue("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ACTIVE, object.getState());
+ }
+
+ public void testCreationWithExceptionThrownFromOnOpen() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnOpen(true);
+ try
+ {
+ object.create();
+ fail("Exception should have been re-thrown");
+ }
+ catch (RuntimeException re)
+ {
+ // pass
+ }
+
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.DELETED, object.getState());
+ }
+
+ public void testCreationWithExceptionThrownFromOnCreate() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnCreate(true);
+ try
+ {
+ object.create();
+ fail("Exception should have been re-thrown");
+ }
+ catch (RuntimeException re)
+ {
+ // pass
+ }
+
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.DELETED, object.getState());
+ }
+
+ public void testUnresolvedChildInERROREDStateIsNotValidatedOrOpenedOrAttainedDesiredStateOnParentOpen() throws Exception
+ {
+ TestConfiguredObject parent = new TestConfiguredObject("parent");
+ TestConfiguredObject child1 = new TestConfiguredObject("child1", parent, parent.getTaskExecutor());
+ child1.registerWithParents();
+ TestConfiguredObject child2 = new TestConfiguredObject("child2", parent, parent.getTaskExecutor());
+ child2.registerWithParents();
+
+ child1.setThrowExceptionOnPostResolve(true);
+
+ parent.open();
+
+ assertTrue("Parent should be resolved", parent.isResolved());
+ assertTrue("Parent should be validated", parent.isValidated());
+ assertTrue("Parent should be opened", parent.isOpened());
+ assertEquals("Unexpected parent state", State.ACTIVE, parent.getState());
+
+ assertTrue("Child2 should be resolved", child2.isResolved());
+ assertTrue("Child2 should be validated", child2.isValidated());
+ assertTrue("Child2 should be opened", child2.isOpened());
+ assertEquals("Unexpected child2 state", State.ACTIVE, child2.getState());
+
+ assertFalse("Child2 should not be resolved", child1.isResolved());
+ assertFalse("Child1 should not be validated", child1.isValidated());
+ assertFalse("Child1 should not be opened", child1.isOpened());
+ assertEquals("Unexpected child1 state", State.ERRORED, child1.getState());
+ }
+
+ public void testUnvalidatedChildInERROREDStateIsNotOpenedOrAttainedDesiredStateOnParentOpen() throws Exception
+ {
+ TestConfiguredObject parent = new TestConfiguredObject("parent");
+ TestConfiguredObject child1 = new TestConfiguredObject("child1", parent, parent.getTaskExecutor());
+ child1.registerWithParents();
+ TestConfiguredObject child2 = new TestConfiguredObject("child2", parent, parent.getTaskExecutor());
+ child2.registerWithParents();
+
+ child1.setThrowExceptionOnValidate(true);
+
+ parent.open();
+
+ assertTrue("Parent should be resolved", parent.isResolved());
+ assertTrue("Parent should be validated", parent.isValidated());
+ assertTrue("Parent should be opened", parent.isOpened());
+ assertEquals("Unexpected parent state", State.ACTIVE, parent.getState());
+
+ assertTrue("Child2 should be resolved", child2.isResolved());
+ assertTrue("Child2 should be validated", child2.isValidated());
+ assertTrue("Child2 should be opened", child2.isOpened());
+ assertEquals("Unexpected child2 state", State.ACTIVE, child2.getState());
+
+ assertTrue("Child1 should be resolved", child1.isResolved());
+ assertFalse("Child1 should not be validated", child1.isValidated());
+ assertFalse("Child1 should not be opened", child1.isOpened());
+ assertEquals("Unexpected child1 state", State.ERRORED, child1.getState());
+ }
+
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestConfiguredObject.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/TestConfiguredObject.java
similarity index 98%
rename from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestConfiguredObject.java
rename to qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/TestConfiguredObject.java
index 8f61e37..0b35ba9 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestConfiguredObject.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/TestConfiguredObject.java
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpid.server.model.testmodel;
+
+package org.apache.qpid.server.model.testmodels.lifecycle;
import static org.mockito.Mockito.mock;
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/AbstractConfiguredObjectTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/AbstractConfiguredObjectTest.java
new file mode 100644
index 0000000..46f2051
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/AbstractConfiguredObjectTest.java
@@ -0,0 +1,479 @@
+/*
+ * 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.testmodels.singleton;
+
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.store.ConfiguredObjectRecord;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+/**
+ * Tests behaviour of AbstractConfiguredObject related to attributes including
+ * persistence, defaulting, and attribute values derived from context variables.
+ */
+public class AbstractConfiguredObjectTest extends QpidTestCase
+{
+ private final Model _model = TestModel.getInstance();
+
+ public void testAttributePersistence()
+ {
+ final String objectName = "testNonPersistAttributes";
+ TestSingleton object =
+ _model.getObjectFactory().create(TestSingleton.class,
+ Collections.<String, Object>singletonMap(ConfiguredObject.NAME,
+ objectName)
+ );
+
+ assertEquals(objectName, object.getName());
+ assertNull(object.getAutomatedNonPersistedValue());
+ assertNull(object.getAutomatedPersistedValue());
+ assertEquals(TestSingletonImpl.DERIVED_VALUE, object.getDerivedValue());
+
+ ConfiguredObjectRecord record = object.asObjectRecord();
+
+ assertEquals(objectName, record.getAttributes().get(ConfiguredObject.NAME));
+
+ assertFalse(record.getAttributes().containsKey(TestSingleton.AUTOMATED_PERSISTED_VALUE));
+ assertFalse(record.getAttributes().containsKey(TestSingleton.AUTOMATED_NONPERSISTED_VALUE));
+ assertFalse(record.getAttributes().containsKey(TestSingleton.DERIVED_VALUE));
+
+ Map<String, Object> updatedAttributes = new HashMap<>();
+
+ final String newValue = "newValue";
+
+ updatedAttributes.put(TestSingleton.AUTOMATED_PERSISTED_VALUE, newValue);
+ updatedAttributes.put(TestSingleton.AUTOMATED_NONPERSISTED_VALUE, newValue);
+ updatedAttributes.put(TestSingleton.DERIVED_VALUE, System.currentTimeMillis()); // Will be ignored
+ object.setAttributes(updatedAttributes);
+
+ assertEquals(newValue, object.getAutomatedPersistedValue());
+ assertEquals(newValue, object.getAutomatedNonPersistedValue());
+
+ record = object.asObjectRecord();
+ assertEquals(objectName, record.getAttributes().get(ConfiguredObject.NAME));
+ assertEquals(newValue, record.getAttributes().get(TestSingleton.AUTOMATED_PERSISTED_VALUE));
+
+ assertFalse(record.getAttributes().containsKey(TestSingleton.AUTOMATED_NONPERSISTED_VALUE));
+ assertFalse(record.getAttributes().containsKey(TestSingleton.DERIVED_VALUE));
+
+ }
+
+ public void testDefaultedAttributeValue()
+ {
+ final String objectName = "myName";
+
+ Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestSingleton.NAME, objectName);
+
+ TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
+ attributes);
+
+ assertEquals(objectName, object1.getName());
+ assertEquals(TestSingleton.DEFAULTED_VALUE_DEFAULT, object1.getDefaultedValue());
+ }
+
+ public void testOverriddenDefaultedAttributeValue()
+ {
+ final String objectName = "myName";
+
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(TestSingleton.NAME, objectName);
+ attributes.put(TestSingleton.DEFAULTED_VALUE, "override");
+
+ TestSingleton object = _model.getObjectFactory().create(TestSingleton.class,
+ attributes);
+
+ assertEquals(objectName, object.getName());
+ assertEquals("override", object.getDefaultedValue());
+
+ }
+
+ public void testOverriddenDefaultedAttributeValueRevertedToDefault()
+ {
+ final String objectName = "myName";
+
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(TestSingleton.NAME, objectName);
+ attributes.put(TestSingleton.DEFAULTED_VALUE, "override");
+
+ TestSingleton object = _model.getObjectFactory().create(TestSingleton.class,
+ attributes);
+
+ assertEquals(objectName, object.getName());
+ assertEquals("override", object.getDefaultedValue());
+
+ object.setAttributes(Collections.singletonMap(TestSingleton.DEFAULTED_VALUE, null));
+
+ assertEquals(TestSingleton.DEFAULTED_VALUE_DEFAULT, object.getDefaultedValue());
+ }
+
+ public void testEnumAttributeValueFromString()
+ {
+ final String objectName = "myName";
+
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(TestSingleton.NAME, objectName);
+ attributes.put(TestSingleton.ENUM_VALUE, TestEnum.TEST_ENUM1.name());
+
+ TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
+ attributes);
+
+ assertEquals(objectName, object1.getName());
+ assertEquals(TestEnum.TEST_ENUM1, object1.getEnumValue());
+ }
+
+ public void testEnumAttributeValueFromEnum()
+ {
+ final String objectName = "myName";
+
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(TestSingleton.NAME, objectName);
+ attributes.put(TestSingleton.ENUM_VALUE, TestEnum.TEST_ENUM1);
+
+ TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
+ attributes);
+
+ assertEquals(objectName, object1.getName());
+ assertEquals(TestEnum.TEST_ENUM1, object1.getEnumValue());
+ }
+
+ public void testIntegerAttributeValueFromString()
+ {
+ final String objectName = "myName";
+
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(TestSingleton.NAME, objectName);
+ attributes.put(TestSingleton.INT_VALUE, "-4");
+
+ TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
+ attributes);
+
+ assertEquals(objectName, object1.getName());
+ assertEquals(-4, object1.getIntValue());
+ }
+
+ public void testIntegerAttributeValueFromInteger()
+ {
+ final String objectName = "myName";
+
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(TestSingleton.NAME, objectName);
+ attributes.put(TestSingleton.INT_VALUE, 5);
+
+ TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
+ attributes);
+
+ assertEquals(objectName, object1.getName());
+ assertEquals(5, object1.getIntValue());
+ }
+
+ public void testIntegerAttributeValueFromDouble()
+ {
+ final String objectName = "myName";
+
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(TestSingleton.NAME, objectName);
+ attributes.put(TestSingleton.INT_VALUE, 6.1);
+
+ TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
+ attributes);
+
+ assertEquals(objectName, object1.getName());
+ assertEquals(6, object1.getIntValue());
+ }
+
+ public void testStringAttributeValueFromContextVariableProvidedBySystemProperty()
+ {
+ String sysPropertyName = "testStringAttributeValueFromContextVariableProvidedBySystemProperty";
+ String contextToken = "${" + sysPropertyName + "}";
+
+ System.setProperty(sysPropertyName, "myValue");
+
+ final String objectName = "myName";
+
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(TestSingleton.NAME, objectName);
+ attributes.put(TestSingleton.STRING_VALUE, contextToken);
+
+ TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
+ attributes);
+
+ assertEquals(objectName, object1.getName());
+ assertEquals("myValue", object1.getStringValue());
+
+ // System property set empty string
+
+ System.setProperty(sysPropertyName, "");
+ TestSingleton object2 = _model.getObjectFactory().create(TestSingleton.class,
+ attributes);
+
+ assertEquals("", object2.getStringValue());
+
+ // System property not set
+ System.clearProperty(sysPropertyName);
+
+ TestSingleton object3 = _model.getObjectFactory().create(TestSingleton.class,
+ attributes);
+
+ // yields the unexpanded token - not sure if this is really useful behaviour?
+ assertEquals(contextToken, object3.getStringValue());
+ }
+
+ public void testMapAttributeValueFromContextVariableProvidedBySystemProperty()
+ {
+ String sysPropertyName = "testMapAttributeValueFromContextVariableProvidedBySystemProperty";
+ String contextToken = "${" + sysPropertyName + "}";
+
+ Map<String,String> expectedMap = new HashMap<>();
+ expectedMap.put("field1", "value1");
+ expectedMap.put("field2", "value2");
+
+ System.setProperty(sysPropertyName, "{ \"field1\" : \"value1\", \"field2\" : \"value2\"}");
+
+ final String objectName = "myName";
+
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(TestSingleton.NAME, objectName);
+ attributes.put(TestSingleton.MAP_VALUE, contextToken);
+
+ TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
+ attributes);
+
+ assertEquals(objectName, object1.getName());
+ assertEquals(expectedMap, object1.getMapValue());
+
+ // System property not set
+ System.clearProperty(sysPropertyName);
+ }
+
+ public void testStringAttributeValueFromContextVariableProvidedObjectsContext()
+ {
+ String contextToken = "${myReplacement}";
+
+ final String objectName = "myName";
+
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(ConfiguredObject.NAME, objectName);
+ attributes.put(ConfiguredObject.CONTEXT, Collections.singletonMap("myReplacement", "myValue"));
+ attributes.put(TestSingleton.STRING_VALUE, contextToken);
+
+ TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
+ attributes);
+ // Check the object's context itself
+ assertTrue(object1.getContext().containsKey("myReplacement"));
+ assertEquals("myValue", object1.getContext().get("myReplacement"));
+
+ assertEquals(objectName, object1.getName());
+ assertEquals("myValue", object1.getStringValue());
+ }
+
+ public void testInvalidIntegerAttributeValueFromContextVariable()
+ {
+ final Map<String, Object> attributes = new HashMap<>();
+
+ attributes.put(TestSingleton.NAME, "myName");
+ attributes.put(TestSingleton.TYPE, TestSingletonImpl.TEST_SINGLETON_TYPE);
+ attributes.put(TestSingleton.CONTEXT, Collections.singletonMap("contextVal", "notAnInteger"));
+ attributes.put(TestSingleton.INT_VALUE, "${contextVal}");
+
+ try
+ {
+ _model.getObjectFactory().create(TestSingleton.class, attributes);
+ fail("creation of child object should have failed due to invalid value");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // PASS
+ String message = e.getMessage();
+ assertTrue("Message does not contain the attribute name", message.contains("intValue"));
+ assertTrue("Message does not contain the non-interpolated value", message.contains("contextVal"));
+ assertTrue("Message does not contain the interpolated value", message.contains("contextVal"));
+
+ }
+ }
+
+ public void testCreateEnforcesAttributeValidValues() throws Exception
+ {
+ final String objectName = getName();
+ Map<String, Object> illegalCreateAttributes = new HashMap<>();
+ illegalCreateAttributes.put(ConfiguredObject.NAME, objectName);
+ illegalCreateAttributes.put(TestSingleton.VALID_VALUE, "illegal");
+
+ try
+ {
+ _model.getObjectFactory().create(TestSingleton.class, illegalCreateAttributes);
+ fail("Exception not thrown");
+ }
+ catch (IllegalConfigurationException ice)
+ {
+ // PASS
+ }
+
+ Map<String, Object> legalCreateAttributes = new HashMap<>();
+ legalCreateAttributes.put(ConfiguredObject.NAME, objectName);
+ legalCreateAttributes.put(TestSingleton.VALID_VALUE, TestSingleton.VALID_VALUE1);
+
+ TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, legalCreateAttributes);
+ assertEquals(TestSingleton.VALID_VALUE1, object.getValidValue());
+ }
+
+ public void testChangeEnforcesAttributeValidValues() throws Exception
+ {
+ final String objectName = getName();
+ Map<String, Object> legalCreateAttributes = new HashMap<>();
+ legalCreateAttributes.put(ConfiguredObject.NAME, objectName);
+ legalCreateAttributes.put(TestSingleton.VALID_VALUE, TestSingleton.VALID_VALUE1);
+
+ TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, legalCreateAttributes);
+ assertEquals(TestSingleton.VALID_VALUE1, object.getValidValue());
+
+ object.setAttributes(Collections.singletonMap(TestSingleton.VALID_VALUE, TestSingleton.VALID_VALUE2));
+ assertEquals(TestSingleton.VALID_VALUE2, object.getValidValue());
+
+ try
+ {
+ object.setAttributes(Collections.singletonMap(TestSingleton.VALID_VALUE, "illegal"));
+ fail("Exception not thrown");
+ }
+ catch (IllegalConfigurationException iae)
+ {
+ // PASS
+ }
+
+ assertEquals(TestSingleton.VALID_VALUE2, object.getValidValue());
+
+ object.setAttributes(Collections.singletonMap(TestSingleton.VALID_VALUE,null));
+ assertNull(object.getValidValue());
+
+ }
+
+ public void testCreateEnforcesAttributeValidValuesWithSets() throws Exception
+ {
+ final String objectName = getName();
+ final Map<String, Object> name = Collections.singletonMap(ConfiguredObject.NAME, (Object)objectName);
+
+ Map<String, Object> illegalCreateAttributes = new HashMap<>(name);
+ illegalCreateAttributes.put(TestSingleton.ENUMSET_VALUES, Collections.singleton(TestEnum.TEST_ENUM3));
+
+ try
+ {
+ _model.getObjectFactory().create(TestSingleton.class, illegalCreateAttributes);
+ fail("Exception not thrown");
+ }
+ catch (IllegalConfigurationException ice)
+ {
+ // PASS
+ }
+
+ {
+ Map<String, Object> legalCreateAttributesEnums = new HashMap<>(name);
+ legalCreateAttributesEnums.put(TestSingleton.ENUMSET_VALUES,
+ Arrays.asList(TestEnum.TEST_ENUM2, TestEnum.TEST_ENUM3));
+
+ TestSingleton obj = _model.getObjectFactory().create(TestSingleton.class, legalCreateAttributesEnums);
+ assertTrue(obj.getEnumSetValues().containsAll(Arrays.asList(TestEnum.TEST_ENUM2, TestEnum.TEST_ENUM3)));
+ }
+
+ {
+ Map<String, Object> legalCreateAttributesStrings = new HashMap<>(name);
+ legalCreateAttributesStrings.put(TestSingleton.ENUMSET_VALUES,
+ Arrays.asList(TestEnum.TEST_ENUM2.name(), TestEnum.TEST_ENUM3.name()));
+
+ TestSingleton
+ obj = _model.getObjectFactory().create(TestSingleton.class, legalCreateAttributesStrings);
+ assertTrue(obj.getEnumSetValues().containsAll(Arrays.asList(TestEnum.TEST_ENUM2, TestEnum.TEST_ENUM3)));
+ }
+ }
+
+ public void testDefaultContextIsInContextKeys()
+ {
+ final String objectName = "myName";
+
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(ConfiguredObject.NAME, objectName);
+
+ TestSingleton object = _model.getObjectFactory().create(TestSingleton.class,
+ attributes);
+
+
+ assertTrue("context default not in contextKeys",
+ object.getContextKeys(true).contains(TestSingleton.TEST_CONTEXT_DEFAULT));
+ assertEquals(object.getContextValue(String.class, TestSingleton.TEST_CONTEXT_DEFAULT), "default");
+
+ setTestSystemProperty(TestSingleton.TEST_CONTEXT_DEFAULT, "notdefault");
+ assertTrue("context default not in contextKeys",
+ object.getContextKeys(true).contains(TestSingleton.TEST_CONTEXT_DEFAULT));
+ assertEquals(object.getContextValue(String.class, TestSingleton.TEST_CONTEXT_DEFAULT), "notdefault");
+ }
+
+ public void testDerivedAttributeValue()
+ {
+ final String objectName = "myName";
+
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(ConfiguredObject.NAME, objectName);
+
+ TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
+ assertEquals(TestSingletonImpl.DERIVED_VALUE, object.getDerivedValue());
+
+ // Check that update is ignored
+ object.setAttribute(TestSingleton.DERIVED_VALUE, object.getDerivedValue(), System.currentTimeMillis());
+
+ assertEquals(TestSingletonImpl.DERIVED_VALUE, object.getDerivedValue());
+ }
+
+ public void testSecureValueRetrieval()
+ {
+ final String objectName = "myName";
+ final String secret = "secret";
+
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(ConfiguredObject.NAME, objectName);
+ attributes.put(TestSingleton.SECURE_VALUE, secret);
+
+ final TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
+
+ assertEquals(AbstractConfiguredObject.SECURED_STRING_VALUE, object.getAttribute(TestSingleton.SECURE_VALUE));
+ assertEquals(secret, object.getSecureValue());
+
+ //verify we can retrieve the actual secure value using system rights
+ Subject.doAs(org.apache.qpid.server.security.SecurityManager.getSubjectWithAddedSystemRights(),
+ new PrivilegedAction<Object>()
+ {
+ @Override
+ public Object run()
+ {
+ assertEquals(secret, object.getAttribute(TestSingleton.SECURE_VALUE));
+ assertEquals(secret, object.getSecureValue());
+ return null;
+ }
+ });
+
+
+ }
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestEnum.java
similarity index 87%
rename from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
rename to qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestEnum.java
index 75c6c19..d8ec160 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestEnum.java
@@ -17,13 +17,9 @@
* under the License.
*/
-package org.apache.qpid.server.model.testmodel;
+package org.apache.qpid.server.model.testmodels.singleton;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
public enum TestEnum
{
TEST_ENUM1,
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestModel.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestModel.java
similarity index 79%
rename from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestModel.java
rename to qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestModel.java
index ab9d753..330127c 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestModel.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestModel.java
@@ -1,5 +1,4 @@
/*
- *
* 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
@@ -16,9 +15,8 @@
* 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.testmodel;
+package org.apache.qpid.server.model.testmodels.singleton;
import java.util.Arrays;
import java.util.Collection;
@@ -36,8 +34,7 @@
private static final Model INSTANCE = new TestModel();
private Class<? extends ConfiguredObject>[] _supportedClasses =
new Class[] {
- TestRootCategory.class,
- TestChildCategory.class
+ TestSingleton.class
};
private final ConfiguredObjectFactory _objectFactory;
@@ -56,13 +53,13 @@
@Override
public Collection<Class<? extends ConfiguredObject>> getConfiguredObjectClasses()
{
- return Arrays.<Class<? extends ConfiguredObject>>asList(TestRootCategoryImpl.class, Test2RootCategoryImpl.class);
+ return Arrays.asList(_supportedClasses);
}
@Override
public String getType()
{
- return "test";
+ return "org.apache.qpid.server.model.testmodels.attribute";
}
};
_registry = new ConfiguredObjectTypeRegistry(Arrays.asList(configuredObjectRegistration), getSupportedCategories());
@@ -78,23 +75,19 @@
@Override
public Collection<Class<? extends ConfiguredObject>> getChildTypes(final Class<? extends ConfiguredObject> parent)
{
- return TestRootCategory.class.isAssignableFrom(parent)
- ? Collections.<Class<? extends ConfiguredObject>>singleton(TestChildCategory.class)
- : Collections.<Class<? extends ConfiguredObject>>emptySet();
+ return Collections.emptySet();
}
@Override
public Class<? extends ConfiguredObject> getRootCategory()
{
- return TestRootCategory.class;
+ return TestSingleton.class;
}
@Override
public Collection<Class<? extends ConfiguredObject>> getParentTypes(final Class<? extends ConfiguredObject> child)
{
- return TestChildCategory.class.isAssignableFrom(child)
- ? Collections.<Class<? extends ConfiguredObject>>singleton(TestRootCategory.class)
- : Collections.<Class<? extends ConfiguredObject>>emptySet();
+ return Collections.<Class<? extends ConfiguredObject>>emptySet();
}
@Override
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestRootCategory.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestSingleton.java
similarity index 80%
rename from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestRootCategory.java
rename to qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestSingleton.java
index cb47ee6..f19dc5e 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestRootCategory.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestSingleton.java
@@ -1,5 +1,4 @@
/*
- *
* 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
@@ -16,31 +15,31 @@
* 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.testmodel;
+package org.apache.qpid.server.model.testmodels.singleton;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.DerivedAttribute;
import org.apache.qpid.server.model.ManagedAttribute;
import org.apache.qpid.server.model.ManagedContextDefault;
import org.apache.qpid.server.model.ManagedObject;
-@ManagedObject( defaultType = "test" )
-public interface TestRootCategory<X extends TestRootCategory<X>> extends ConfiguredObject<X>
+@ManagedObject( defaultType = TestSingletonImpl.TEST_SINGLETON_TYPE)
+public interface TestSingleton<X extends TestSingleton<X>> extends ConfiguredObject<X>
{
String AUTOMATED_PERSISTED_VALUE = "automatedPersistedValue";
String AUTOMATED_NONPERSISTED_VALUE = "automatedNonPersistedValue";
+ String DERIVED_VALUE = "derivedValue";
String DEFAULTED_VALUE = "defaultedValue";
String STRING_VALUE = "stringValue";
String MAP_VALUE = "mapValue";
- String VALID_VALUE = "validValue";
String ENUM_VALUE = "enumValue";
+ String INT_VALUE = "intValue";
+ String VALID_VALUE = "validValue";
+ String SECURE_VALUE = "secureValue";
String ENUMSET_VALUES = "enumSetValues";
String TEST_CONTEXT_DEFAULT = "TEST_CONTEXT_DEFAULT";
@@ -48,7 +47,6 @@
@ManagedContextDefault(name = TEST_CONTEXT_DEFAULT)
String testGlobalDefault = "default";
-
@ManagedAttribute
String getAutomatedPersistedValue();
@@ -71,10 +69,19 @@
@ManagedAttribute
TestEnum getEnumValue();
+ @ManagedAttribute
+ int getIntValue();
+
@ManagedAttribute(validValues = {VALID_VALUE1, VALID_VALUE2} )
String getValidValue();
@ManagedAttribute( validValues = {"[\"TEST_ENUM1\"]", "[\"TEST_ENUM2\", \"TEST_ENUM3\"]"})
Set<TestEnum> getEnumSetValues();
+ @DerivedAttribute
+ long getDerivedValue();
+
+ @ManagedAttribute(secure = true)
+ String getSecureValue();
+
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/Test2RootCategoryImpl.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestSingletonImpl.java
similarity index 76%
rename from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/Test2RootCategoryImpl.java
rename to qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestSingletonImpl.java
index 238863e..c4dc0fa 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/Test2RootCategoryImpl.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestSingletonImpl.java
@@ -1,5 +1,4 @@
/*
- *
* 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
@@ -16,12 +15,9 @@
* 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.testmodel;
+package org.apache.qpid.server.model.testmodels.singleton;
-import java.util.Collection;
-import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -32,10 +28,14 @@
import org.apache.qpid.server.model.ManagedObject;
import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
-@ManagedObject( category = false , type = "test2" )
-public class Test2RootCategoryImpl extends AbstractConfiguredObject<Test2RootCategoryImpl>
- implements Test2RootCategory<Test2RootCategoryImpl>
+@ManagedObject( category = false, type = TestSingletonImpl.TEST_SINGLETON_TYPE)
+public class TestSingletonImpl extends AbstractConfiguredObject<TestSingletonImpl>
+ implements TestSingleton<TestSingletonImpl>
{
+ public static final String TEST_SINGLETON_TYPE = "testsingleton";
+
+ public static final int DERIVED_VALUE = -100;
+
@ManagedAttributeField
private String _automatedPersistedValue;
@@ -49,6 +49,9 @@
private String _stringValue;
@ManagedAttributeField
+ private int _intValue;
+
+ @ManagedAttributeField
private Map<String,String> _mapValue;
@ManagedAttributeField
@@ -60,8 +63,12 @@
@ManagedAttributeField
private Set<TestEnum> _enumSetValues;
+ @ManagedAttributeField
+ private String _secureValue;
+
+
@ManagedObjectFactoryConstructor
- public Test2RootCategoryImpl(final Map<String, Object> attributes)
+ public TestSingletonImpl(final Map<String, Object> attributes)
{
super(parentsMap(), attributes, newTaskExecutor(), TestModel.getInstance());
}
@@ -73,12 +80,13 @@
return currentThreadTaskExecutor;
}
- public Test2RootCategoryImpl(final Map<String, Object> attributes,
- final TaskExecutor taskExecutor)
+ public TestSingletonImpl(final Map<String, Object> attributes,
+ final TaskExecutor taskExecutor)
{
super(parentsMap(), attributes, taskExecutor);
}
+
@Override
public String getAutomatedPersistedValue()
{
@@ -98,18 +106,6 @@
}
@Override
- public String getValidValue()
- {
- return _validValue;
- }
-
- @Override
- public int getDerivedAttribute()
- {
- return 0;
- }
-
- @Override
public String getStringValue()
{
return _stringValue;
@@ -133,8 +129,27 @@
return _enumSetValues;
}
- public static Collection<String> functionGeneratedValidValues()
+ @Override
+ public String getValidValue()
{
- return Collections.singleton("generated");
+ return _validValue;
+ }
+
+ @Override
+ public int getIntValue()
+ {
+ return _intValue;
+ }
+
+ @Override
+ public long getDerivedValue()
+ {
+ return DERIVED_VALUE;
+ }
+
+ @Override
+ public String getSecureValue()
+ {
+ return _secureValue;
}
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/FileKeyStoreTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/FileKeyStoreTest.java
new file mode 100644
index 0000000..0e45582
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/FileKeyStoreTest.java
@@ -0,0 +1,328 @@
+/*
+ * 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.security;
+
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.net.ssl.KeyManager;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObjectFactory;
+import org.apache.qpid.server.model.IntegrityViolationException;
+import org.apache.qpid.server.model.KeyStore;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.TestSSLConstants;
+import org.apache.qpid.util.DataUrlUtils;
+import org.apache.qpid.util.FileUtils;
+
+public class FileKeyStoreTest extends QpidTestCase
+{
+ private final Broker<?> _broker = mock(Broker.class);
+ private final TaskExecutor _taskExecutor = CurrentThreadTaskExecutor.newStartedInstance();
+ private final SecurityManager _securityManager = mock(SecurityManager.class);
+ private final Model _model = BrokerModel.getInstance();
+ private final ConfiguredObjectFactory _factory = _model.getObjectFactory();
+
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+
+ when(_broker.getTaskExecutor()).thenReturn(_taskExecutor);
+ when(_broker.getModel()).thenReturn(_model);
+ when(_broker.getSecurityManager()).thenReturn(_securityManager);
+ }
+
+ public void testCreateKeyStoreFromFile_Success() throws Exception
+ {
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileKeyStore.NAME, "myFileKeyStore");
+ attributes.put(FileKeyStore.PATH, TestSSLConstants.BROKER_KEYSTORE);
+ attributes.put(FileKeyStore.PASSWORD, TestSSLConstants.BROKER_KEYSTORE_PASSWORD);
+
+ FileKeyStoreImpl fileKeyStore = (FileKeyStoreImpl) _factory.create(KeyStore.class, attributes, _broker);
+
+ KeyManager[] keyManager = fileKeyStore.getKeyManagers();
+ assertNotNull(keyManager);
+ assertEquals("Unexpected number of key managers", 1, keyManager.length);
+ assertNotNull("Key manager unexpected null", keyManager[0]);
+ }
+
+ public void testCreateKeyStoreWithAliasFromFile_Success() throws Exception
+ {
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileKeyStore.NAME, "myFileKeyStore");
+ attributes.put(FileKeyStore.PATH, TestSSLConstants.BROKER_KEYSTORE);
+ attributes.put(FileKeyStore.PASSWORD, TestSSLConstants.BROKER_KEYSTORE_PASSWORD);
+ attributes.put(FileKeyStore.CERTIFICATE_ALIAS, TestSSLConstants.BROKER_KEYSTORE_ALIAS);
+
+ FileKeyStoreImpl fileKeyStore = (FileKeyStoreImpl) _factory.create(KeyStore.class, attributes, _broker);
+
+ KeyManager[] keyManager = fileKeyStore.getKeyManagers();
+ assertNotNull(keyManager);
+ assertEquals("Unexpected number of key managers", 1, keyManager.length);
+ assertNotNull("Key manager unexpected null", keyManager[0]);
+ }
+
+ public void testCreateKeyStoreFromFile_WrongPassword() throws Exception
+ {
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileKeyStore.NAME, "myFileKeyStore");
+ attributes.put(FileKeyStore.PATH, TestSSLConstants.BROKER_KEYSTORE);
+ attributes.put(FileKeyStore.PASSWORD, "wrong");
+
+ try
+ {
+ _factory.create(KeyStore.class, attributes, _broker);
+ fail("Exception not thrown");
+ }
+ catch (IllegalConfigurationException ice)
+ {
+ String message = ice.getMessage();
+ assertTrue("Exception text not as unexpected:" + message, message.contains("Check key store password"));
+ }
+ }
+
+ public void testCreateKeyStoreFromFile_UnknownAlias() throws Exception
+ {
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileKeyStore.NAME, "myFileKeyStore");
+ attributes.put(FileKeyStore.PATH, TestSSLConstants.KEYSTORE);
+ attributes.put(FileKeyStore.PASSWORD, TestSSLConstants.KEYSTORE_PASSWORD);
+ attributes.put(FileKeyStore.CERTIFICATE_ALIAS, "notknown");
+
+ try
+ {
+ _factory.create(KeyStore.class, attributes, _broker);
+ fail("Exception not thrown");
+ }
+ catch (IllegalConfigurationException ice)
+ {
+ String message = ice.getMessage();
+ assertTrue("Exception text not as unexpected:" + message, message.contains("Cannot find a certificate with alias 'notknown' in key store"));
+ }
+ }
+
+ public void testCreateKeyStoreFromDataUrl_Success() throws Exception
+ {
+ String trustStoreAsDataUrl = createDataUrlForFile(TestSSLConstants.BROKER_KEYSTORE);
+
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileKeyStore.NAME, "myFileKeyStore");
+ attributes.put(FileKeyStore.PATH, trustStoreAsDataUrl);
+ attributes.put(FileKeyStore.PASSWORD, TestSSLConstants.BROKER_KEYSTORE_PASSWORD);
+
+ FileKeyStoreImpl fileKeyStore = (FileKeyStoreImpl) _factory.create(KeyStore.class, attributes, _broker);
+
+ KeyManager[] keyManagers = fileKeyStore.getKeyManagers();
+ assertNotNull(keyManagers);
+ assertEquals("Unexpected number of key managers", 1, keyManagers.length);
+ assertNotNull("Key manager unexpected null", keyManagers[0]);
+ }
+
+ public void testCreateKeyStoreWithAliasFromDataUrl_Success() throws Exception
+ {
+ String trustStoreAsDataUrl = createDataUrlForFile(TestSSLConstants.BROKER_KEYSTORE);
+
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileKeyStore.NAME, "myFileKeyStore");
+ attributes.put(FileKeyStore.PATH, trustStoreAsDataUrl);
+ attributes.put(FileKeyStore.PASSWORD, TestSSLConstants.BROKER_KEYSTORE_PASSWORD);
+ attributes.put(FileKeyStore.CERTIFICATE_ALIAS, TestSSLConstants.BROKER_KEYSTORE_ALIAS);
+
+ FileKeyStoreImpl fileKeyStore = (FileKeyStoreImpl) _factory.create(KeyStore.class, attributes, _broker);
+
+ KeyManager[] keyManagers = fileKeyStore.getKeyManagers();
+ assertNotNull(keyManagers);
+ assertEquals("Unexpected number of key managers", 1, keyManagers.length);
+ assertNotNull("Key manager unexpected null", keyManagers[0]);
+ }
+
+ public void testCreateKeyStoreFromDataUrl_WrongPassword() throws Exception
+ {
+ String keyStoreAsDataUrl = createDataUrlForFile(TestSSLConstants.BROKER_KEYSTORE);
+
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileKeyStore.NAME, "myFileKeyStore");
+ attributes.put(FileKeyStore.PASSWORD, "wrong");
+ attributes.put(FileKeyStore.PATH, keyStoreAsDataUrl);
+
+ try
+ {
+ _factory.create(KeyStore.class, attributes, _broker);
+ fail("Exception not thrown");
+ }
+ catch (IllegalConfigurationException ice)
+ {
+ String message = ice.getMessage();
+ assertTrue("Exception text not as unexpected:" + message, message.contains("Check key store password"));
+ }
+ }
+
+ public void testCreateKeyStoreFromDataUrl_BadKeystoreBytes() throws Exception
+ {
+ String keyStoreAsDataUrl = DataUrlUtils.getDataUrlForBytes("notatruststore".getBytes());
+
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileKeyStore.NAME, "myFileKeyStore");
+ attributes.put(FileKeyStore.PASSWORD, TestSSLConstants.BROKER_KEYSTORE_PASSWORD);
+ attributes.put(FileKeyStore.PATH, keyStoreAsDataUrl);
+
+ try
+ {
+ _factory.create(KeyStore.class, attributes, _broker);
+ fail("Exception not thrown");
+ }
+ catch (IllegalConfigurationException ice)
+ {
+ String message = ice.getMessage();
+ assertTrue("Exception text not as unexpected:" + message, message.contains("Cannot instantiate key store"));
+
+ }
+ }
+
+ public void testCreateKeyStoreFromDataUrl_UnknownAlias() throws Exception
+ {
+ String keyStoreAsDataUrl = createDataUrlForFile(TestSSLConstants.BROKER_KEYSTORE);
+
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileKeyStore.NAME, "myFileKeyStore");
+ attributes.put(FileKeyStore.PASSWORD, TestSSLConstants.BROKER_KEYSTORE_PASSWORD);
+ attributes.put(FileKeyStore.PATH, keyStoreAsDataUrl);
+ attributes.put(FileKeyStore.CERTIFICATE_ALIAS, "notknown");
+
+ try
+ {
+ _factory.create(KeyStore.class, attributes, _broker);
+ fail("Exception not thrown");
+ }
+ catch (IllegalConfigurationException ice)
+ {
+ String message = ice.getMessage();
+ assertTrue("Exception text not as unexpected:" + message, message.contains("Cannot find a certificate with alias 'notknown' in key store"));
+ }
+ }
+
+ public void testUpdateKeyStore_Success() throws Exception
+ {
+
+ when(_securityManager.authoriseConfiguringBroker(any(String.class), (Class<? extends ConfiguredObject>)any(), any(Operation.class))).thenReturn(true);
+
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileKeyStore.NAME, "myFileKeyStore");
+ attributes.put(FileKeyStore.PATH, TestSSLConstants.BROKER_KEYSTORE);
+ attributes.put(FileKeyStore.PASSWORD, TestSSLConstants.BROKER_KEYSTORE_PASSWORD);
+
+ FileKeyStoreImpl fileKeyStore = (FileKeyStoreImpl) _factory.create(KeyStore.class, attributes, _broker);
+
+ assertNull("Unexpected alias value before change", fileKeyStore.getCertificateAlias());
+
+ try
+ {
+ Map<String,Object> unacceptableAttributes = new HashMap<>();
+ unacceptableAttributes.put(FileKeyStore.CERTIFICATE_ALIAS, "notknown");
+
+ fileKeyStore.setAttributes(unacceptableAttributes);
+ fail("Exception not thrown");
+ }
+ catch (IllegalConfigurationException ice)
+ {
+ String message = ice.getMessage();
+ assertTrue("Exception text not as unexpected:" + message, message.contains("Cannot find a certificate with alias 'notknown' in key store"));
+ }
+
+ assertNull("Unexpected alias value after failed change", fileKeyStore.getCertificateAlias());
+
+ Map<String,Object> changedAttributes = new HashMap<>();
+ changedAttributes.put(FileKeyStore.CERTIFICATE_ALIAS, TestSSLConstants.BROKER_KEYSTORE_ALIAS);
+
+ fileKeyStore.setAttributes(changedAttributes);
+
+ assertEquals("Unexpected alias value after change that is expected to be successful",
+ TestSSLConstants.BROKER_KEYSTORE_ALIAS,
+ fileKeyStore.getCertificateAlias());
+
+ }
+
+ public void testDeleteKeyStore_Success() throws Exception
+ {
+
+ when(_securityManager.authoriseConfiguringBroker(any(String.class), (Class<? extends ConfiguredObject>)any(), any(Operation.class))).thenReturn(true);
+
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileKeyStore.NAME, "myFileKeyStore");
+ attributes.put(FileKeyStore.PATH, TestSSLConstants.BROKER_KEYSTORE);
+ attributes.put(FileKeyStore.PASSWORD, TestSSLConstants.BROKER_KEYSTORE_PASSWORD);
+
+ FileKeyStoreImpl fileKeyStore = (FileKeyStoreImpl) _factory.create(KeyStore.class, attributes, _broker);
+
+ fileKeyStore.delete();
+ }
+
+ public void testDeleteKeyStore_KeyManagerInUseByPort() throws Exception
+ {
+ when(_securityManager.authoriseConfiguringBroker(any(String.class),
+ any(Class.class),
+ any(Operation.class))).thenReturn(true);
+
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileKeyStore.NAME, "myFileKeyStore");
+ attributes.put(FileKeyStore.PATH, TestSSLConstants.BROKER_KEYSTORE);
+ attributes.put(FileKeyStore.PASSWORD, TestSSLConstants.BROKER_KEYSTORE_PASSWORD);
+
+ FileKeyStoreImpl fileKeyStore = (FileKeyStoreImpl) _factory.create(KeyStore.class, attributes, _broker);
+
+ Port<?> port = mock(Port.class);
+ when(port.getKeyStore()).thenReturn(fileKeyStore);
+
+ when(_broker.getPorts()).thenReturn(Collections.<Port<?>>singletonList(port));
+
+ try
+ {
+ fileKeyStore.delete();
+ fail("Exception not thrown");
+ }
+ catch (IntegrityViolationException ive)
+ {
+ // PASS
+ }
+ }
+
+ private static String createDataUrlForFile(String filename)
+ {
+ byte[] fileAsBytes = FileUtils.readFileAsBytes(filename);
+ return DataUrlUtils.getDataUrlForBytes(fileAsBytes);
+ }
+}
\ No newline at end of file
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/FileTrustStoreTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/FileTrustStoreTest.java
new file mode 100644
index 0000000..d965549
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/FileTrustStoreTest.java
@@ -0,0 +1,311 @@
+/*
+ * 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.security;
+
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.net.ssl.TrustManager;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObjectFactory;
+import org.apache.qpid.server.model.IntegrityViolationException;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.TrustStore;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.auth.manager.SimpleLDAPAuthenticationManager;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.TestSSLConstants;
+import org.apache.qpid.transport.network.security.ssl.QpidMultipleTrustManager;
+import org.apache.qpid.util.DataUrlUtils;
+import org.apache.qpid.util.FileUtils;
+
+public class FileTrustStoreTest extends QpidTestCase
+{
+ private final Broker<?> _broker = mock(Broker.class);
+ private final TaskExecutor _taskExecutor = CurrentThreadTaskExecutor.newStartedInstance();
+ private final SecurityManager _securityManager = mock(SecurityManager.class);
+ private final Model _model = BrokerModel.getInstance();
+ private final ConfiguredObjectFactory _factory = _model.getObjectFactory();
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+
+ when(_broker.getTaskExecutor()).thenReturn(_taskExecutor);
+ when(_broker.getModel()).thenReturn(_model);
+ when(_broker.getSecurityManager()).thenReturn(_securityManager);
+
+ }
+
+ public void testCreateTrustStoreFromFile_Success() throws Exception
+ {
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileTrustStore.NAME, "myFileTrustStore");
+ attributes.put(FileTrustStore.PATH, TestSSLConstants.TRUSTSTORE);
+ attributes.put(FileTrustStore.PASSWORD, TestSSLConstants.TRUSTSTORE_PASSWORD);
+
+ FileTrustStoreImpl fileTrustStore =
+ (FileTrustStoreImpl) _factory.create(TrustStore.class, attributes, _broker);
+
+ TrustManager[] trustManagers = fileTrustStore.getTrustManagers();
+ assertNotNull(trustManagers);
+ assertEquals("Unexpected number of trust managers", 1, trustManagers.length);
+ assertNotNull("Trust manager unexpected null", trustManagers[0]);
+ }
+
+ public void testCreateTrustStoreFromFile_WrongPassword() throws Exception
+ {
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileTrustStore.NAME, "myFileTrustStore");
+ attributes.put(FileTrustStore.PATH, TestSSLConstants.TRUSTSTORE);
+ attributes.put(FileTrustStore.PASSWORD, "wrong");
+
+ try
+ {
+ _factory.create(TrustStore.class, attributes, _broker);
+ fail("Exception not thrown");
+ }
+ catch (IllegalConfigurationException ice)
+ {
+ String message = ice.getMessage();
+ assertTrue("Exception text not as unexpected:" + message, message.contains("Check trust store password"));
+ }
+ }
+
+ public void testCreatePeersOnlyTrustStoreFromFile_Success() throws Exception
+ {
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileTrustStore.NAME, "myFileTrustStore");
+ attributes.put(FileTrustStore.PATH, TestSSLConstants.BROKER_PEERSTORE);
+ attributes.put(FileTrustStore.PASSWORD, TestSSLConstants.BROKER_PEERSTORE_PASSWORD);
+ attributes.put(FileTrustStore.PEERS_ONLY, true);
+
+ FileTrustStoreImpl fileTrustStore =
+ (FileTrustStoreImpl) _factory.create(TrustStore.class, attributes, _broker);
+
+ TrustManager[] trustManagers = fileTrustStore.getTrustManagers();
+ assertNotNull(trustManagers);
+ assertEquals("Unexpected number of trust managers", 1, trustManagers.length);
+ assertNotNull("Trust manager unexpected null", trustManagers[0]);
+ assertTrue("Trust manager unexpected null", trustManagers[0] instanceof QpidMultipleTrustManager);
+ }
+
+
+ public void testCreateTrustStoreFromDataUrl_Success() throws Exception
+ {
+ String trustStoreAsDataUrl = createDataUrlForFile(TestSSLConstants.TRUSTSTORE);
+
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileTrustStore.NAME, "myFileTrustStore");
+ attributes.put(FileTrustStore.PATH, trustStoreAsDataUrl);
+ attributes.put(FileTrustStore.PASSWORD, TestSSLConstants.TRUSTSTORE_PASSWORD);
+
+ FileTrustStoreImpl fileTrustStore =
+ (FileTrustStoreImpl) _factory.create(TrustStore.class, attributes, _broker);
+
+ TrustManager[] trustManagers = fileTrustStore.getTrustManagers();
+ assertNotNull(trustManagers);
+ assertEquals("Unexpected number of trust managers", 1, trustManagers.length);
+ assertNotNull("Trust manager unexpected null", trustManagers[0]);
+ }
+
+ public void testCreateTrustStoreFromDataUrl_WrongPassword() throws Exception
+ {
+ String trustStoreAsDataUrl = createDataUrlForFile(TestSSLConstants.TRUSTSTORE);
+
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileTrustStore.NAME, "myFileTrustStore");
+ attributes.put(FileTrustStore.PASSWORD, "wrong");
+ attributes.put(FileTrustStore.PATH, trustStoreAsDataUrl);
+
+ try
+ {
+ _factory.create(TrustStore.class, attributes, _broker);
+ fail("Exception not thrown");
+ }
+ catch (IllegalConfigurationException ice)
+ {
+ String message = ice.getMessage();
+ assertTrue("Exception text not as unexpected:" + message, message.contains("Check trust store password"));
+ }
+ }
+
+ public void testCreateTrustStoreFromDataUrl_BadTruststoreBytes() throws Exception
+ {
+ String trustStoreAsDataUrl = DataUrlUtils.getDataUrlForBytes("notatruststore".getBytes());
+
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileTrustStore.NAME, "myFileTrustStore");
+ attributes.put(FileTrustStore.PASSWORD, TestSSLConstants.TRUSTSTORE_PASSWORD);
+ attributes.put(FileTrustStore.PATH, trustStoreAsDataUrl);
+
+ try
+ {
+ _factory.create(TrustStore.class, attributes, _broker);
+ fail("Exception not thrown");
+ }
+ catch (IllegalConfigurationException ice)
+ {
+ String message = ice.getMessage();
+ assertTrue("Exception text not as unexpected:" + message, message.contains("Cannot instantiate trust store"));
+
+ }
+ }
+
+ public void testUpdateTrustStore_Success() throws Exception
+ {
+
+ when(_securityManager.authoriseConfiguringBroker(any(String.class), (Class<? extends ConfiguredObject>)any(), any(Operation.class))).thenReturn(true);
+
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileTrustStore.NAME, "myFileTrustStore");
+ attributes.put(FileTrustStore.PATH, TestSSLConstants.TRUSTSTORE);
+ attributes.put(FileTrustStore.PASSWORD, TestSSLConstants.TRUSTSTORE_PASSWORD);
+
+ FileTrustStoreImpl fileTrustStore =
+ (FileTrustStoreImpl) _factory.create(TrustStore.class, attributes, _broker);
+
+ assertEquals("Unexpected path value before change", TestSSLConstants.TRUSTSTORE, fileTrustStore.getPath());
+
+ try
+ {
+ Map<String,Object> unacceptableAttributes = new HashMap<>();
+ unacceptableAttributes.put(FileTrustStore.PATH, "/not/a/truststore");
+
+ fileTrustStore.setAttributes(unacceptableAttributes);
+ fail("Exception not thrown");
+ }
+ catch (IllegalConfigurationException ice)
+ {
+ String message = ice.getMessage();
+ assertTrue("Exception text not as unexpected:" + message, message.contains("Cannot instantiate trust store"));
+ }
+
+ assertEquals("Unexpected path value after failed change", TestSSLConstants.TRUSTSTORE, fileTrustStore.getPath());
+
+ Map<String,Object> changedAttributes = new HashMap<>();
+ changedAttributes.put(FileTrustStore.PATH, TestSSLConstants.BROKER_TRUSTSTORE);
+ changedAttributes.put(FileTrustStore.PASSWORD, TestSSLConstants.BROKER_TRUSTSTORE_PASSWORD);
+
+ fileTrustStore.setAttributes(changedAttributes);
+
+ assertEquals("Unexpected path value after change that is expected to be successful",
+ TestSSLConstants.BROKER_TRUSTSTORE,
+ fileTrustStore.getPath());
+ }
+
+ public void testDeleteTrustStore_Success() throws Exception
+ {
+
+ when(_securityManager.authoriseConfiguringBroker(any(String.class), (Class<? extends ConfiguredObject>)any(), any(Operation.class))).thenReturn(true);
+
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileTrustStore.NAME, "myFileTrustStore");
+ attributes.put(FileTrustStore.PATH, TestSSLConstants.TRUSTSTORE);
+ attributes.put(FileTrustStore.PASSWORD, TestSSLConstants.TRUSTSTORE_PASSWORD);
+
+ FileTrustStoreImpl fileTrustStore =
+ (FileTrustStoreImpl) _factory.create(TrustStore.class, attributes, _broker);
+
+ fileTrustStore.delete();
+ }
+
+ public void testDeleteTrustStore_TrustManagerInUseByAuthProvider() throws Exception
+ {
+ when(_securityManager.authoriseConfiguringBroker(any(String.class),
+ any(Class.class),
+ any(Operation.class))).thenReturn(true);
+
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileTrustStore.NAME, "myFileTrustStore");
+ attributes.put(FileTrustStore.PATH, TestSSLConstants.TRUSTSTORE);
+ attributes.put(FileTrustStore.PASSWORD, TestSSLConstants.TRUSTSTORE_PASSWORD);
+
+ FileTrustStoreImpl fileTrustStore =
+ (FileTrustStoreImpl) _factory.create(TrustStore.class, attributes, _broker);
+
+ SimpleLDAPAuthenticationManager ldap = mock(SimpleLDAPAuthenticationManager.class);
+ when(ldap.getTrustStore()).thenReturn(fileTrustStore);
+
+ Collection<AuthenticationProvider<?>> authenticationProviders = Collections.<AuthenticationProvider<?>>singletonList(ldap);
+ when(_broker.getAuthenticationProviders()).thenReturn(authenticationProviders);
+
+ try
+ {
+ fileTrustStore.delete();
+ fail("Exception not thrown");
+ }
+ catch (IntegrityViolationException ive)
+ {
+ // PASS
+ }
+ }
+
+ public void testDeleteTrustStore_TrustManagerInUseByPort() throws Exception
+ {
+ when(_securityManager.authoriseConfiguringBroker(any(String.class),
+ any(Class.class),
+ any(Operation.class))).thenReturn(true);
+
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(FileTrustStore.NAME, "myFileTrustStore");
+ attributes.put(FileTrustStore.PATH, TestSSLConstants.TRUSTSTORE);
+ attributes.put(FileTrustStore.PASSWORD, TestSSLConstants.TRUSTSTORE_PASSWORD);
+
+ FileTrustStoreImpl fileTrustStore =
+ (FileTrustStoreImpl) _factory.create(TrustStore.class, attributes, _broker);
+
+ Port<?> port = mock(Port.class);
+ when(port.getTrustStores()).thenReturn(Collections.<TrustStore>singletonList(fileTrustStore));
+
+ when(_broker.getPorts()).thenReturn(Collections.<Port<?>>singletonList(port));
+
+ try
+ {
+ fileTrustStore.delete();
+ fail("Exception not thrown");
+ }
+ catch (IntegrityViolationException ive)
+ {
+ // PASS
+ }
+ }
+
+ private static String createDataUrlForFile(String filename)
+ {
+ byte[] fileAsBytes = FileUtils.readFileAsBytes(filename);
+ return DataUrlUtils.getDataUrlForBytes(fileAsBytes);
+ }
+}
\ No newline at end of file
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java
index 15d4cba..54bd691 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java
@@ -30,6 +30,7 @@
import static org.mockito.Mockito.when;
import java.security.AccessControlException;
+import java.util.Collections;
import org.apache.qpid.server.binding.BindingImpl;
import org.apache.qpid.server.consumer.ConsumerImpl;
@@ -68,11 +69,13 @@
AccessControlProvider<?> aclProvider = mock(AccessControlProvider.class);
when(aclProvider.getAccessControl()).thenReturn(_accessControl);
+ when(aclProvider.getState()).thenReturn(State.ACTIVE);
when(_virtualHost.getName()).thenReturn(TEST_VIRTUAL_HOST);
- _securityManager = new SecurityManager(mock(Broker.class), false);
- _securityManager.stateChanged(aclProvider, State.UNINITIALIZED, State.ACTIVE);
+ Broker broker = mock(Broker.class);
+ when(broker.getAccessControlProviders()).thenReturn(Collections.singleton(aclProvider));
+ _securityManager = new SecurityManager(broker, false);
}
public void testAuthoriseCreateBinding()
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java
index f480248..0713988 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java
@@ -69,7 +69,7 @@
_brokerShutdownProvider = mock(BrokerShutdownProvider.class);
_systemConfig = new JsonSystemConfigImpl(_taskExecutor,
mock(EventLogger.class), mock(LogRecorder.class),
- new BrokerOptions(),
+ new BrokerOptions().convertToSystemConfigAttributes(),
_brokerShutdownProvider);
when(_brokerEntry.getId()).thenReturn(_brokerId);
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java
index 830fa46..274ff1b 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java
@@ -81,7 +81,7 @@
_systemConfig = new JsonSystemConfigImpl(_taskExecutor,
mock(EventLogger.class),
mock(LogRecorder.class),
- new BrokerOptions(),
+ new BrokerOptions().convertToSystemConfigAttributes(),
mock(BrokerShutdownProvider.class));
}
diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AbstractConfiguration.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AbstractConfiguration.java
deleted file mode 100644
index e15361a..0000000
--- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AbstractConfiguration.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *
- * 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.security.access.config;
-
-import org.apache.qpid.server.logging.EventLogger;
-import org.apache.qpid.server.logging.EventLoggerProvider;
-
-import java.io.File;
-
-public abstract class AbstractConfiguration implements ConfigurationFile
-{
- private File _file;
- private RuleSet _config;
- private final EventLoggerProvider _eventLogger;
-
- public AbstractConfiguration(File file, final EventLoggerProvider eventLogger)
- {
- _file = file;
- _eventLogger = eventLogger;
- }
-
- public File getFile()
- {
- return _file;
- }
-
- public RuleSet load()
- {
- _config = new RuleSet(_eventLogger);
- return _config;
- }
-
- public RuleSet getConfiguration()
- {
- return _config;
- }
-
- public boolean save(RuleSet configuration)
- {
- return true;
- }
-
- public RuleSet reload()
- {
- RuleSet oldRules = _config;
-
- try
- {
- RuleSet newRules = load();
- _config = newRules;
- }
- catch (Exception e)
- {
- _config = oldRules;
- }
-
- return _config;
- }
-}
diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ConfigurationFile.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ConfigurationFile.java
index 966c32e..3405b6c 100644
--- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ConfigurationFile.java
+++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ConfigurationFile.java
@@ -20,35 +20,20 @@
*/
package org.apache.qpid.server.security.access.config;
-import java.io.File;
+import java.io.Reader;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
public interface ConfigurationFile
{
/**
- * Return the actual {@link File} object containing the configuration.
- */
- File getFile();
-
- /**
* Load this configuration file's contents into a {@link RuleSet}.
* @throws IllegalConfigurationException if the configuration file has errors.
* @throws IllegalArgumentException if individual tokens cannot be parsed.
+ * @param configReader
*/
- RuleSet load() throws IllegalConfigurationException;
-
- /**
- * Reload this configuration file's contents.
- * @throws IllegalConfigurationException if the configuration file has errors.
- * @throws IllegalArgumentException if individual tokens cannot be parsed.
- */
- RuleSet reload() throws IllegalConfigurationException;
-
+ RuleSet load(final Reader configReader) throws IllegalConfigurationException;
+
RuleSet getConfiguration();
-
- /**
- * TODO document me.
- */
- boolean save(RuleSet configuration);
+
}
diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java
index 8a5dae8..5ed28b6 100644
--- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java
+++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java
@@ -21,10 +21,9 @@
package org.apache.qpid.server.security.access.config;
import java.io.BufferedReader;
-import java.io.File;
import java.io.FileNotFoundException;
-import java.io.FileReader;
import java.io.IOException;
+import java.io.Reader;
import java.io.StreamTokenizer;
import java.util.HashMap;
import java.util.Iterator;
@@ -34,14 +33,14 @@
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
+
import org.apache.qpid.server.configuration.IllegalConfigurationException;
-import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.EventLoggerProvider;
import org.apache.qpid.server.security.access.ObjectType;
import org.apache.qpid.server.security.access.Operation;
import org.apache.qpid.server.security.access.Permission;
-public class PlainConfiguration extends AbstractConfiguration
+public class PlainConfiguration implements ConfigurationFile
{
private static final Logger _logger = Logger.getLogger(PlainConfiguration.class);
@@ -66,30 +65,30 @@
static final String PROPERTY_KEY_ONLY_MSG = "Incomplete property (key only) at line %d";
static final String PROPERTY_NO_EQUALS_MSG = "Incomplete property (no equals) at line %d";
static final String PROPERTY_NO_VALUE_MSG = "Incomplete property (no value) at line %d";
+ private final EventLoggerProvider _eventLogger;
+ private final String _name;
private StreamTokenizer _st;
+ private RuleSet _config;
- public PlainConfiguration(File file, final EventLoggerProvider eventLogger)
+ public PlainConfiguration(String name, final EventLoggerProvider eventLogger)
{
- super(file, eventLogger);
+ _eventLogger = eventLogger;
+ _name = name;
}
@Override
- public RuleSet load()
+ public RuleSet load(final Reader configReader)
{
- RuleSet ruleSet = super.load();
+ _config = new RuleSet(_eventLogger);
- File file = getFile();
- FileReader fileReader = null;
-
- try
+ try(Reader fileReader = configReader)
{
if(_logger.isDebugEnabled())
{
- _logger.debug("About to load ACL file " + file);
+ _logger.debug("About to load ACL file");
}
- fileReader = new FileReader(file);
_st = new StreamTokenizer(new BufferedReader(fileReader));
_st.resetSyntax(); // setup the tokenizer
@@ -209,29 +208,14 @@
}
catch (FileNotFoundException fnfe)
{
- throw new IllegalConfigurationException(String.format(CONFIG_NOT_FOUND_MSG, file.getName()), fnfe);
+ throw new IllegalConfigurationException(String.format(CONFIG_NOT_FOUND_MSG, _name), fnfe);
}
catch (IOException ioe)
{
- throw new IllegalConfigurationException(String.format(CANNOT_LOAD_MSG, file.getName()), ioe);
- }
- finally
- {
- if(fileReader != null)
- {
- try
- {
- fileReader.close();
- }
- catch (IOException e)
- {
- throw new IllegalConfigurationException(String.format(CANNOT_CLOSE_MSG, file.getName()), e);
- }
- }
+ throw new IllegalConfigurationException(String.format(CANNOT_LOAD_MSG, _name), ioe);
}
-
- return ruleSet;
+ return _config;
}
private void parseAcl(Integer number, List<String> args)
@@ -333,4 +317,10 @@
{
return _st.lineno() - 1;
}
+
+ public RuleSet getConfiguration()
+ {
+ return _config;
+ }
+
}
diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java
index 1adc656..00b4209 100644
--- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java
+++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java
@@ -39,6 +39,7 @@
import org.apache.qpid.server.model.StateTransition;
import org.apache.qpid.server.security.AccessControl;
import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.util.urlstreamhandler.data.Handler;
public class ACLFileAccessControlProviderImpl
extends AbstractConfiguredObject<ACLFileAccessControlProviderImpl>
@@ -46,10 +47,15 @@
{
private static final Logger LOGGER = Logger.getLogger(ACLFileAccessControlProviderImpl.class);
+ static
+ {
+ Handler.register();
+ }
+
protected DefaultAccessControl _accessControl;
protected final Broker _broker;
- @ManagedAttributeField
+ @ManagedAttributeField( afterSet = "reloadAclFile")
private String _path;
@ManagedObjectFactoryConstructor
@@ -112,6 +118,26 @@
_accessControl = new DefaultAccessControl(getPath(), _broker);
}
+ @SuppressWarnings("unused")
+ private void reloadAclFile()
+ {
+ try
+ {
+ DefaultAccessControl accessControl = new DefaultAccessControl(getPath(), _broker);
+ accessControl.open();
+ DefaultAccessControl oldAccessControl = _accessControl;
+ _accessControl = accessControl;
+ if(oldAccessControl != null)
+ {
+ oldAccessControl.close();
+ }
+ }
+ catch(RuntimeException e)
+ {
+ throw new IllegalConfigurationException(e.getMessage(), e);
+ }
+ }
+
@Override
public String getPath()
{
diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java
index c42dc88..2998252 100644
--- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java
+++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java
@@ -21,9 +21,14 @@
package org.apache.qpid.server.security.access.plugins;
import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
import java.net.SocketAddress;
+import java.net.URL;
import java.security.AccessController;
import java.util.Set;
@@ -47,46 +52,81 @@
public class DefaultAccessControl implements AccessControl
{
private static final Logger _logger = Logger.getLogger(DefaultAccessControl.class);
+ private final String _fileName;
private RuleSet _ruleSet;
- private File _aclFile;
private final EventLoggerProvider _eventLogger;
- public DefaultAccessControl(String fileName, final EventLoggerProvider eventLogger)
+ public DefaultAccessControl(String name, final EventLoggerProvider eventLogger)
{
+ _fileName = name;
_eventLogger = eventLogger;
if (_logger.isDebugEnabled())
{
- _logger.debug("Creating AccessControl instance using file: " + fileName);
+ _logger.debug("Creating AccessControl instance");
}
-
- _aclFile = new File(fileName);
}
DefaultAccessControl(RuleSet rs)
{
+ _fileName = null;
_ruleSet = rs;
_eventLogger = rs;
}
public void open()
{
- if(_aclFile != null)
+ if(_fileName != null)
{
- if (!validate())
- {
- throw new IllegalConfigurationException("ACL file '" + _aclFile + "' is not found");
- }
-
- ConfigurationFile configFile = new PlainConfiguration(_aclFile, _eventLogger);
- _ruleSet = configFile.load();
+ ConfigurationFile configFile = new PlainConfiguration(_fileName, _eventLogger);
+ _ruleSet = configFile.load(getReaderFromURLString(_fileName));
}
}
@Override
public boolean validate()
{
- return _aclFile.exists();
+ try
+ {
+ getReaderFromURLString(_fileName);
+ return true;
+ }
+ catch(IllegalConfigurationException e)
+ {
+ return false;
+ }
+ }
+
+
+ private static Reader getReaderFromURLString(String urlString)
+ {
+ try
+ {
+ URL url;
+
+ try
+ {
+ url = new URL(urlString);
+ }
+ catch (MalformedURLException e)
+ {
+ File file = new File(urlString);
+ try
+ {
+ url = file.toURI().toURL();
+ }
+ catch (MalformedURLException notAFile)
+ {
+ throw new IllegalConfigurationException("Cannot convert " + urlString + " to a readable resource");
+ }
+
+ }
+ return new InputStreamReader(url.openStream());
+ }
+ catch (IOException e)
+ {
+ throw new IllegalConfigurationException("Cannot convert " + urlString + " to a readable resource");
+ }
}
@Override
@@ -104,16 +144,10 @@
@Override
public void onCreate()
{
- if(_aclFile != null)
+ if(_fileName != null)
{
- //verify it exists
- if (!validate())
- {
- throw new IllegalConfigurationException("ACL file '" + _aclFile + "' is not found");
- }
-
//verify it is parsable
- new PlainConfiguration(_aclFile, _eventLogger).load();
+ new PlainConfiguration(_fileName, _eventLogger).load(getReaderFromURLString(_fileName));
}
}
diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java
index 6ac21f8..76435cb 100644
--- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java
+++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java
@@ -18,8 +18,10 @@
*/
package org.apache.qpid.server.security.access.config;
+import static org.mockito.Mockito.mock;
+
import java.io.File;
-import java.io.FileNotFoundException;
+import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.Map;
@@ -27,15 +29,12 @@
import junit.framework.TestCase;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
-import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.EventLoggerProvider;
import org.apache.qpid.server.security.access.ObjectProperties;
import org.apache.qpid.server.security.access.ObjectProperties.Property;
import org.apache.qpid.server.security.access.ObjectType;
import org.apache.qpid.server.security.access.Operation;
-import static org.mockito.Mockito.mock;
-
public class PlainConfigurationTest extends TestCase
{
private PlainConfiguration writeACLConfig(String...aclData) throws Exception
@@ -52,28 +51,11 @@
aclWriter.close();
// Load ruleset
- PlainConfiguration configFile = new PlainConfiguration(acl, mock(EventLoggerProvider.class));
- configFile.load();
+ PlainConfiguration configFile = new PlainConfiguration(acl.getName(), mock(EventLoggerProvider.class));
+ configFile.load(new FileReader(acl));
return configFile;
}
- public void testMissingACLConfig() throws Exception
- {
- try
- {
- // Load ruleset
- ConfigurationFile configFile = new PlainConfiguration(new File("doesnotexist"), mock(EventLoggerProvider.class));
- configFile.load();
-
- fail("fail");
- }
- catch (IllegalConfigurationException ce)
- {
- assertEquals(String.format(PlainConfiguration.CONFIG_NOT_FOUND_MSG, "doesnotexist"), ce.getMessage());
- assertTrue(ce.getCause() instanceof FileNotFoundException);
- }
- }
-
public void testACLFileSyntaxContinuation() throws Exception
{
try
diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderFactoryTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderFactoryTest.java
index 49697cf..a34ac16 100644
--- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderFactoryTest.java
+++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderFactoryTest.java
@@ -107,7 +107,7 @@
}
catch (IllegalConfigurationException e)
{
- assertTrue("Unexpected exception message: " + e.getMessage(), Pattern.matches("ACL file '.*' is not found", e.getMessage()));
+ assertTrue("Unexpected exception message: " + e.getMessage(), Pattern.matches("Cannot convert .* to a readable resource", e.getMessage()));
}
}
}
diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImplTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImplTest.java
index 005d2a9..82c209b 100644
--- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImplTest.java
+++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImplTest.java
@@ -73,7 +73,7 @@
}
catch (IllegalConfigurationException e)
{
- assertEquals("Unexpected exception message:" + e.getMessage(), String.format("ACL file '%s' is not found", aclFilePath ), e.getMessage());
+ assertEquals("Unexpected exception message:" + e.getMessage(), String.format("Cannot convert %s to a readable resource", aclFilePath ), e.getMessage());
}
}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
index 9a6059c..f7f65e2 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
@@ -122,6 +122,8 @@
public static final int DEFAULT_PREFETCH = 4096;
private static final Logger _logger = Logger.getLogger(AMQChannel.class);
+ private final DefaultQueueAssociationClearingTask
+ _defaultQueueAssociationClearingTask = new DefaultQueueAssociationClearingTask();
//TODO use Broker property to configure message authorization requirements
private boolean _messageAuthorizationRequired = Boolean.getBoolean(BrokerProperties.PROPERTY_MSG_AUTH);
@@ -139,7 +141,7 @@
private long _deliveryTag = 0;
/** A channel has a default queue (the last declared) that is used when no queue name is explicitly set */
- private AMQQueue _defaultQueue;
+ private volatile AMQQueue<?> _defaultQueue;
/** This tag is unique per subscription to a queue. The server returns this in response to a basic.consume request. */
private int _consumerTag;
@@ -180,11 +182,9 @@
private LogSubject _logSubject;
private volatile boolean _rollingBack;
- private static final Runnable NULL_TASK = new Runnable() { public void run() {} };
private List<MessageInstance> _resendList = new ArrayList<MessageInstance>();
private static final
AMQShortString IMMEDIATE_DELIVERY_REPLY_TEXT = new AMQShortString("Immediate delivery is not possible.");
- private long _createTime = System.currentTimeMillis();
private final ClientDeliveryMethod _clientDeliveryMethod;
@@ -829,7 +829,7 @@
getVirtualHost().getEventLogger().message(_logSubject, operationalLogMessage);
unsubscribeAllConsumers();
-
+ setDefaultQueue(null);
for (Action<? super AMQChannel> task : _taskList)
{
task.performAction(this);
@@ -1291,17 +1291,6 @@
return "("+ _suspended.get() + ", " + _closing.get() + ", " + _connection.isClosing() + ") "+"["+ _connection.toString()+":"+_channelId+"]";
}
- public void setDefaultQueue(AMQQueue queue)
- {
- _defaultQueue = queue;
- }
-
- public AMQQueue getDefaultQueue()
- {
- return _defaultQueue;
- }
-
-
public boolean isClosing()
{
return _closing.get();
@@ -2123,32 +2112,32 @@
catch (AMQQueue.ExistingExclusiveConsumer e)
{
_connection.closeConnection(AMQConstant.ACCESS_REFUSED,
- "Cannot subscribe to queue "
+ "Cannot subscribe to queue '"
+ queue1.getName()
- + " as it already has an existing exclusive consumer", _channelId);
+ + "' as it already has an existing exclusive consumer", _channelId);
}
catch (AMQQueue.ExistingConsumerPreventsExclusive e)
{
_connection.closeConnection(AMQConstant.ACCESS_REFUSED,
- "Cannot subscribe to queue "
+ "Cannot subscribe to queue '"
+ queue1.getName()
- + " exclusively as it already has a consumer", _channelId);
+ + "' exclusively as it already has a consumer", _channelId);
}
catch (AccessControlException e)
{
- _connection.closeConnection(AMQConstant.ACCESS_REFUSED, "Cannot subscribe to queue "
+ _connection.closeConnection(AMQConstant.ACCESS_REFUSED, "Cannot subscribe to queue '"
+ queue1.getName()
- + " permission denied", _channelId);
+ + "' permission denied", _channelId);
}
catch (MessageSource.ConsumerAccessRefused consumerAccessRefused)
{
_connection.closeConnection(AMQConstant.ACCESS_REFUSED,
- "Cannot subscribe to queue "
+ "Cannot subscribe to queue '"
+ queue1.getName()
- + " as it already has an incompatible exclusivity policy", _channelId);
+ + "' as it already has an incompatible exclusivity policy", _channelId);
}
@@ -2257,7 +2246,7 @@
// if the exchange does not exist we raise a channel exception
if (destination == null)
{
- closeChannel(AMQConstant.NOT_FOUND, "Unknown exchange name: " + exchangeName);
+ closeChannel(AMQConstant.NOT_FOUND, "Unknown exchange name: '" + exchangeName + "'");
}
else
{
@@ -2815,15 +2804,14 @@
exchange = virtualHost.getExchange(exchangeName.toString());
if (exchange == null)
{
- closeChannel(AMQConstant.NOT_FOUND, "Unknown exchange: " + exchangeName);
+ closeChannel(AMQConstant.NOT_FOUND, "Unknown exchange: '" + exchangeName + "'");
}
else if (!(type == null || type.length() == 0) && !exchange.getType().equals(type.asString()))
{
- _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: "
- +
- exchangeName
- + " of type "
+ _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: '"
+ + exchangeName
+ + "' of type "
+ exchange.getType()
+ " to "
+ type
@@ -2850,7 +2838,6 @@
{
attributes.putAll(FieldTable.convertToMap(arguments));
}
- attributes.put(Exchange.ID, null);
attributes.put(Exchange.NAME, name);
attributes.put(Exchange.TYPE, typeString);
attributes.put(Exchange.DURABLE, durable);
@@ -2875,8 +2862,8 @@
catch (ReservedExchangeNameException e)
{
_connection.closeConnection(AMQConstant.NOT_ALLOWED,
- "Attempt to declare exchange: " + exchangeName +
- " which begins with reserved prefix.", getChannelId());
+ "Attempt to declare exchange: '" + exchangeName +
+ "' which begins with reserved prefix.", getChannelId());
}
@@ -2885,8 +2872,8 @@
exchange = e.getExistingExchange();
if (!new AMQShortString(exchange.getType()).equals(type))
{
- _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: "
- + exchangeName + " of type "
+ _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: '"
+ + exchangeName + "' of type "
+ exchange.getType()
+ " to " + type + ".", getChannelId());
@@ -2922,7 +2909,7 @@
// note - since 0-8/9/9-1 can't set the alt. exchange this exception should never occur
final String message = "Unknown alternate exchange "
+ (e.getName() != null
- ? "name: \"" + e.getName() + "\""
+ ? "name: '" + e.getName() + "'"
: "id: " + e.getId());
_connection.closeConnection(AMQConstant.NOT_FOUND, message, getChannelId());
@@ -2968,7 +2955,7 @@
final ExchangeImpl exchange = virtualHost.getExchange(exchangeName);
if (exchange == null)
{
- closeChannel(AMQConstant.NOT_FOUND, "No such exchange: " + exchangeStr);
+ closeChannel(AMQConstant.NOT_FOUND, "No such exchange: '" + exchangeStr + "'");
}
else
{
@@ -3045,7 +3032,7 @@
else if (isDefaultExchange(exchange))
{
_connection.closeConnection(AMQConstant.NOT_ALLOWED,
- "Cannot bind the queue " + queueName + " to the default exchange", getChannelId());
+ "Cannot bind the queue '" + queueName + "' to the default exchange", getChannelId());
}
else
@@ -3057,7 +3044,7 @@
if (exch == null)
{
closeChannel(AMQConstant.NOT_FOUND,
- "Exchange " + exchangeName + " does not exist.");
+ "Exchange '" + exchangeName + "' does not exist.");
}
else
{
@@ -3137,7 +3124,7 @@
queueName = queueStr.intern();
}
- AMQQueue queue;
+ AMQQueue<?> queue;
//TODO: do we need to check that the queue already exists with exactly the same "configuration"?
@@ -3148,19 +3135,19 @@
if (queue == null)
{
closeChannel(AMQConstant.NOT_FOUND,
- "Queue: "
+ "Queue: '"
+ queueName
- + " not found on VirtualHost("
- + virtualHost
- + ").");
+ + "' not found on VirtualHost '"
+ + virtualHost.getName()
+ + "'.");
}
else
{
if (!queue.verifySessionAccess(this))
{
- _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Queue "
+ _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Queue '"
+ queue.getName()
- + " is exclusive, but not created on this Connection.", getChannelId());
+ + "' is exclusive, but not created on this Connection.", getChannelId());
}
else
{
@@ -3190,7 +3177,6 @@
QueueArgumentsConverter.convertWireArgsToModel(FieldTable.convertToMap(arguments));
final String queueNameString = AMQShortString.toString(queueName);
attributes.put(Queue.NAME, queueNameString);
- attributes.put(Queue.ID, UUID.randomUUID());
attributes.put(Queue.DURABLE, durable);
LifetimePolicy lifetimePolicy;
@@ -3237,9 +3223,9 @@
if (!queue.verifySessionAccess(this))
{
- _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Queue "
+ _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Queue '"
+ queue.getName()
- + " is exclusive, but not created on this Connection.", getChannelId());
+ + "' is exclusive, but not created on this Connection.", getChannelId());
}
else if (queue.isExclusive() != exclusive)
@@ -3333,27 +3319,27 @@
if (queue == null)
{
- closeChannel(AMQConstant.NOT_FOUND, "Queue " + queueName + " does not exist.");
+ closeChannel(AMQConstant.NOT_FOUND, "Queue '" + queueName + "' does not exist.");
}
else
{
if (ifEmpty && !queue.isEmpty())
{
- closeChannel(AMQConstant.IN_USE, "Queue: " + queueName + " is not empty.");
+ closeChannel(AMQConstant.IN_USE, "Queue: '" + queueName + "' is not empty.");
}
else if (ifUnused && !queue.isUnused())
{
// TODO - Error code
- closeChannel(AMQConstant.IN_USE, "Queue: " + queueName + " is still used.");
+ closeChannel(AMQConstant.IN_USE, "Queue: '" + queueName + "' is still used.");
}
else
{
if (!queue.verifySessionAccess(this))
{
- _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Queue "
+ _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Queue '"
+ queue.getName()
- + " is exclusive, but not created on this Connection.", getChannelId());
+ + "' is exclusive, but not created on this Connection.", getChannelId());
}
else
@@ -3393,7 +3379,7 @@
}
else if ((queueName != null) && (queue = virtualHost.getQueue(queueName.toString())) == null)
{
- closeChannel(AMQConstant.NOT_FOUND, "Queue " + queueName + " does not exist.");
+ closeChannel(AMQConstant.NOT_FOUND, "Queue '" + queueName + "' does not exist.");
}
else if (!queue.verifySessionAccess(this))
{
@@ -3426,14 +3412,14 @@
@Override
public void receiveQueueUnbind(final AMQShortString queueName,
final AMQShortString exchange,
- final AMQShortString routingKey,
+ final AMQShortString bindingKey,
final FieldTable arguments)
{
if(_logger.isDebugEnabled())
{
_logger.debug("RECV[" + _channelId + "] QueueUnbind[" +" queue: " + queueName +
" exchange: " + exchange +
- " bindingKey: " + routingKey +
+ " bindingKey: " + bindingKey +
" arguments: " + arguments + " ]");
}
@@ -3450,14 +3436,14 @@
{
String message = useDefaultQueue
? "No default queue defined on channel and queue was null"
- : "Queue " + queueName + " does not exist.";
+ : "Queue '" + queueName + "' does not exist.";
closeChannel(AMQConstant.NOT_FOUND, message);
}
else if (isDefaultExchange(exchange))
{
- _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Cannot unbind the queue "
+ _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Cannot unbind the queue '"
+ queue.getName()
- + " from the default exchange", getChannelId());
+ + "' from the default exchange", getChannelId());
}
else
@@ -3467,9 +3453,9 @@
if (exch == null)
{
- closeChannel(AMQConstant.NOT_FOUND, "Exchange " + exchange + " does not exist.");
+ closeChannel(AMQConstant.NOT_FOUND, "Exchange '" + exchange + "' does not exist.");
}
- else if (!exch.hasBinding(String.valueOf(routingKey), queue))
+ else if (!exch.hasBinding(String.valueOf(bindingKey), queue))
{
closeChannel(AMQConstant.NOT_FOUND, "No such binding");
}
@@ -3477,7 +3463,7 @@
{
try
{
- exch.deleteBinding(String.valueOf(routingKey), queue);
+ exch.deleteBinding(String.valueOf(bindingKey), queue);
final AMQMethodBody responseBody = _connection.getMethodRegistry().createQueueUnbindOkBody();
sync();
@@ -3598,4 +3584,37 @@
return exchangeName == null || AMQShortString.EMPTY_STRING.equals(exchangeName);
}
+ private void setDefaultQueue(AMQQueue<?> queue)
+ {
+ AMQQueue<?> currentDefaultQueue = _defaultQueue;
+ if (queue != currentDefaultQueue)
+ {
+ if (currentDefaultQueue != null)
+ {
+ currentDefaultQueue.removeDeleteTask(_defaultQueueAssociationClearingTask);
+ }
+ if (queue != null)
+ {
+ queue.addDeleteTask(_defaultQueueAssociationClearingTask);
+ }
+ }
+ _defaultQueue = queue;
+ }
+
+ private AMQQueue getDefaultQueue()
+ {
+ return _defaultQueue;
+ }
+
+ private class DefaultQueueAssociationClearingTask implements Action<AMQQueue>
+ {
+ @Override
+ public void performAction(final AMQQueue queue)
+ {
+ if ( queue == _defaultQueue)
+ {
+ _defaultQueue = null;
+ }
+ }
+ }
}
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
index f5827a3..01c11b9 100644
--- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
@@ -518,6 +518,11 @@
}
_connection.sessionEnded(this);
+ performCloseTasks();
+ if(_modelObject != null)
+ {
+ _modelObject.delete();
+ }
}
diff --git a/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java b/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java
index a8b9eda..0cc4f2b 100644
--- a/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java
+++ b/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java
@@ -20,7 +20,8 @@
*/
package org.apache.qpid.server.store.derby;
-import org.apache.qpid.server.BrokerOptions;
+import java.util.Map;
+
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.LogRecorder;
@@ -48,10 +49,10 @@
public DerbySystemConfigImpl(final TaskExecutor taskExecutor,
final EventLogger eventLogger,
final LogRecorder logRecorder,
- final BrokerOptions brokerOptions,
+ final Map<String,Object> attributes,
final BrokerShutdownProvider brokerShutdownProvider)
{
- super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);
+ super(taskExecutor, eventLogger, logRecorder, attributes, brokerShutdownProvider);
}
@Override
diff --git a/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/virtualhostnode/derby/DerbyVirtualHostNodeImpl.java b/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/virtualhostnode/derby/DerbyVirtualHostNodeImpl.java
index 4bb3cc5..dc768af 100644
--- a/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/virtualhostnode/derby/DerbyVirtualHostNodeImpl.java
+++ b/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/virtualhostnode/derby/DerbyVirtualHostNodeImpl.java
@@ -21,6 +21,8 @@
package org.apache.qpid.server.virtualhostnode.derby;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Map;
import org.apache.qpid.server.logging.messages.ConfigStoreMessages;
@@ -33,7 +35,9 @@
import org.apache.qpid.server.store.derby.DerbyConfigurationStore;
import org.apache.qpid.server.virtualhostnode.AbstractStandardVirtualHostNode;
-@ManagedObject( category = false, type = DerbyVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE )
+@ManagedObject( category = false,
+ type = DerbyVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE,
+ validChildTypes = "org.apache.qpid.server.virtualhostnode.derby.DerbyVirtualHostNodeImpl#getSupportedChildTypes()" )
public class DerbyVirtualHostNodeImpl extends AbstractStandardVirtualHostNode<DerbyVirtualHostNodeImpl> implements DerbyVirtualHostNode<DerbyVirtualHostNodeImpl>
{
public static final String VIRTUAL_HOST_NODE_TYPE = "DERBY";
@@ -70,4 +74,10 @@
{
return getClass().getSimpleName() + " [id=" + getId() + ", name=" + getName() + ", storePath=" + getStorePath() + "]";
}
+
+
+ public static Map<String, Collection<String>> getSupportedChildTypes()
+ {
+ return Collections.singletonMap(VirtualHost.class.getSimpleName(), getSupportedVirtualHostTypes(true));
+ }
}
diff --git a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java
index a552b17..9c3d33f 100644
--- a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java
+++ b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java
@@ -20,7 +20,8 @@
*/
package org.apache.qpid.server.store.jdbc;
-import org.apache.qpid.server.BrokerOptions;
+import java.util.Map;
+
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.LogRecorder;
@@ -50,10 +51,10 @@
public JDBCSystemConfigImpl(final TaskExecutor taskExecutor,
final EventLogger eventLogger,
final LogRecorder logRecorder,
- final BrokerOptions brokerOptions,
+ final Map<String,Object> attributes,
final BrokerShutdownProvider brokerShutdownProvider)
{
- super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);
+ super(taskExecutor, eventLogger, logRecorder, attributes, brokerShutdownProvider);
}
@Override
diff --git a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhostnode/jdbc/JDBCVirtualHostNodeImpl.java b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhostnode/jdbc/JDBCVirtualHostNodeImpl.java
index eab53e6..cb20549 100644
--- a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhostnode/jdbc/JDBCVirtualHostNodeImpl.java
+++ b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhostnode/jdbc/JDBCVirtualHostNodeImpl.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.server.virtualhostnode.jdbc;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Map;
import org.apache.qpid.server.model.Broker;
@@ -31,7 +33,8 @@
import org.apache.qpid.server.store.jdbc.GenericJDBCConfigurationStore;
import org.apache.qpid.server.virtualhostnode.AbstractStandardVirtualHostNode;
-@ManagedObject(type = JDBCVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE, category = false )
+@ManagedObject(type = JDBCVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE, category = false ,
+ validChildTypes = "org.apache.qpid.server.virtualhostnode.jdbc.JDBCVirtualHostNodeImpl#getSupportedChildTypes()")
public class JDBCVirtualHostNodeImpl extends AbstractStandardVirtualHostNode<JDBCVirtualHostNodeImpl> implements JDBCVirtualHostNode<JDBCVirtualHostNodeImpl>
{
public static final String VIRTUAL_HOST_NODE_TYPE = "JDBC";
@@ -97,4 +100,10 @@
", connectionPoolType=" + getConnectionPoolType() +
", username=" + getUsername() + "]";
}
+
+
+ public static Map<String, Collection<String>> getSupportedChildTypes()
+ {
+ return Collections.singletonMap(VirtualHost.class.getSimpleName(), getSupportedVirtualHostTypes(true));
+ }
}
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java
index 1e79548..cafde3b 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java
@@ -54,9 +54,6 @@
_mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
Action[] supportedActions = {
- new ListBrokerAttribute(Broker.SUPPORTED_VIRTUALHOSTNODE_TYPES, "ListVirtualHostNodeTypes"),
- new ListBrokerAttribute(Broker.SUPPORTED_VIRTUALHOST_TYPES, "ListVirtualHostTypes"),
- new ListBrokerAttribute(Broker.SUPPORTED_PREFERENCES_PROVIDER_TYPES, "ListPreferencesProvidersTypes"),
new ListBrokerAttribute(Broker.PRODUCT_VERSION, "version"),
new ListGroupProviderAttributes(),
new ListAccessControlProviderAttributes(),
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MetaDataServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MetaDataServlet.java
index 2947cfb..01dd873 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MetaDataServlet.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MetaDataServlet.java
@@ -24,6 +24,7 @@
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -101,9 +102,24 @@
Map<String,Object> typeDetails = new LinkedHashMap<>();
typeDetails.put("attributes", processAttributes(type));
typeDetails.put("managedInterfaces", getManagedInterfaces(type));
+ typeDetails.put("validChildTypes", getValidChildTypes(type));
return typeDetails;
}
+ private Map<String, Collection<String>> getValidChildTypes(final Class<? extends ConfiguredObject> type)
+ {
+ Map<String, Collection<String>> validChildTypes = new HashMap<>();
+ for(Class<? extends ConfiguredObject> childType : _instance.getChildTypes(ConfiguredObjectTypeRegistry.getCategory(type)))
+ {
+ Collection<String> validValues = _instance.getTypeRegistry().getValidChildTypes(type, childType);
+ if(validValues != null)
+ {
+ validChildTypes.put(childType.getSimpleName(), validValues);
+ }
+ }
+ return validChildTypes;
+ }
+
private Set<String> getManagedInterfaces(Class<? extends ConfiguredObject> type)
{
Set<String> interfaces = new HashSet<>();
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
index 0bc0a45..71ec6e7 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
@@ -36,7 +36,6 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
-import javax.xml.bind.DatatypeConverter;
import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;
@@ -46,6 +45,7 @@
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.util.urlstreamhandler.data.Handler;
+import org.apache.qpid.util.DataUrlUtils;
public class RestServlet extends AbstractServlet
{
@@ -62,13 +62,20 @@
public static final String INHERITED_ACTUALS_PARAM = "inheritedActuals";
public static final String EXTRACT_INITIAL_CONFIG_PARAM = "extractInitialConfig";
+ /**
+ * Signifies that the agent wishes the servlet to set the Content-Disposition on the
+ * response with the value attachment. This filename will be derived from the parameter value.
+ */
+ public static final String CONTENT_DISPOSITION_ATTACHMENT_FILENAME_PARAM = "contentDispositionAttachmentFilename";
+
public static final Set<String> RESERVED_PARAMS =
new HashSet<>(Arrays.asList(DEPTH_PARAM,
SORT_PARAM,
ACTUALS_PARAM,
INCLUDE_SYS_CONTEXT_PARAM,
EXTRACT_INITIAL_CONFIG_PARAM,
- INHERITED_ACTUALS_PARAM));
+ INHERITED_ACTUALS_PARAM,
+ CONTENT_DISPOSITION_ATTACHMENT_FILENAME_PARAM));
private Class<? extends ConfiguredObject>[] _hierarchy;
@@ -316,19 +323,29 @@
@Override
protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
+ // TODO - sort special params, everything else should act as a filter
+ String attachmentFilename = request.getParameter(CONTENT_DISPOSITION_ATTACHMENT_FILENAME_PARAM);
+ boolean extractInitialConfig = getBooleanParameterFromRequest(request, EXTRACT_INITIAL_CONFIG_PARAM);
+
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_OK);
- setCachingHeadersOnResponse(response);
+ if (attachmentFilename == null)
+ {
+ setCachingHeadersOnResponse(response);
+ }
+ else
+ {
+ setContentDispositionHeaderIfNecessary(response, attachmentFilename);
+ }
Collection<ConfiguredObject<?>> allObjects = getObjects(request);
- // TODO - sort special params, everything else should act as a filter
- boolean extractInitialConfig = getBooleanParameterFromRequest(request, EXTRACT_INITIAL_CONFIG_PARAM);
int depth;
boolean actuals;
boolean includeSystemContext;
boolean inheritedActuals;
+
if(extractInitialConfig)
{
depth = Integer.MAX_VALUE;
@@ -344,20 +361,35 @@
inheritedActuals = getBooleanParameterFromRequest(request, INHERITED_ACTUALS_PARAM);
}
- List<Map<String, Object>> output = new ArrayList<Map<String, Object>>();
+ List<Map<String, Object>> output = new ArrayList<>();
for(ConfiguredObject configuredObject : allObjects)
{
output.add(_objectConverter.convertObjectToMap(configuredObject, getConfiguredClass(),
depth, actuals, inheritedActuals, includeSystemContext, extractInitialConfig));
}
+
Writer writer = getOutputWriter(request, response);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
mapper.writeValue(writer, extractInitialConfig && output.size() == 1 ? output.get(0) : output);
+ }
- response.setContentType("application/json");
- response.setStatus(HttpServletResponse.SC_OK);
+ private void setContentDispositionHeaderIfNecessary(final HttpServletResponse response,
+ final String attachmentFilename)
+ {
+ if (attachmentFilename != null)
+ {
+ String filenameRfc2183 = ensureFilenameIsRfc2183(attachmentFilename);
+ if (filenameRfc2183.length() > 0)
+ {
+ response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", filenameRfc2183));
+ }
+ else
+ {
+ response.setHeader("Content-disposition", String.format("attachment")); // Agent will allow user to choose a name
+ }
+ }
}
private Class<? extends ConfiguredObject> getConfiguredClass()
@@ -407,8 +439,7 @@
{
byte[] data = new byte[(int) part.getSize()];
part.getInputStream().read(data);
- StringBuilder inlineURL = new StringBuilder("data:;base64,");
- inlineURL.append(DatatypeConverter.printBase64Binary(data));
+ String inlineURL = DataUrlUtils.getDataUrlForBytes(data);
fileUploads.put(part.getName(),inlineURL.toString());
}
}
@@ -671,4 +702,10 @@
return Boolean.parseBoolean(request.getParameter(paramName));
}
+ private String ensureFilenameIsRfc2183(final String requestedFilename)
+ {
+ String fileNameRfc2183 = requestedFilename.replaceAll("[\\P{InBasic_Latin}\\\\:/]", "");
+ return fileNameRfc2183;
+ }
+
}
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/aclfile/add.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/aclfile/add.html
new file mode 100644
index 0000000..796988c
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/aclfile/add.html
@@ -0,0 +1,64 @@
+<!--
+ ~ 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.
+ -->
+
+<div>
+ <div id="addAccessControlProvider.oldBrowserWarning" class="infoMessage hidden clear"></div>
+ <div class="clear">
+ <div id="addAccessControlProvider.serverPathLabel" class="formLabel-labelCell tableContainer-labelCell">Server path or upload*:</div>
+ <div class="formLabel-controlCell tableContainer-valueCell">
+ <input type="text" id="addAccessControlProvider.serverPath"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'serverPath',
+ placeHolder: 'access control provider file server path',
+ required: true,
+ excluded: true,
+ promptMessage: 'Location of the access control provider file on the server',
+ title: 'Enter the access control provider file path'" />
+
+ <!-- Hidden and used purely for form submission -->
+ <input type="hidden" id="addAccessControlProvider.path"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'path',
+ required: true" />
+ </div>
+
+ <div id="addAccessControlProvider.uploadFields">
+ <div id="addAccessControlProvider.fileLabel" class="formLabel-labelCell tableContainer-labelCell"></div>
+ <div class="fileUpload clear">
+ <span id="addAccessControlProvider.selectedFile" class="infoMessage"></span>
+ <span id="addAccessControlProvider.selectedFileStatus"></span>
+ </div>
+
+ <div class="fileUpload clear">
+ <input type="file" id="addAccessControlProvider.file"
+ multiple="false"
+ data-dojo-type="dojox/form/Uploader"
+ data-dojo-props="label: 'Upload'"/>
+ <button id="addAccessControlProvider.fileClearButton"
+ data-dojo-type="dijit/form/Button"
+ data-dojo-props="label: 'Clear',
+ disabled: true">
+ </button>
+ </div>
+ </div>
+
+ </div>
+</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addAccessControlProvider.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addAccessControlProvider.html
new file mode 100644
index 0000000..07a0c4c
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addAccessControlProvider.html
@@ -0,0 +1,66 @@
+<!--
+ ~ 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.
+ -->
+<div class="dijitHidden">
+ <div data-dojo-type="dijit/Dialog" data-dojo-props="title:'Access Control Provider'" id="addAccessControlProvider">
+ <div id="addAccessControlProvider.contentPane">
+ <form id="addAccessControlProvider.form" method="post" data-dojo-type="dijit/form/Form">
+ <div class="formBox">
+ <div class="clear">
+ <div class="formLabel-labelCell tableContainer-labelCell">Name*:</div>
+ <div class="formLabel-controlCell tableContainer-valueCell">
+ <input type="text" id="addAccessControlProvider.name"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'name',
+ placeHolder: 'access control provider name',
+ required: true,
+ promptMessage: 'Name of access control provider, must be unique',
+ title: 'Enter a unique access control provider name per broker'" />
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell tableContainer-labelCell">Type*:</div>
+ <div class="tableContainer-valueCell formLabel-controlCell">
+ <select id="addAccessControlProvider.type" data-dojo-type="dijit/form/FilteringSelect"
+ data-dojo-props="
+ name: 'type',
+ required: true,
+ placeHolder: 'select access control provider type',
+ promptMessage: 'Type of access control provider',
+ title: 'Select access control provider type',
+ searchAttr: 'name'">
+ </select>
+ </div>
+ </div>
+
+ <div class="clear">
+ <div id="addAccessControlProvider.typeFields"></div>
+ </div>
+ </div>
+ </form>
+ <div class="clear">
+ </div>
+ </div>
+
+ <div class="dijitDialogPaneActionBar">
+ <button data-dojo-type="dijit/form/Button" id="addAccessControlProvider.addButton" data-dojo-props="label: 'Save'" type="submit"></button>
+ <button data-dojo-type="dijit/form/Button" id="addAccessControlProvider.cancelButton" data-dojo-props="label: 'Cancel'" ></button>
+ </div>
+ </div>
+</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addStore.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addStore.html
new file mode 100644
index 0000000..dd6e7a3
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addStore.html
@@ -0,0 +1,66 @@
+<!--
+ ~ 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.
+ -->
+
+<div class="dijitHidden">
+ <div data-dojo-type="dijit/Dialog" data-dojo-props="title:'Add Store'" id="addStore">
+ <div id="addStore.contentPane">
+ <form id="addStore.form" method="post" data-dojo-type="dijit/form/Form">
+ <div class="formBox">
+ <div class="clear">
+ <div class="formLabel-labelCell tableContainer-labelCell">Name*:</div>
+ <div class="formLabel-controlCell tableContainer-valueCell">
+ <input type="text" id="addStore.name"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'name',
+ placeHolder: 'store name',
+ required: true,
+ promptMessage: 'Name of store, must be unique',
+ title: 'Enter a unique store name per broker'" />
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell tableContainer-labelCell">Type*:</div>
+ <div class="tableContainer-valueCell formLabel-controlCell">
+ <select id="addStore.type" data-dojo-type="dijit/form/FilteringSelect"
+ data-dojo-props="
+ name: 'type',
+ required: true,
+ placeHolder: 'store type',
+ promptMessage: 'Type of store',
+ title: 'Select type',
+ searchAttr: 'name'">
+ </select>
+ </div>
+ </div>
+ <div class="clear">
+ <div id="addStore.typeFields"></div>
+ </div>
+ </div>
+ </form>
+ <div class="clear">
+ </div>
+ </div>
+
+ <div class="dijitDialogPaneActionBar">
+ <button data-dojo-type="dijit/form/Button" id="addStore.addButton" data-dojo-props="label: 'Save'" type="submit"></button>
+ <button data-dojo-type="dijit/form/Button" id="addStore.cancelButton" data-dojo-props="label: 'Cancel'" ></button>
+ </div>
+ </div>
+</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addVirtualHostNodeAndVirtualHost.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addVirtualHostNodeAndVirtualHost.html
index 3e3e931..383c782 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/addVirtualHostNodeAndVirtualHost.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addVirtualHostNodeAndVirtualHost.html
@@ -59,6 +59,34 @@
<div id="addVirtualHostNode.typeFields"></div>
+ <div id="addVirtualHostNode.uploadFields" class="clear">
+ <div class="formLabel-labelCell">
+ <label for="addVirtualHostNode.upload">Upload virtualhost configuration from file:</label>
+ </div>
+ <div class="formLabel-controlCell">
+ <input id="addVirtualHostNode.upload" type="checkbox"
+ data-dojo-type="dijit.form.CheckBox"
+ data-dojo-props="
+ name: 'upload'" />
+ </div>
+ <div id="addVirtualHostNode.fileFields" class="clear">
+ <div class="formLabel-labelCell">
+ <label for="addVirtualHostNode.file">Select JSON file*:</label>
+ </div>
+ <div class="tableContainer-valueCell formLabel-controlCell">
+ <input type="file" id="addVirtualHostNode.file"
+ multiple="false"
+ data-dojo-type="dojox.form.Uploader"
+ data-dojo-props="
+ label: 'Select'"/>
+ <span id="addVirtualHostNode.selectedFile" class="infoMessage"></span>
+ <span id="addVirtualHostNode.selectedFileStatus"></span>
+ </div>
+ </div>
+ </div>
+
+ <div class="clear"></div>
+
<div data-dojo-type="dijit/TitlePane" data-dojo-props="title: 'Context variables', open: false">
<div id="addVirtualHostNode.context"></div>
</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css b/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css
index d04117b..a18562f 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css
@@ -215,6 +215,30 @@
height: 16px;
}
+.loadingIcon
+{
+ background: url("../dojo/dojox/image/resources/images/loading.gif") no-repeat;
+ width: 16px;
+ height: 16px;
+ background-size: contain;
+ display: inline-block;
+}
+
+.loadedIcon
+{
+ background: url("../dojo/dijit/icons/images/commonIconsObjActEnabled_rtl.png") no-repeat;
+ background-position: -352px -0px;
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+}
+
+.fileUpload
+{
+ float: right;
+ padding: 5px;
+}
+
.infoMessage
{
padding: 5px;
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html
index eb742bb..379a25b 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html
@@ -25,6 +25,7 @@
<link rel="stylesheet" href="dojo/dojox/grid/enhanced/resources/claro/EnhancedGrid.css">
<link rel="stylesheet" href="dojo/dojox/grid/enhanced/resources/EnhancedGrid_rtl.css">
<link rel="stylesheet" href="dojo/dojox/form/resources/CheckedMultiSelect.css">
+ <link rel="stylesheet" href="dojo/dojox/form/resources/FileInput.css" />
<link rel="stylesheet" href="css/common.css" media="screen">
<script>
function getContextPath()
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/metadata.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/metadata.js
index 749b9b8..c62ba5d 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/metadata.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/metadata.js
@@ -69,7 +69,13 @@
implementsManagedInterface: function (category, type, managedInterfaceName)
{
return this.getMetaData(category, type).managedInterfaces.indexOf(managedInterfaceName) >= 0;
+ },
+ validChildTypes: function (category, type, childCategory)
+ {
+ var metaData = this.getMetaData(category, type);
+ return metaData ? metaData.validChildTypes[childCategory] : [];
}
+
};
metadata._init();
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js
index c6741ca..161ce4f 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js
@@ -159,8 +159,8 @@
this.deletePreferencesProviderButton = query(".deletePreferencesProviderButton", node)[0];
this.preferencesProviderAttributes = dom.byId("preferencesProviderAttributes")
this.preferencesNode = query(".preferencesProviderDetails", node)[0];
- this.authenticationProviderDetailsContainer = query(".authenticationProviderDetails", node)[0];
+this.authenticationProviderDetailsContainer = query(".authenticationProviderDetails", node)[0];
this.query = "api/latest/authenticationprovider/" + encodeURIComponent(authProviderObj.name);
}
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js
index 5363882..a0a2e83 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js
@@ -23,6 +23,7 @@
"dojo/query",
"dojo/json",
"dojo/_base/connect",
+ "dojo/store/Memory",
"qpid/common/properties",
"qpid/common/updater",
"qpid/common/util",
@@ -33,7 +34,7 @@
"qpid/management/addAuthenticationProvider",
"qpid/management/addVirtualHostNodeAndVirtualHost",
"qpid/management/addPort",
- "qpid/management/addKeystore",
+ "qpid/management/addStore",
"qpid/management/addGroupProvider",
"qpid/management/addAccessControlProvider",
"qpid/management/editBroker",
@@ -50,8 +51,8 @@
"dijit/Menu",
"dijit/MenuItem",
"dojo/domReady!"],
- function (xhr, parser, query, json, connect, properties, updater, util, UpdatableStore, EnhancedGrid, registry, entities,
- addAuthenticationProvider, addVirtualHostNodeAndVirtualHost, addPort, addKeystore, addGroupProvider, addAccessControlProvider, editBroker) {
+ function (xhr, parser, query, json, connect, memory, properties, updater, util, UpdatableStore, EnhancedGrid, registry, entities,
+ addAuthenticationProvider, addVirtualHostNodeAndVirtualHost, addPort, addStore, addGroupProvider, addAccessControlProvider, editBroker) {
var brokerAttributeNames = ["name", "operatingSystem", "platform", "productVersion", "modelVersion",
"defaultVirtualHost", "statisticsReportingPeriod", "statisticsReportingResetEnabled",
@@ -153,7 +154,11 @@
var addKeystoreButton = query(".addKeystore", contentPane.containerNode)[0];
connect.connect(registry.byNode(addKeystoreButton), "onClick",
- function(evt){ addKeystore.showKeystoreDialog() });
+ function(evt)
+ {
+ addStore.setupTypeStore("KeyStore");
+ addStore.show();
+ });
var deleteKeystore = query(".deleteKeystore", contentPane.containerNode)[0];
connect.connect(registry.byNode(deleteKeystore), "onClick",
@@ -168,7 +173,11 @@
var addTruststoreButton = query(".addTruststore", contentPane.containerNode)[0];
connect.connect(registry.byNode(addTruststoreButton), "onClick",
- function(evt){ addKeystore.showTruststoreDialog() });
+ function(evt)
+ {
+ addStore.setupTypeStore("TrustStore");
+ addStore.show();
+ });
var deleteTruststore = query(".deleteTruststore", contentPane.containerNode)[0];
connect.connect(registry.byNode(deleteTruststore), "onClick",
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/KeyStore.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/KeyStore.js
index 84103fd..6cb9ad7 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/KeyStore.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/KeyStore.js
@@ -29,16 +29,15 @@
"qpid/common/updater",
"qpid/common/util",
"qpid/common/formatter",
- "qpid/management/addKeystore",
+ "qpid/management/addStore",
"dojo/domReady!"],
- function (dom, xhr, parser, query, connect, registry, entities, properties, updater, util, formatter, addKeystore) {
+ function (dom, xhr, parser, query, connect, registry, entities, properties, updater, util, formatter, addStore) {
- function KeyStore(name, parent, controller, objectType) {
+ function KeyStore(name, parent, controller) {
this.keyStoreName = name;
this.controller = controller;
this.modelObj = { type: "keystore", name: name, parent: parent};
this.url = "api/latest/keystore/" + encodeURIComponent(name);
- this.dialog = addKeystore.showKeystoreDialog;
}
KeyStore.prototype.getTitle = function() {
@@ -48,7 +47,7 @@
KeyStore.prototype.open = function(contentPane) {
var that = this;
this.contentPane = contentPane;
- xhr.get({url: "showKeyStore.html",
+ xhr.get({url: "showStore.html",
sync: true,
load: function(data) {
contentPane.containerNode.innerHTML = data;
@@ -60,22 +59,22 @@
that.keyStoreUpdater.update();
- var deleteKeyStoreButton = query(".deleteKeyStoreButton", contentPane.containerNode)[0];
+ var deleteKeyStoreButton = query(".deleteStoreButton", contentPane.containerNode)[0];
var node = registry.byNode(deleteKeyStoreButton);
connect.connect(node, "onClick",
function(evt){
that.deleteKeyStore();
});
- var editKeyStoreButton = query(".editKeyStoreButton", contentPane.containerNode)[0];
+ var editKeyStoreButton = query(".editStoreButton", contentPane.containerNode)[0];
var node = registry.byNode(editKeyStoreButton);
connect.connect(node, "onClick",
function(evt){
xhr.get({url: that.url, sync: properties.useSyncGet, handleAs: "json", content: { actuals: true }})
.then(function(data)
{
- // calls showKeystoreDialog
- that.dialog(data[0], that.url);
+ addStore.setupTypeStore("KeyStore");
+ addStore.show(data[0], that.url);
});
});
}});
@@ -88,9 +87,10 @@
function KeyStoreUpdater(containerNode, keyStoreObj, controller, url)
{
var that = this;
+ this.keyStoreDetailsContainer = query(".typeFieldsContainer", containerNode)[0];
function findNode(name) {
- return query("." + name + "Value", containerNode)[0];
+ return query("." + name, containerNode)[0];
}
function storeNodes(names)
@@ -101,12 +101,8 @@
}
storeNodes(["name",
- "path",
- "keyStoreType",
- "keyStoreState",
- "keyManagerFactoryAlgorithm",
- "certificateAlias",
- "peersOnly"
+ "type",
+ "state"
]);
this.query = url;
@@ -122,22 +118,27 @@
KeyStoreUpdater.prototype.updateHeader = function()
{
this.name.innerHTML = entities.encode(String(this.keyStoreData[ "name" ]));
- this.path.innerHTML = entities.encode(String(this.keyStoreData[ "path" ]));
- this.keyStoreType.innerHTML = entities.encode(String(this.keyStoreData[ "keyStoreType" ]));
- this.keyStoreState.innerHTML = entities.encode(String(this.keyStoreData[ "state" ]));
- this.keyManagerFactoryAlgorithm.innerHTML = entities.encode(String(this.keyStoreData[ "keyManagerFactoryAlgorithm" ]));
- this.certificateAlias.innerHTML = this.keyStoreData[ "certificateAlias" ] ? entities.encode(String( this.keyStoreData[ "certificateAlias" ])) : "";
+ this.type.innerHTML = entities.encode(String(this.keyStoreData[ "type" ]));
+ this.state.innerHTML = entities.encode(String(this.keyStoreData[ "state" ]));
};
KeyStoreUpdater.prototype.update = function()
{
- var thisObj = this;
+ var that = this;
xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
{
- thisObj.keyStoreData = data[0];
- thisObj.updateHeader();
+ that.keyStoreData = data[0];
+ that.updateHeader();
+
+ require(["qpid/management/store/" + encodeURIComponent(that.keyStoreData.type.toLowerCase()) + "/show"],
+ function(DetailsUI)
+ {
+ that.details = new DetailsUI({containerNode:that.keyStoreDetailsContainer, parent: that});
+ that.details.update(that.keyStoreData);
+ }
+ );
});
};
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/TrustStore.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/TrustStore.js
index 9b243cc..f3fa06c 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/TrustStore.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/TrustStore.js
@@ -29,16 +29,15 @@
"qpid/common/updater",
"qpid/common/util",
"qpid/common/formatter",
- "qpid/management/addKeystore",
+ "qpid/management/addStore",
"dojo/domReady!"],
- function (dom, xhr, parser, query, connect, registry, entities, properties, updater, util, formatter, addKeystore) {
+ function (dom, xhr, parser, query, connect, registry, entities, properties, updater, util, formatter, addStore) {
function TrustStore(name, parent, controller) {
this.keyStoreName = name;
this.controller = controller;
this.modelObj = { type: "truststore", name: name, parent: parent};
this.url = "api/latest/truststore/" + encodeURIComponent(name);
- this.dialog = addKeystore.showTruststoreDialog;
}
TrustStore.prototype.getTitle = function() {
@@ -48,7 +47,7 @@
TrustStore.prototype.open = function(contentPane) {
var that = this;
this.contentPane = contentPane;
- xhr.get({url: "showTrustStore.html",
+ xhr.get({url: "showStore.html",
sync: true,
load: function(data) {
contentPane.containerNode.innerHTML = data;
@@ -60,28 +59,27 @@
that.keyStoreUpdater.update();
- var deleteTrustStoreButton = query(".deleteTrustStoreButton", contentPane.containerNode)[0];
+ var deleteTrustStoreButton = query(".deleteStoreButton", contentPane.containerNode)[0];
var node = registry.byNode(deleteTrustStoreButton);
connect.connect(node, "onClick",
function(evt){
that.deleteKeyStore();
});
- var editTrustStoreButton = query(".editTrustStoreButton", contentPane.containerNode)[0];
+ var editTrustStoreButton = query(".editStoreButton", contentPane.containerNode)[0];
var node = registry.byNode(editTrustStoreButton);
connect.connect(node, "onClick",
function(evt){
xhr.get({url: that.url, sync: properties.useSyncGet, handleAs: "json", content: { actuals: true }})
.then(function(data)
{
- that.dialog(data[0], that.url);
+ addStore.setupTypeStore("TrustStore");
+ addStore.show(data[0], that.url);
});
});
}});
};
-
-
TrustStore.prototype.close = function() {
updater.remove( this.keyStoreUpdater );
};
@@ -89,9 +87,10 @@
function KeyStoreUpdater(containerNode, keyStoreObj, controller, url)
{
var that = this;
+ this.keyStoreDetailsContainer = query(".typeFieldsContainer", containerNode)[0];
function findNode(name) {
- return query("." + name + "Value", containerNode)[0];
+ return query("." + name , containerNode)[0];
}
function storeNodes(names)
@@ -102,12 +101,8 @@
}
storeNodes(["name",
- "path",
- "trustStoreType",
- "trustStoreState",
- "trustManagerFactoryAlgorithm",
- "certificateAlias",
- "peersOnly"
+ "type",
+ "state"
]);
this.query = url;
@@ -123,23 +118,26 @@
KeyStoreUpdater.prototype.updateHeader = function()
{
this.name.innerHTML = entities.encode(String(this.keyStoreData[ "name" ]));
- this.path.innerHTML = entities.encode(String(this.keyStoreData[ "path" ]));
- this.trustStoreType.innerHTML = entities.encode(String(this.keyStoreData[ "trustStoreType" ]));
- this.trustStoreState.innerHTML = entities.encode(String(this.keyStoreData[ "state" ]));
- this.trustManagerFactoryAlgorithm.innerHTML = entities.encode(String(this.keyStoreData[ "trustManagerFactoryAlgorithm" ]));
- this.peersOnly.innerHTML = "<input type='checkbox' disabled='disabled' "+(this.keyStoreData[ "peersOnly" ] ? "checked='checked'": "")+" />" ;
+ this.type.innerHTML = entities.encode(String(this.keyStoreData[ "type" ]));
+ this.state.innerHTML = entities.encode(String(this.keyStoreData[ "state" ]));
};
KeyStoreUpdater.prototype.update = function()
{
-
- var thisObj = this;
-
+ var that = this;
xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
- {
- thisObj.keyStoreData = data[0];
- thisObj.updateHeader();
- });
+ {
+ that.trustStoreData = data[0];
+ that.updateHeader();
+
+ require(["qpid/management/store/" + encodeURIComponent(that.trustStoreData.type.toLowerCase()) + "/show"],
+ function(DetailsUI)
+ {
+ that.details = new DetailsUI({containerNode:that.keyStoreDetailsContainer, parent: that});
+ that.details.update(that.trustStoreData);
+ }
+ );
+ });
};
TrustStore.prototype.deleteKeyStore = function() {
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js
index cdc7890..434e119 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js
@@ -93,6 +93,19 @@
that.stopButton = registry.byNode(query(".stopButton", containerNode)[0]);
that.startButton = registry.byNode(query(".startButton", containerNode)[0]);
that.editButton = registry.byNode(query(".editButton", containerNode)[0]);
+ that.downloadButton = registry.byNode(query(".downloadButton", containerNode)[0]);
+ that.downloadButton.on("click",
+ function(e)
+ {
+ var iframe = document.createElement('iframe');
+ iframe.id = "downloader_" + that.name;
+ document.body.appendChild(iframe);
+ var suggestedAttachmentName = encodeURIComponent(that.name + ".json");
+ iframe.src = "/api/latest/virtualhost/" + encodeURIComponent(that.modelObj.parent.name) + "/" + encodeURIComponent(that.name) + "?extractInitialConfig=true&contentDispositionAttachmentFilename=" + suggestedAttachmentName;
+ // It seems there is no way to remove this iframe in a manner that is cross browser compatible.
+ }
+ );
+
that.deleteButton = registry.byNode(query(".deleteButton", containerNode)[0]);
that.deleteButton.on("click",
function(e)
@@ -344,6 +357,7 @@
this.virtualHost.startButton.set("disabled", !this.vhostData.state || this.vhostData.state != "STOPPED");
this.virtualHost.stopButton.set("disabled", !this.vhostData.state || this.vhostData.state != "ACTIVE");
this.virtualHost.editButton.set("disabled", !this.vhostData.state || this.vhostData.state == "UNAVAILABLE");
+ this.virtualHost.downloadButton.set("disabled", !this.vhostData.state || this.vhostData.state != "ACTIVE");
this.virtualHost.deleteButton.set("disabled", !this.vhostData.state);
util.flattenStatistics( thisObj.vhostData );
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/aclfile/add.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/aclfile/add.js
new file mode 100644
index 0000000..e42dafb
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/aclfile/add.js
@@ -0,0 +1,122 @@
+/*
+ *
+ * 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.
+ *
+ */
+define(["dojo/dom","dojo/query","dijit/registry","qpid/common/util"],
+ function (dom, query, registry, util)
+ {
+ var addACLFileAccessControlProvider =
+ {
+ init: function()
+ {
+ // Readers are HTML5
+ this.reader = window.FileReader ? new FileReader() : undefined;
+ },
+ show: function(data)
+ {
+ var that=this;
+ util.parseHtmlIntoDiv(data.containerNode, "accesscontrolprovider/aclfile/add.html");
+
+ this.aclServerPath = registry.byId("addAccessControlProvider.serverPath");
+ this.aclUploadFields = dom.byId("addAccessControlProvider.uploadFields");
+ this.aclSelectedFileContainer = dom.byId("addAccessControlProvider.selectedFile");
+ this.aclSelectedFileStatusContainer = dom.byId("addAccessControlProvider.selectedFileStatus");
+ this.aclFile = registry.byId("addAccessControlProvider.file");
+ this.aclFileClearButton = registry.byId("addAccessControlProvider.fileClearButton");
+ this.aclFileOldBrowserWarning = dom.byId("addAccessControlProvider.oldBrowserWarning");
+
+ //Only submitted field
+ this.aclPath = registry.byId("addAccessControlProvider.path");
+
+ this.addButton = data.parent.addButton;
+
+ if (this.reader)
+ {
+ this.reader.onload = function(evt) {that._aclUploadFileComplete(evt);};
+ this.reader.onerror = function(ex) {console.error("Failed to load ACL file", ex);};
+ this.aclFile.on("change", function(selected){that._aclFileChanged(selected)});
+ this.aclFileClearButton.on("click", function(event){that._aclFileClearButtonClicked(event)});
+ }
+ else
+ {
+ // Fall back for IE8/9 which do not support FileReader
+ this.aclUploadFields.style.display = "none";
+ this.aclFileOldBrowserWarning.innerHTML = "File upload requires a more recent browser with HTML5 support";
+ this.aclFileOldBrowserWarning.className = this.aclFileOldBrowserWarning.className.replace("hidden", "");
+ }
+
+ this.aclServerPath.on("blur", function(){that._aclServerPathChanged()});
+ },
+ _aclFileChanged: function (evt)
+ {
+ // We only ever expect a single file
+ var file = this.aclFile.domNode.children[0].files[0];
+
+ this.addButton.setDisabled(true);
+ this.aclSelectedFileContainer.innerHTML = file.name;
+ this.aclSelectedFileStatusContainer.className = "loadingIcon";
+
+ console.log("Beginning to read ACL file " + file.name);
+ this.reader.readAsDataURL(file);
+ },
+ _aclUploadFileComplete: function(evt)
+ {
+ var reader = evt.target;
+ var result = reader.result;
+ console.log("ACL file read complete, contents " + result);
+ this.addButton.setDisabled(false);
+ this.aclSelectedFileStatusContainer.className = "loadedIcon";
+
+ this.aclServerPath.set("value", "");
+ this.aclServerPath.setDisabled(true);
+ this.aclServerPath.set("required", false);
+
+ this.aclFileClearButton.setDisabled(false);
+
+ this.aclPath.set("value", result);
+ },
+ _aclFileClearButtonClicked: function(event)
+ {
+ this.aclFile.reset();
+ this.aclSelectedFileStatusContainer.className = "";
+ this.aclSelectedFileContainer.innerHTML = "";
+ this.aclServerPath.set("required", true);
+ this.aclServerPath.setDisabled(false);
+ this.aclFileClearButton.setDisabled(true);
+
+ this.aclPath.set("value", "");
+ },
+ _aclServerPathChanged: function()
+ {
+ var serverPathValue = this.aclServerPath.get("value");
+ this.aclPath.set("value", serverPathValue);
+ }
+ };
+
+ try
+ {
+ addACLFileAccessControlProvider.init();
+ }
+ catch(e)
+ {
+ console.warn(e);
+ }
+ return addACLFileAccessControlProvider;
+ }
+);
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js
index ac0493b..38a6c8e 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js
@@ -26,8 +26,10 @@
"dojo/parser",
"dojo/_base/array",
"dojo/_base/event",
- 'dojo/_base/json',
+ 'dojo/json',
"qpid/common/util",
+ "qpid/common/metadata",
+ "dojo/text!addAccessControlProvider.html",
"dojo/store/Memory",
"dojox/validate/us",
"dojox/validate/web",
@@ -42,140 +44,124 @@
"dijit/layout/ContentPane",
"dojox/layout/TableContainer",
"dojo/domReady!"],
- function (lang, xhr, dom, construct, registry, parser, array, event, json, util) {
+ function (lang, xhr, dom, construct, registry, parser, array, event, json, util, metadata, template)
+ {
- var addAccessControlProvider = {};
+ var addAccessControlProvider =
+ {
+ init: function()
+ {
+ var that=this;
+ this.containerNode = construct.create("div", {innerHTML: template});
+ parser.parse(this.containerNode);
- addAccessControlProvider.show = function(accessControlProvider) {
- var fields = [{
- name: "name",
- createWidget: function(accessControlProvider) {
- return new dijit.form.ValidationTextBox({
- required: true,
- value: accessControlProvider.name,
- disabled: accessControlProvider.name ? true : false,
- label: "Name*:",
- regexp: "^[\x20-\x2e\x30-\x7F]{1,255}$",
- promptMessage: "Name of access control provider.",
- placeHolder: "name",
- name: "name"});
- }
- }, {
- name: "type",
- createWidget: function(accessControlProvider) {
+ this.accessControlProviderName = registry.byId("addAccessControlProvider.name");
+ this.accessControlProviderName.set("regExpGen", util.nameOrContextVarRegexp);
- var typeContainer = construct.create("div");
+ this.dialog = registry.byId("addAccessControlProvider");
+ this.addButton = registry.byId("addAccessControlProvider.addButton");
+ this.cancelButton = registry.byId("addAccessControlProvider.cancelButton");
+ this.cancelButton.on("click", function(e){that._cancel(e);});
+ this.addButton.on("click", function(e){that._add(e);});
- var typeListContainer = new dojox.layout.TableContainer({
- cols: 1,
- "labelWidth": "300",
- customClass: "formLabel",
- showLabels: true,
- orientation: "horiz"
- });
+ this.accessControlProviderTypeFieldsContainer = dom.byId("addAccessControlProvider.typeFields");
+ this.accessControlProviderForm = registry.byId("addAccessControlProvider.form");
+ this.accessControlProviderType = registry.byId("addAccessControlProvider.type");
+ this.supportedAccessControlProviderTypes = metadata.getTypesForCategory("AccessControlProvider");
+ this.supportedAccessControlProviderTypes.sort();
+ var accessControlProviderTypeStore = util.makeTypeStore(this.supportedAccessControlProviderTypes);
+ this.accessControlProviderType.set("store", accessControlProviderTypeStore);
+ this.accessControlProviderType.on("change", function(type){that._accessControlProviderTypeChanged(type);});
+ },
+ show: function(effectiveData)
+ {
+ this.accessControlProviderForm.reset();
+ this.dialog.show();
+ },
+ _cancel: function(e)
+ {
+ event.stop(e);
+ if (this.reader)
+ {
+ this.reader.abort();
+ }
+ this.dialog.hide();
+ },
+ _add: function(e)
+ {
+ event.stop(e);
+ this._submit();
+ },
+ _submit: function()
+ {
+ if (this.accessControlProviderForm.validate())
+ {
+ var success = false,failureReason=null;
- typeContainer.appendChild(typeListContainer.domNode);
+ var accessControlProviderData = util.getFormWidgetValues(this.accessControlProviderForm, this.initialData);
+ var encodedAccessControlProviderName = encodeURIComponent(this.accessControlProviderName.value);
- var providers = [];
- var fieldSetContainers = {};
- xhr.get({
- url: "service/helper?action=ListAccessControlProviderAttributes",
- handleAs: "json",
- sync: true
- }).then(
- function(data) {
- var providerIndex = 0;
+ xhr.put(
+ {
+ url: "api/latest/accesscontrolprovider/" + encodedAccessControlProviderName,
+ sync: true,
+ handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ putData: json.stringify(accessControlProviderData),
+ load: function(x) {success = true; },
+ error: function(error) {success = false; failureReason = error;}
+ });
- for (var providerType in data) {
- if (data.hasOwnProperty(providerType)) {
- providers[providerIndex++] = {id: providerType, name: providerType};
-
- var attributes = data[providerType].attributes;
- var descriptions = data[providerType].descriptions;
-
- var layout = new dojox.layout.TableContainer( {
- cols: 1,
- "labelWidth": "300",
- customClass: "formLabel",
- showLabels: true,
- orientation: "horiz"
- });
-
- for(var i=0; i < attributes.length; i++) {
- if ("type" == attributes[i])
- {
- continue;
- }
- var labelValue = attributes[i];
- if (descriptions && descriptions[attributes[i]])
- {
- labelValue = descriptions[attributes[i]];
- }
- var text = new dijit.form.TextBox({
- label: labelValue + ":",
- name: attributes[i]
- });
- layout.addChild(text);
- }
-
- typeContainer.appendChild(layout.domNode);
- fieldSetContainers[providerType] = layout;
- }
- }
- });
-
- var providersStore = new dojo.store.Memory({ data: providers });
-
- var typeList = new dijit.form.FilteringSelect({
- required: true,
- value: accessControlProvider.type,
- store: providersStore,
- label: "Type*:",
- name: "type"});
-
- typeListContainer.addChild(typeList);
-
- var onChangeHandler = function onChangeHandler(newValue){
- for (var i in fieldSetContainers) {
- var container = fieldSetContainers[i];
- var descendants = container.getChildren();
- for(var i in descendants){
- var descendant = descendants[i];
- var propName = descendant.name;
- if (propName) {
- descendant.set("disabled", true);
- }
+ if (success == true)
+ {
+ this.dialog.hide();
}
- container.domNode.style.display = "none";
- }
- var container = fieldSetContainers[newValue];
- if (container)
- {
- container.domNode.style.display = "block";
- var descendants = container.getChildren();
- for(var i in descendants){
- var descendant = descendants[i];
- var propName = descendant.name;
- if (propName) {
- descendant.set("disabled", false);
- }
+ else
+ {
+ util.xhrErrorHandler(failureReason);
}
- }
- };
- typeList.on("change", onChangeHandler);
- onChangeHandler(typeList.value);
- return new dijit.layout.ContentPane({content: typeContainer, style:{padding: 0}});
- }
- }];
+ }
+ else
+ {
+ alert('Form contains invalid data. Please correct first');
+ }
+ },
+ _accessControlProviderTypeChanged: function(type)
+ {
+ this._typeChanged(type, this.accessControlProviderTypeFieldsContainer, "qpid/management/accesscontrolprovider/", "AccessControlProvider" );
+ },
+ _typeChanged: function(type, typeFieldsContainer, baseUrl, category )
+ {
+ var widgets = registry.findWidgets(typeFieldsContainer);
+ array.forEach(widgets, function(item) { item.destroyRecursive();});
+ construct.empty(typeFieldsContainer);
- util.showSetAttributesDialog(
- fields,
- accessControlProvider ? accessControlProvider : {},
- "api/latest/accesscontrolprovider" + (name ? "/" + encodeURIComponent(name.name) : ""),
- accessControlProvider ? "Edit access control provider - " + accessControlProvider.name : "Add access control provider",
- "AccessControlProvider",
- accessControlProvider && accessControlProvider.type ? accessControlProvider.type : "AclFile",
- accessControlProvider ? false : true);
+ if (type)
+ {
+ var that = this;
+ require([ baseUrl + type.toLowerCase() + "/add"], function(typeUI)
+ {
+ try
+ {
+ typeUI.show({containerNode:typeFieldsContainer, parent: that, data: that.initialData, effectiveData: that.effectiveData});
+ util.applyMetadataToWidgets(typeFieldsContainer, category, type);
+ }
+ catch(e)
+ {
+ console.warn(e);
+ }
+ });
+ }
+ }
};
+
+ try
+ {
+ addAccessControlProvider.init();
+ }
+ catch(e)
+ {
+ console.warn(e);
+ }
return addAccessControlProvider;
- });
\ No newline at end of file
+ });
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addKeystore.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addKeystore.js
deleted file mode 100644
index e7e79e7..0000000
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addKeystore.js
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- *
- * 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.
- *
- */
-define(["dojo/_base/lang",
- "dojo/_base/xhr",
- "dojo/dom",
- "dojo/dom-construct",
- "dijit/registry",
- "dojo/parser",
- "dojo/_base/array",
- "dojo/_base/event",
- 'dojo/_base/json',
- "qpid/common/util",
- "dojo/store/Memory",
- "dojox/validate/us",
- "dojox/validate/web",
- "dijit/Dialog",
- "dijit/form/CheckBox",
- "dijit/form/Textarea",
- "dijit/form/ComboBox",
- "dijit/form/TextBox",
- "dijit/form/ValidationTextBox",
- "dijit/form/Button",
- "dijit/form/Form",
- "dijit/TitlePane",
- "dojox/layout/TableContainer",
- "dojo/domReady!"],
- function (lang, xhr, dom, construct, registry, parser, array, event, json, util) {
-
- var addKeystore = { };
-
- addKeystore.createWidgetFactories = function(isKeystore)
- {
- var fields = [{
- name: "name",
- createWidget: function(keystore) {
- return new dijit.form.ValidationTextBox({
- required: true,
- value: keystore.name,
- disabled: keystore.name ? true : false,
- label: "Name:",
- regExpGen: util.nameOrContextVarRegexp,
- promptMessage: "Name of keystore. Used to refer to the keystore from other objects within the Broker.",
- placeHolder: "name",
- name: "name"});
- }
- }, {
- name: "path",
- createWidget: function(keystore) {
- return new dijit.form.ValidationTextBox({
- required: true,
- value: keystore.path,
- label: "Path to keystore:",
- promptMessage: "File system location to the keystore file",
- placeHolder: "path/to/keystore",
- name: "path"});
- }
- }, {
- name: "password",
- requiredFor: "path",
- createWidget: function(keystore) {
- return new dijit.form.ValidationTextBox({
- required: false,
- label: "Keystore password:",
- promptMessage: "Password used to open the keystore",
- name: "password",
- placeHolder: keystore["password"] ? keystore["password"] : ""
- });
- }
- }];
- if (!isKeystore)
- {
- fields.push({
- name: "peersOnly",
- createWidget: function(keystore) {
- return new dijit.form.CheckBox({
- required: false,
- checked: keystore && keystore.peersOnly,
- label: "Peers only:",
- name: "peersOnly"});
- }
- });
- }
- fields.push({
- name: "Options",
-
- createWidget: function(keystore) {
- var optionalFieldContainer = new dojox.layout.TableContainer({
- cols: 1,
- "labelWidth": "300",
- showLabels: true,
- orientation: "horiz",
- customClass: "formLabel"
- });
- if (isKeystore)
- {
- optionalFieldContainer.addChild(new dijit.form.ValidationTextBox({
- required: false,
- value: keystore.certificateAlias,
- label: "Keystore certificate alias:",
- name: "certificateAlias",
- placeHolder: "alias",
- promptMessage: "Used to identify one certificate in a store that has many"}));
-
- optionalFieldContainer.addChild( new dijit.form.ValidationTextBox({
- required: false,
- value: keystore.keyManagerFactoryAlgorithm,
- label: "Key manager factory algorithm:",
- placeHolder: "algorithm name",
- promptMessage: "Name of the key manager algorithm known to Java",
- name: "keyManagerFactoryAlgorithm"}));
- }
- else
- {
- optionalFieldContainer.addChild( new dijit.form.ValidationTextBox({
- required: false,
- value: keystore.trustManagerFactoryAlgorithm,
- label: "Trust manager factory algorithm:",
- placeHolder: "algorithm name",
- promptMessage: "Name of the trust manager algorithm known to Java",
- name: "trustManagerFactoryAlgorithm"}));
- }
- optionalFieldContainer.addChild(new dijit.form.ValidationTextBox({
- required: false,
- value: isKeystore ? keystore.keyStoreType : keystore.trustStoreType,
- label: "Key store type:",
- placeHolder: "store type",
- promptMessage: "Name of the store type known to Java",
- name: isKeystore ? "keyStoreType" : "trustStoreType"}));
-
- var panel = new dijit.TitlePane({title: "Optional Attributes", content: optionalFieldContainer.domNode, open: false});
-
- return panel;
- }
- });
- return fields;
- }
-
- addKeystore.showKeystoreDialog = function(keystore, putURL) {
- var keystoreAttributeWidgetFactories = addKeystore.createWidgetFactories(true);
-
- util.showSetAttributesDialog(
- keystoreAttributeWidgetFactories,
- keystore ? keystore : {},
- keystore ? putURL : "api/latest/keystore",
- keystore ? "Edit keystore - " + keystore.name : "Add keystore",
- "KeyStore",
- keystore && keystore.type ? keystore.type : "FileKeyStore", // GET?actuals=true doesn't get type for objects of the default type for the category
- keystore ? false : true);
- };
-
- addKeystore.showTruststoreDialog = function(truststore, putURL) {
- var truststoreAttributeWidgetFactories = addKeystore.createWidgetFactories(false);
- util.showSetAttributesDialog(
- truststoreAttributeWidgetFactories,
- truststore ? truststore : {},
- truststore ? putURL : "api/latest/truststore",
- truststore ? "Edit truststore - " + truststore.name : "Add truststore",
- "TrustStore",
- truststore && truststore.type ? truststore.type : "FileTrustStore",
- truststore ? false : true);
- };
- return addKeystore;
- });
\ No newline at end of file
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addStore.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addStore.js
new file mode 100644
index 0000000..98068f2
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addStore.js
@@ -0,0 +1,211 @@
+/*
+ *
+ * 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.
+ *
+ */
+define(["dojo/_base/lang",
+ "dojo/_base/xhr",
+ "dojo/dom",
+ "dojo/dom-construct",
+ "dijit/registry",
+ "dojo/parser",
+ "dojo/store/Memory",
+ "dojo/_base/array",
+ "dojo/_base/event",
+ 'dojo/json',
+ "qpid/common/util",
+ "qpid/common/metadata",
+ "dojo/text!addStore.html",
+ "dojo/store/Memory",
+ "dojox/validate/us",
+ "dojox/validate/web",
+ "dijit/Dialog",
+ "dijit/form/CheckBox",
+ "dijit/form/Textarea",
+ "dijit/form/ComboBox",
+ "dijit/form/TextBox",
+ "dijit/form/ValidationTextBox",
+ "dijit/form/Button",
+ "dijit/form/Form",
+ "dijit/layout/ContentPane",
+ "dojox/layout/TableContainer",
+ "dojo/domReady!"],
+ function (lang, xhr, dom, construct, registry, parser, memory, array, event, json, util, metadata, template)
+ {
+ var addStore =
+ {
+ init: function()
+ {
+ var that=this;
+ this.containerNode = construct.create("div", {innerHTML: template});
+ parser.parse(this.containerNode);
+
+ this.storeName = registry.byId("addStore.name");
+ this.storeName.set("regExpGen", util.nameOrContextVarRegexp);
+
+ this.dialog = registry.byId("addStore");
+ this.addButton = registry.byId("addStore.addButton");
+ this.cancelButton = registry.byId("addStore.cancelButton");
+ this.cancelButton.on("click", function(e){that._cancel(e);});
+ this.addButton.on("click", function(e){that._add(e);});
+
+ this.storeTypeFieldsContainer = dom.byId("addStore.typeFields");
+ this.storeForm = registry.byId("addStore.form");
+
+ this.storeType = registry.byId("addStore.type");
+ this.storeType.on("change", function(type){that._storeTypeChanged(type);});
+ },
+ setupTypeStore: function(category)
+ {
+ this.category = category;
+ var storeTypeSupportedTypes = metadata.getTypesForCategory(category);
+ storeTypeSupportedTypes.sort();
+ var storeTypeStore = util.makeTypeStore(storeTypeSupportedTypes);
+ this.storeType.set("store", storeTypeStore);
+ },
+ show: function(effectiveData)
+ {
+ this.storeForm.reset();
+
+ if (effectiveData)
+ {
+ this.effectiveData = effectiveData;
+ this._destroyTypeFields(this.containerNode);
+ this._initFields(effectiveData);
+ }
+ this.storeName.set("disabled", effectiveData == null ? false : true);
+ this.storeType.set("disabled", effectiveData == null ? false : true);
+ this.dialog.show();
+ },
+ _initFields:function(data)
+ {
+ var type = data["type"];
+ var attributes = metadata.getMetaData(this.category, type).attributes;
+ for(var name in attributes)
+ {
+ var widget = registry.byId("addStore."+name);
+ if (widget)
+ {
+ widget.set("value", data[name]);
+ }
+ }
+ },
+ _cancel: function(e)
+ {
+ event.stop(e);
+ if (this.reader)
+ {
+ this.reader.abort();
+ }
+ this.dialog.hide();
+ },
+ _add: function(e)
+ {
+ event.stop(e);
+ this._submit();
+ },
+ _submit: function()
+ {
+ if (this.storeForm.validate())
+ {
+ var success = false,failureReason=null;
+
+ var storeData = util.getFormWidgetValues(this.storeForm, this.initialData);
+ var encodedStoreName = encodeURIComponent(this.storeName.value);
+ var encodedCategory = encodeURIComponent(this.category.toLowerCase());
+ var jsonString = json.stringify(storeData);
+
+ try {
+ xhr.put(
+ {
+ url: "api/latest/" + encodedCategory + "/" + encodedStoreName,
+ sync: true,
+ handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ putData: jsonString,
+ load: function(x) {success = true; },
+ error: function(error) {success = false; failureReason = error;}
+ });
+ }
+ catch (e)
+ {
+ console.warn(e);
+ }
+
+ if (success == true)
+ {
+ this.dialog.hide();
+ }
+ else
+ {
+ util.xhrErrorHandler(failureReason);
+ }
+ }
+ else
+ {
+ alert('Form contains invalid data. Please correct first');
+ }
+ },
+ _storeTypeChanged: function(type)
+ {
+ this._typeChanged(type, this.storeTypeFieldsContainer, "qpid/management/store/", this.category );
+ },
+ _destroyTypeFields: function(typeFieldsContainer)
+ {
+ var widgets = registry.findWidgets(typeFieldsContainer);
+ array.forEach(widgets, function(item) { item.destroyRecursive();});
+ construct.empty(typeFieldsContainer);
+ },
+ _typeChanged: function(type, typeFieldsContainer, baseUrl, category )
+ {
+ this._destroyTypeFields(typeFieldsContainer);
+
+ if (type)
+ {
+ var that = this;
+ require([ baseUrl + type.toLowerCase() + "/add"], function(typeUI)
+ {
+ try
+ {
+ typeUI.show({containerNode:typeFieldsContainer, parent: that, data: that.initialData, effectiveData: that.effectiveData});
+ util.applyMetadataToWidgets(typeFieldsContainer, category, type);
+ if (that.effectiveData)
+ {
+ typeUI.update(that.effectiveData);
+ that.effectiveData = undefined;
+ }
+ }
+ catch(e)
+ {
+ console.warn(e);
+ }
+ });
+ }
+ }
+ };
+
+ try
+ {
+ addStore.init();
+ }
+ catch(e)
+ {
+ console.warn(e);
+ }
+ return addStore;
+ });
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js
index 0a18a89..f379361 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js
@@ -44,6 +44,7 @@
"dijit/form/Form",
"dijit/form/CheckBox",
"dijit/form/RadioButton",
+ "dojox/form/Uploader",
"dojox/validate/us",
"dojox/validate/web",
"dojo/domReady!"],
@@ -61,6 +62,9 @@
var virtualHostNodeName = registry.byId("addVirtualHostNode.nodeName");
virtualHostNodeName.set("regExpGen", util.nameOrContextVarRegexp);
+ // Readers are HTML5
+ this.reader = window.FileReader ? new FileReader() : undefined;
+
this.dialog = registry.byId("addVirtualHostNodeAndVirtualHost");
this.addButton = registry.byId("addVirtualHostNodeAndVirtualHost.addButton");
this.cancelButton = registry.byId("addVirtualHostNodeAndVirtualHost.cancelButton");
@@ -68,34 +72,51 @@
this.addButton.on("click", function(e){that._add(e);});
this.virtualHostNodeTypeFieldsContainer = dom.byId("addVirtualHostNode.typeFields");
+ this.virtualHostNodeSelectedFileContainer = dom.byId("addVirtualHostNode.selectedFile");
+ this.virtualHostNodeSelectedFileStatusContainer = dom.byId("addVirtualHostNode.selectedFileStatus");
+ this.virtualHostNodeUploadFields = dom.byId("addVirtualHostNode.uploadFields");
+ this.virtualHostNodeFileFields = dom.byId("addVirtualHostNode.fileFields");
+
this.virtualHostNodeForm = registry.byId("addVirtualHostNode.form");
this.virtualHostNodeType = registry.byId("addVirtualHostNode.type");
+ this.virtualHostNodeFileCheck = registry.byId("addVirtualHostNode.upload");
+ this.virtualHostNodeFile = registry.byId("addVirtualHostNode.file");
+
this.virtualHostNodeType.set("disabled", true);
this.virtualHostTypeFieldsContainer = dom.byId("addVirtualHost.typeFields");
this.virtualHostForm = registry.byId("addVirtualHost.form");
this.virtualHostType = registry.byId("addVirtualHost.type");
+
this.virtualHostType.set("disabled", true);
- this.supportedVirtualHostNodeTypes = metadata.getTypesForCategory("VirtualHostNode");
- this.supportedVirtualHostNodeTypes.sort();
- this.supportedVirtualHostTypes = metadata.getTypesForCategory("VirtualHost");
- this.supportedVirtualHostTypes.sort();
+ var supportedVirtualHostNodeTypes = metadata.getTypesForCategory("VirtualHostNode");
+ supportedVirtualHostNodeTypes.sort();
- //VH Type BDB_HA_REPLICA is not user creatable. This is only needed until we have model meta data available.
- this.supportedVirtualHostTypes = array.filter(this.supportedVirtualHostTypes, function(item){
- return item != "BDB_HA_REPLICA" && item != "BDB_HA";
- });
-
- var virtualHostNodeTypeStore = util.makeTypeStore(this.supportedVirtualHostNodeTypes);
+ var virtualHostNodeTypeStore = util.makeTypeStore(supportedVirtualHostNodeTypes);
this.virtualHostNodeType.set("store", virtualHostNodeTypeStore);
this.virtualHostNodeType.set("disabled", false);
this.virtualHostNodeType.on("change", function(type){that._vhnTypeChanged(type, that.virtualHostNodeTypeFieldsContainer, "qpid/management/virtualhostnode/");});
- this.virtualHostTypeStore = util.makeTypeStore(this.supportedVirtualHostTypes);
- this.virtualHostType.set("store", this.virtualHostTypeStore);
- this.virtualHostType.set("disabled", false);
+ this.virtualHostType.set("disabled", true);
this.virtualHostType.on("change", function(type){that._vhTypeChanged(type, that.virtualHostTypeFieldsContainer, "qpid/management/virtualhost/");});
+
+ if (this.reader)
+ {
+ this.reader.onload = function(evt) {that._vhnUploadFileComplete(evt);};
+ this.reader.onerror = function(ex) {console.error("Failed to load JSON file", ex);};
+ this.virtualHostNodeFile.on("change", function(selected){that._vhnFileChanged(selected)});
+ this.virtualHostNodeFileCheck.on("change", function(selected){that._vhnFileFlagChanged(selected)});
+ }
+ else
+ {
+ // Fall back for IE8/9 which do not support FileReader
+ this.virtualHostNodeFileCheck.set("disabled", "disabled");
+ this.virtualHostNodeFileCheck.set("title", "Requires a more recent browser with HTML5 support");
+ this.virtualHostNodeFileFields.style.display = "none";
+ }
+
+ this.virtualHostNodeUploadFields.style.display = "none";
},
show: function()
{
@@ -161,8 +182,29 @@
},
_vhnTypeChanged: function (type, typeFieldsContainer, urlStem)
{
- this._processDropDownsForBdbHa(type);
- this._processDropDownsForJson(type);
+ var validChildTypes = metadata.validChildTypes("VirtualHostNode", type, "VirtualHost");
+ validChildTypes.sort();
+
+ var virtualHostTypeStore = util.makeTypeStore( validChildTypes );
+
+ this.virtualHostType.set("store", virtualHostTypeStore);
+ this.virtualHostType.set("disabled", validChildTypes.length <= 1);
+ if (validChildTypes.length == 1)
+ {
+ this.virtualHostType.set("value", validChildTypes[0]);
+ }
+ else
+ {
+ this.virtualHostType.reset();
+ }
+
+ var vhnTypeSelected = !(type == '');
+ this.virtualHostNodeUploadFields.style.display = vhnTypeSelected ? "block" : "none";
+
+ if (!vhnTypeSelected)
+ {
+ this._vhnFileFlagChanged(false);
+ }
this._typeChanged(type, typeFieldsContainer, urlStem, "VirtualHostNode");
},
@@ -203,52 +245,43 @@
);
}
},
- _processDropDownsForBdbHa: function (type)
+ _vhnFileFlagChanged: function (selected)
{
- if (type == "BDB_HA")
- {
- this.virtualHostType.set("disabled", true);
- if (!this.virtualHostTypeStore.get("BDB_HA"))
- {
- this.virtualHostTypeStore.add({id: "BDB_HA", name: "BDB_HA"});
- }
- this.virtualHostType.set("value", "BDB_HA");
- }
- else
- {
- if (this.virtualHostTypeStore.get("BDB_HA"))
- {
- this.virtualHostTypeStore.remove("BDB_HA");
- }
- this.virtualHostType.set("value", "");
-
- this.virtualHostType.set("disabled", false);
- }
+ this.virtualHostForm.domNode.style.display = selected ? "none" : "block";
+ this.virtualHostNodeFileFields.style.display = selected ? "block" : "none";
+ this.virtualHostType.set("required", !selected);
+ this.virtualHostNodeFile.reset();
+ this.virtualHostInitialConfiguration = undefined;
+ this.virtualHostNodeSelectedFileContainer.innerHTML = "";
+ this.virtualHostNodeSelectedFileStatusContainer.className = "";
},
- _processDropDownsForJson: function (type)
+ _vhnFileChanged: function (evt)
{
- if (type == "JSON")
- {
- if (this.virtualHostType.value == "ProvidedStore")
- {
- this.virtualHostType.set("value", "");
- }
+ // We only ever expect a single file
+ var file = this.virtualHostNodeFile.domNode.children[0].files[0];
- if (this.virtualHostTypeStore.get("ProvidedStore"))
- {
- this.virtualHostTypeStore.remove("ProvidedStore");
- }
- }
- else
- {
- if (!this.virtualHostTypeStore.get("ProvidedStore"))
- {
- this.virtualHostTypeStore.add({id: "ProvidedStore", name: "ProvidedStore"});
- }
- }
+ this.addButton.set("disabled", true);
+ this.virtualHostNodeSelectedFileContainer.innerHTML = file.name;
+ this.virtualHostNodeSelectedFileStatusContainer.className = "loadingIcon";
+
+ console.log("Beginning to read file " + file.name);
+ this.reader.readAsDataURL(file);
+ },
+ _vhnUploadFileComplete: function(evt)
+ {
+ var reader = evt.target;
+ var result = reader.result;
+ console.log("File read complete, contents " + result);
+ this.virtualHostInitialConfiguration = result;
+ this.addButton.set("disabled", false);
+ this.virtualHostNodeSelectedFileStatusContainer.className = "loadedIcon";
},
_cancel: function(e)
{
+ if (this.reader)
+ {
+ this.reader.abort();
+ }
this.dialog.hide();
},
_add: function(e)
@@ -258,16 +291,32 @@
},
_submit: function()
{
- if(this.virtualHostNodeForm.validate() && this.virtualHostForm.validate())
- {
- var success = false,failureReason=null;
- var virtualHostNodeData = this._getValues(this.virtualHostNodeForm);
+ var uploadVHConfig = this.virtualHostNodeFileCheck.get("checked");
+ var virtualHostNodeData = undefined;
+
+ if (uploadVHConfig && this.virtualHostNodeFile.getFileList().length > 0 && this.virtualHostNodeForm.validate())
+ {
+ // VH config is being uploaded
+ virtualHostNodeData = this._getValues(this.virtualHostNodeForm);
var virtualHostNodeContext = this.virtualHostNodeContext.get("value");
if (virtualHostNodeContext)
{
virtualHostNodeData["context"] = virtualHostNodeContext;
}
+
+ // Add the loaded virtualhost configuration
+ virtualHostNodeData["virtualHostInitialConfiguration"] = this.virtualHostInitialConfiguration;
+ }
+ else if (!uploadVHConfig && this.virtualHostNodeForm.validate() && this.virtualHostForm.validate())
+ {
+ virtualHostNodeData = this._getValues(this.virtualHostNodeForm);
+ var virtualHostNodeContext = this.virtualHostNodeContext.get("value");
+ if (virtualHostNodeContext)
+ {
+ virtualHostNodeData["context"] = virtualHostNodeContext;
+ }
+
var virtualHostData = this._getValues(this.virtualHostForm);
var virtualHostContext = this.virtualHostContext.get("value");
if (virtualHostContext)
@@ -278,48 +327,35 @@
//Default the VH name to be the same as the VHN name.
virtualHostData["name"] = virtualHostNodeData["name"];
- var encodedVirtualHostNodeName = encodeURIComponent(virtualHostNodeData.name);
- xhr.put({
- url: "api/latest/virtualhostnode/" + encodedVirtualHostNodeName,
- sync: true,
- handleAs: "json",
- headers: { "Content-Type": "application/json"},
- putData: json.stringify(virtualHostNodeData),
- load: function(x) {success = true; },
- error: function(error) {success = false; failureReason = error;}
- });
+ virtualHostNodeData["virtualHostInitialConfiguration"] = json.stringify(virtualHostData)
- if(success === true && virtualHostNodeData["type"] != "BDB_HA")
- {
- var encodedVirtualHostName = encodeURIComponent(virtualHostData.name);
- xhr.put({
- url: "api/latest/virtualhost/" + encodedVirtualHostNodeName + "/" + encodedVirtualHostName,
- sync: true,
- handleAs: "json",
- headers: { "Content-Type": "application/json"},
- putData: json.stringify(virtualHostData),
- load: function (x) {
- success = true;
- },
- error: function (error) {
- success = false;
- failureReason = error;
- }
- });
- }
-
- if (success == true)
- {
- this.dialog.hide();
- }
- else
- {
- util.xhrErrorHandler(failureReason);
- }
}
else
{
- alert('Form contains invalid data. Please correct first');
+ alert('Form contains invalid data. Please correct first');
+ return;
+ }
+
+ var success = false,failureReason=null;
+
+ var encodedVirtualHostNodeName = encodeURIComponent(virtualHostNodeData.name);
+ xhr.put({
+ url: "api/latest/virtualhostnode/" + encodedVirtualHostNodeName,
+ sync: true,
+ handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ putData: json.stringify(virtualHostNodeData),
+ load: function(x) {success = true; },
+ error: function(error) {success = false; failureReason = error;}
+ });
+
+ if (success == true)
+ {
+ this.dialog.hide();
+ }
+ else
+ {
+ util.xhrErrorHandler(failureReason);
}
},
_getValues: function (form)
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/filekeystore/add.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/filekeystore/add.js
new file mode 100644
index 0000000..b158b9e
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/filekeystore/add.js
@@ -0,0 +1,152 @@
+/*
+ *
+ * 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.
+ *
+ */
+define(["dojo/dom","dojo/query", "dojo/_base/array", "dijit/registry","qpid/common/util", "qpid/common/metadata"],
+ function (dom, query, array, registry, util, metadata)
+ {
+ var addKeyStore =
+ {
+ init: function()
+ {
+ // Readers are HTML5
+ this.reader = window.FileReader ? new FileReader() : undefined;
+ },
+ show: function(data)
+ {
+ var that=this;
+ util.parseHtmlIntoDiv(data.containerNode, "store/filekeystore/add.html");
+
+ this.containerNode = data.containerNode;
+ this.keyStoreServerPath = registry.byId("addStore.serverPath");
+ this.keyStoreUploadFields = dom.byId("addStore.uploadFields");
+ this.keyStoreSelectedFileContainer = dom.byId("addStore.selectedFile");
+ this.keyStoreSelectedFileStatusContainer = dom.byId("addStore.selectedFileStatus");
+ this.keyStoreFile = registry.byId("addStore.file");
+ this.keyStoreFileClearButton = registry.byId("addStore.fileClearButton");
+ this.keyStoreOldBrowserWarning = dom.byId("addStore.oldBrowserWarning");
+
+ //Only submitted field
+ this.keyStorePath = registry.byId("addStore.path");
+
+ this.addButton = data.parent.addButton;
+
+ if (this.reader)
+ {
+ this.reader.onload = function(evt) {that._keyStoreUploadFileComplete(evt);};
+ this.reader.onerror = function(ex) {console.error("Failed to load key store file", ex);};
+ this.keyStoreFile.on("change", function(selected){that._keyStoreFileChanged(selected)});
+ this.keyStoreFileClearButton.on("click", function(event){that._keyStoreFileClearButtonClicked(event)});
+ }
+ else
+ {
+ // Fall back for IE8/9 which do not support FileReader
+ this.keyStoreUploadFields.style.display = "none";
+ this.keyStoreOldBrowserWarning.innerHTML = "File upload requires a more recent browser with HTML5 support";
+ this.keyStoreOldBrowserWarning.className = this.keyStoreOldBrowserWarning.className.replace("hidden", "");
+ }
+
+ this.keyStoreServerPath.on("blur", function(){that._keyStoreServerPathChanged()});
+ },
+ _keyStoreFileChanged: function (evt)
+ {
+ // We only ever expect a single file
+ var file = this.keyStoreFile.domNode.children[0].files[0];
+
+ this.addButton.setDisabled(true);
+ this.keyStoreSelectedFileContainer.innerHTML = file.name;
+ this.keyStoreSelectedFileStatusContainer.className = "loadingIcon";
+
+ console.log("Beginning to read key store file " + file.name);
+ this.reader.readAsDataURL(file);
+ },
+ _keyStoreUploadFileComplete: function(evt)
+ {
+ var reader = evt.target;
+ var result = reader.result;
+ console.log("Key store file read complete, contents " + result);
+ this.addButton.setDisabled(false);
+ this.keyStoreSelectedFileStatusContainer.className = "loadedIcon";
+
+ this.keyStoreServerPath.set("value", "");
+ this.keyStoreServerPath.setDisabled(true);
+ this.keyStoreServerPath.set("required", false);
+
+ this.keyStoreFileClearButton.setDisabled(false);
+
+ this.keyStorePath.set("value", result);
+ },
+ _keyStoreFileClearButtonClicked: function(event)
+ {
+ this.keyStoreFile.reset();
+ this.keyStoreSelectedFileStatusContainer.className = "";
+ this.keyStoreSelectedFileContainer.innerHTML = "";
+ this.keyStoreServerPath.set("required", true);
+ this.keyStoreServerPath.setDisabled(false);
+ this.keyStoreFileClearButton.setDisabled(true);
+
+ this.keyStorePath.set("value", "");
+ },
+ _keyStoreServerPathChanged: function()
+ {
+ var serverPathValue = this.keyStoreServerPath.get("value");
+ this.keyStorePath.set("value", serverPathValue);
+ },
+ update: function(effectiveData)
+ {
+ var attributes = metadata.getMetaData("KeyStore", "FileKeyStore").attributes;
+ var widgets = registry.findWidgets(this.containerNode);
+ array.forEach(widgets, function(item)
+ {
+ var name = item.id.replace("addStore.","");
+ if (name in attributes && item.type != "password")
+ {
+ item.set("value", effectiveData[name]);
+ }
+ });
+
+ var keyStorePathValue = effectiveData["path"];
+ var isDataUrl = keyStorePathValue.indexOf("data:") == 0;
+
+ if (isDataUrl)
+ {
+ this.keyStoreSelectedFileStatusContainer.className = "loadedIcon";
+ this.keyStoreSelectedFileContainer.innerHTML = "uploaded.jks";
+ this.keyStoreServerPath.setDisabled(true);
+ this.keyStoreServerPath.set("required", false);
+ this.keyStoreFileClearButton.setDisabled(false);
+ }
+ else
+ {
+ this.keyStoreServerPath.set("value", keyStorePathValue);
+ }
+ }
+ };
+
+ try
+ {
+ addKeyStore.init();
+ }
+ catch(e)
+ {
+ console.warn(e);
+ }
+ return addKeyStore;
+ }
+);
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/filekeystore/show.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/filekeystore/show.js
new file mode 100644
index 0000000..fbe2bbc
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/filekeystore/show.js
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+define(["qpid/common/util", "qpid/common/metadata", "dojo/domReady!"],
+ function (util, metadata)
+ {
+
+ function FileKeyStoreProvider(data)
+ {
+ this.fields = [];
+ var attributes = metadata.getMetaData("KeyStore", "FileKeyStore").attributes;
+ for(var name in attributes)
+ {
+ this.fields.push(name);
+ }
+ util.buildUI(data.containerNode, data.parent, "store/filekeystore/show.html", this.fields, this);
+ }
+
+ FileKeyStoreProvider.prototype.update = function(data)
+ {
+ util.updateUI(data, this.fields, this);
+ }
+
+ return FileKeyStoreProvider;
+ }
+);
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/filetruststore/add.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/filetruststore/add.js
new file mode 100644
index 0000000..9d113a9
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/filetruststore/add.js
@@ -0,0 +1,152 @@
+/*
+ *
+ * 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.
+ *
+ */
+define(["dojo/dom","dojo/query", "dojo/_base/array", "dijit/registry","qpid/common/util", "qpid/common/metadata"],
+ function (dom, query, array, registry, util, metadata)
+ {
+ var addTrustStore =
+ {
+ init: function()
+ {
+ // Readers are HTML5
+ this.reader = window.FileReader ? new FileReader() : undefined;
+ },
+ show: function(data)
+ {
+ var that=this;
+ util.parseHtmlIntoDiv(data.containerNode, "store/filetruststore/add.html");
+
+ this.containerNode = data.containerNode;
+ this.keyStoreServerPath = registry.byId("addStore.serverPath");
+ this.keyStoreUploadFields = dom.byId("addStore.uploadFields");
+ this.keyStoreSelectedFileContainer = dom.byId("addStore.selectedFile");
+ this.keyStoreSelectedFileStatusContainer = dom.byId("addStore.selectedFileStatus");
+ this.keyStoreFile = registry.byId("addStore.file");
+ this.keyStoreFileClearButton = registry.byId("addStore.fileClearButton");
+ this.keyStoreOldBrowserWarning = dom.byId("addStore.oldBrowserWarning");
+
+ //Only submitted field
+ this.keyStorePath = registry.byId("addStore.path");
+
+ this.addButton = data.parent.addButton;
+
+ if (this.reader)
+ {
+ this.reader.onload = function(evt) {that._keyStoreUploadFileComplete(evt);};
+ this.reader.onerror = function(ex) {console.error("Failed to load trust store file", ex);};
+ this.keyStoreFile.on("change", function(selected){that._keyStoreFileChanged(selected)});
+ this.keyStoreFileClearButton.on("click", function(event){that._keyStoreFileClearButtonClicked(event)});
+ }
+ else
+ {
+ // Fall back for IE8/9 which do not support FileReader
+ this.keyStoreUploadFields.style.display = "none";
+ this.keyStoreOldBrowserWarning.innerHTML = "File upload requires a more recent browser with HTML5 support";
+ this.keyStoreOldBrowserWarning.className = this.keyStoreOldBrowserWarning.className.replace("hidden", "");
+ }
+
+ this.keyStoreServerPath.on("blur", function(){that._keyStoreServerPathChanged()});
+ },
+ _keyStoreFileChanged: function (evt)
+ {
+ // We only ever expect a single file
+ var file = this.keyStoreFile.domNode.children[0].files[0];
+
+ this.addButton.setDisabled(true);
+ this.keyStoreSelectedFileContainer.innerHTML = file.name;
+ this.keyStoreSelectedFileStatusContainer.className = "loadingIcon";
+
+ console.log("Beginning to read trust store file " + file.name);
+ this.reader.readAsDataURL(file);
+ },
+ _keyStoreUploadFileComplete: function(evt)
+ {
+ var reader = evt.target;
+ var result = reader.result;
+ console.log("Trust store file read complete, contents " + result);
+ this.addButton.setDisabled(false);
+ this.keyStoreSelectedFileStatusContainer.className = "loadedIcon";
+
+ this.keyStoreServerPath.set("value", "");
+ this.keyStoreServerPath.setDisabled(true);
+ this.keyStoreServerPath.set("required", false);
+
+ this.keyStoreFileClearButton.setDisabled(false);
+
+ this.keyStorePath.set("value", result);
+ },
+ _keyStoreFileClearButtonClicked: function(event)
+ {
+ this.keyStoreFile.reset();
+ this.keyStoreSelectedFileStatusContainer.className = "";
+ this.keyStoreSelectedFileContainer.innerHTML = "";
+ this.keyStoreServerPath.set("required", true);
+ this.keyStoreServerPath.setDisabled(false);
+ this.keyStoreFileClearButton.setDisabled(true);
+
+ this.keyStorePath.set("value", "");
+ },
+ _keyStoreServerPathChanged: function()
+ {
+ var serverPathValue = this.keyStoreServerPath.get("value");
+ this.keyStorePath.set("value", serverPathValue);
+ },
+ update: function(effectiveData)
+ {
+ var attributes = metadata.getMetaData("TrustStore", "FileTrustStore").attributes;
+ var widgets = registry.findWidgets(this.containerNode);
+ array.forEach(widgets, function(item)
+ {
+ var name = item.id.replace("addStore.","");
+ if (name in attributes && item.type != "password")
+ {
+ item.set("value", effectiveData[name]);
+ }
+ });
+
+ var keyStorePathValue = effectiveData["path"];
+ var isDataUrl = keyStorePathValue.indexOf("data:") == 0;
+
+ if (isDataUrl)
+ {
+ this.keyStoreSelectedFileStatusContainer.className = "loadedIcon";
+ this.keyStoreSelectedFileContainer.innerHTML = "uploaded.jks";
+ this.keyStoreServerPath.setDisabled(true);
+ this.keyStoreServerPath.set("required", false);
+ this.keyStoreFileClearButton.setDisabled(false);
+ }
+ else
+ {
+ this.keyStoreServerPath.set("value", keyStorePathValue);
+ }
+ }
+ };
+
+ try
+ {
+ addTrustStore.init();
+ }
+ catch(e)
+ {
+ console.warn(e);
+ }
+ return addTrustStore;
+ }
+);
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/filetruststore/show.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/filetruststore/show.js
new file mode 100644
index 0000000..b031990
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/filetruststore/show.js
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+define(["qpid/common/util", "qpid/common/metadata", "dojo/domReady!"],
+ function (util, metadata)
+ {
+
+ function FileTrustStoreProvider(data)
+ {
+ this.fields = [];
+ var attributes = metadata.getMetaData("TrustStore", "FileTrustStore").attributes;
+ for(var name in attributes)
+ {
+ this.fields.push(name);
+ }
+ util.buildUI(data.containerNode, data.parent, "store/filetruststore/show.html", this.fields, this);
+ }
+
+ FileTrustStoreProvider.prototype.update = function(data)
+ {
+ util.updateUI(data, this.fields, this);
+ }
+
+ return FileTrustStoreProvider;
+ }
+);
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showKeyStore.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showKeyStore.html
deleted file mode 100644
index 33987a8..0000000
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showKeyStore.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!--
- -
- - 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.
- -
- -->
-<div class="keystore">
- <div class="keyStoreContainer" data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'KeyStore Attributes', open: true">
-
- <div class="formLabel-labelCell">Name:</div>
- <div class="nameValue"></div>
-
- <div class="formLabel-labelCell">Type:</div>
- <div class="keyStoreTypeValue"></div>
-
- <div class="formLabel-labelCell">State:</div>
- <div class="keyStoreStateValue"></div>
-
- <div class="formLabel-labelCell">Key Manager Factory Algorithm:</div>
- <div class="keyManagerFactoryAlgorithmValue"></div>
-
- <div class="formLabel-labelCell">Path:</div>
- <div class="pathValue"></div>
-
- <div class="certificateAlias">
- <div class="formLabel-labelCell">Certificate alias:</div>
- <div class="certificateAliasValue"></div>
- </div>
- <div class="clear"></div>
- </div>
-
- <br/>
- <div class="dijitDialogPaneActionBar">
- <button data-dojo-type="dijit.form.Button" class="editKeyStoreButton" type="button">Edit</button>
- <button data-dojo-type="dijit.form.Button" class="deleteKeyStoreButton" type="button">Delete</button>
- </div>
-</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showStore.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showStore.html
new file mode 100644
index 0000000..e564726
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showStore.html
@@ -0,0 +1,46 @@
+<!--
+ ~ 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.
+ -->
+<div>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Show Store', open: true">
+ <div id="showStore.contentPane">
+ <div class="clear">
+ <div class="formLabel-labelCell">Name:</div>
+ <div class="name"></div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Type:</div>
+ <div class="type"></div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell">State:</div>
+ <div class="state"></div>
+ </div>
+ <div class="clear">
+ <div class="typeFieldsContainer"></div>
+ </div>
+ <div class="clear">
+ </div>
+ </div>
+
+ <div class="dijitDialogPaneActionBar">
+ <button data-dojo-type="dijit.form.Button" class="editStoreButton" type="button">Edit</button>
+ <button data-dojo-type="dijit.form.Button" class="deleteStoreButton" type="button">Delete</button>
+ </div>
+ </div>
+</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showTrustStore.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showTrustStore.html
deleted file mode 100644
index 2b35efd..0000000
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showTrustStore.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!--
- -
- - 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.
- -
- -->
-<div class="truststore">
- <div class="trustStoreContainer" data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'TrustStore Attributes', open: true">
-
- <div class="formLabel-labelCell">Name:</div>
- <div class="nameValue"></div>
-
- <div class="formLabel-labelCell">Type:</div>
- <div class="trustStoreTypeValue"></div>
-
- <div class="formLabel-labelCell">State:</div>
- <div class="trustStoreStateValue"></div>
-
- <div class="formLabel-labelCell">Trust Manager Factory Algorithm:</div>
- <div class="trustManagerFactoryAlgorithmValue"></div>
-
- <div class="formLabel-labelCell">Path:</div>
- <div class="pathValue"></div>
-
- <div class="peersOnly">
- <div class="formLabel-labelCell">Peer store:</div>
- <div class="peersOnlyValue"></div>
- </div>
- <div class="clear"></div>
- </div>
-
- <br/>
- <div class="dijitDialogPaneActionBar">
- <button data-dojo-type="dijit.form.Button" class="editTrustStoreButton" type="button">Edit</button>
- <button data-dojo-type="dijit.form.Button" class="deleteTrustStoreButton" type="button">Delete</button>
- </div>
-</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html
index a99c73f..1a2b529 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html
@@ -114,6 +114,7 @@
<button data-dojo-type="dijit.form.Button" class="startButton" type="button" data-dojo-props="disabled: true">Start</button>
<button data-dojo-type="dijit.form.Button" class="stopButton" type="button" data-dojo-props="disabled: true">Stop</button>
<button data-dojo-type="dijit.form.Button" class="editButton" type="button" data-dojo-props="disabled: true">Edit</button>
+ <button data-dojo-type="dijit.form.Button" class="downloadButton" type="button" data-dojo-props="disabled: true">Download</button>
<button data-dojo-type="dijit.form.Button" class="deleteButton" data-dojo-props="iconClass: 'dijitIconDelete'">Delete</button>
</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/store/filekeystore/add.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/store/filekeystore/add.html
new file mode 100644
index 0000000..1732688
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/store/filekeystore/add.html
@@ -0,0 +1,114 @@
+<!--
+ ~ 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.
+ -->
+
+<div>
+ <div id="addStore.oldBrowserWarning" class="infoMessage hidden clear"></div>
+ <div class="clear">
+ <div id="addStore.serverPathLabel" class="formLabel-labelCell tableContainer-labelCell">Server path or upload*:</div>
+ <div class="formLabel-controlCell tableContainer-valueCell">
+ <input type="text" id="addStore.serverPath"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'serverPath',
+ placeHolder: 'key store file server path',
+ required: true,
+ excluded: true,
+ promptMessage: 'Location of the key store file on the server',
+ title: 'Enter the key store file path'" />
+
+ <!-- Hidden and used purely for form submission -->
+ <input type="hidden" id="addStore.path"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'path',
+ required: true" />
+ </div>
+
+ <div id="addStore.uploadFields">
+ <div id="addStore.fileLabel" class="formLabel-labelCell tableContainer-labelCell"></div>
+ <div class="fileUpload clear">
+ <span id="addStore.selectedFile" class="infoMessage"></span>
+ <span id="addStore.selectedFileStatus"></span>
+ </div>
+
+ <div class="fileUpload clear">
+ <input type="file" id="addStore.file"
+ multiple="false"
+ data-dojo-type="dojox/form/Uploader"
+ data-dojo-props="label: 'Upload'"/>
+ <button id="addStore.fileClearButton"
+ data-dojo-type="dijit/form/Button"
+ data-dojo-props="label: 'Clear',
+ disabled: true">
+ </button>
+ </div>
+ </div>
+
+ <div class="clear">
+ <div class="formLabel-labelCell tableContainer-labelCell">Password*:</div>
+ <div class="formLabel-controlCell tableContainer-valueCell">
+ <input type="password" id="addStore.password"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'password',
+ placeHolder: 'store password',
+ required: true,
+ promptMessage: 'password for store',
+ title: 'Enter a password for the store'" />
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell tableContainer-labelCell">Certificate alias:</div>
+ <div class="formLabel-controlCell tableContainer-valueCell">
+ <input type="text" id="addStore.certificateAlias"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'certificateAlias',
+ placeHolder: 'certificate alias',
+ promptMessage: 'Used to identify one certificate in a store that has many',
+ title: 'Enter an alias to identify one certificate in a store with many'" />
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell tableContainer-labelCell clear">Key manager factory algorithm:</div>
+ <div class="formLabel-controlCell tableContainer-valueCell">
+ <input type="text" id="addStore.keyManagerFactoryAlgorithm"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'keyManagerFactoryAlgorithm',
+ placeHolder: 'key manager factory algorithm',
+ promptMessage: 'Name of the key manager algorithm known to Java',
+ title: 'Enter the key manager algorithm known to Java'" />
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell tableContainer-labelCell">Java key store type:</div>
+ <div class="formLabel-controlCell tableContainer-valueCell">
+ <input type="text" id="addStore.keyStoreType"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'keyStoreType',
+ placeHolder: 'java key store type',
+ promptMessage: 'Name of the store type known to Java',
+ title: 'Enter the store type known to Java'" />
+ </div>
+ </div>
+
+ </div>
+</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/store/filekeystore/show.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/store/filekeystore/show.html
new file mode 100644
index 0000000..9a1d93d
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/store/filekeystore/show.html
@@ -0,0 +1,39 @@
+<!--
+ ~ 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.
+ -->
+
+<div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Path:</div>
+ <div ><span class="path" ></span></div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Certificate alias:</div>
+ <div><span class="certificateAlias" ></span></div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Java key store type:</div>
+ <div><span class="keyStoreType" ></span></div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Key manager factory algorithm:</div>
+ <div><span class="keyManagerFactoryAlgorithm" ></span></div>
+ </div>
+ <div class="clear"></div>
+</div>
+
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/store/filetruststore/add.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/store/filetruststore/add.html
new file mode 100644
index 0000000..36180d8
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/store/filetruststore/add.html
@@ -0,0 +1,109 @@
+<!--
+ ~ 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.
+ -->
+
+<div>
+ <div id="addStore.oldBrowserWarning" class="infoMessage hidden clear"></div>
+ <div class="clear">
+ <div id="addStore.serverPathLabel" class="formLabel-labelCell tableContainer-labelCell">Server path or upload*:</div>
+ <div class="formLabel-controlCell tableContainer-valueCell">
+ <input type="text" id="addStore.serverPath"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'serverPath',
+ placeHolder: 'trust store file server path',
+ required: true,
+ excluded: true,
+ promptMessage: 'Location of the trust store file on the server',
+ title: 'Enter the store file path'" />
+ <!-- Hidden and used purely for form submission -->
+ <input type="hidden" id="addStore.path"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'path',
+ required: true" />
+ </div>
+ <div id="addStore.uploadFields">
+ <div id="addStore.fileLabel" class="formLabel-labelCell tableContainer-labelCell"></div>
+ <div class="fileUpload clear">
+ <span id="addStore.selectedFile" class="infoMessage"></span>
+ <span id="addStore.selectedFileStatus"></span>
+ </div>
+ <div class="fileUpload clear">
+ <input type="file" id="addStore.file"
+ multiple="false"
+ data-dojo-type="dojox/form/Uploader"
+ data-dojo-props="label: 'Upload'"/>
+ <button id="addStore.fileClearButton"
+ data-dojo-type="dijit/form/Button"
+ data-dojo-props="label: 'Clear',
+ disabled: true">
+ </button>
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell tableContainer-labelCell">Password*:</div>
+ <div class="formLabel-controlCell tableContainer-valueCell">
+ <input type="password" id="addStore.password"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'password',
+ placeHolder: 'store password',
+ required: true,
+ promptMessage: 'password for store',
+ title: 'Enter a password for the store'" />
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell tableContainer-labelCell">Peers only:</div>
+ <div class="formLabel-controlCell tableContainer-valueCell">
+ <input type="text" id="addStore.peersOnly"
+ data-dojo-type="dijit/form/CheckBox"
+ data-dojo-props="
+ name: 'peersOnly',
+ promptMessage: 'Peers only or not',
+ title: 'Tick if peers only'" />
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell tableContainer-labelCell">Trust manager factory algorithm:</div>
+ <div class="formLabel-controlCell tableContainer-valueCell">
+ <input type="text" id="addStore.keyManagerFactoryAlgorithm"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'trustManagerFactoryAlgorithm',
+ placeHolder: 'trust manager factory algorithm',
+ promptMessage: 'Name of the trust manager algorithm known to Java',
+ title: 'Enter the trust manager algorithm known to Java'" />
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell tableContainer-labelCell">Java trust store type:</div>
+ <div class="formLabel-controlCell tableContainer-valueCell">
+ <input type="text" id="addStore.trustStoreType"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'trustStoreType',
+ placeHolder: 'java trust store type',
+ promptMessage: 'Name of the store type known to Java',
+ title: 'Enter the store type known to Java'" />
+ </div>
+ </div>
+
+ </div>
+</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/store/filetruststore/show.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/store/filetruststore/show.html
new file mode 100644
index 0000000..1c3744b
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/store/filetruststore/show.html
@@ -0,0 +1,39 @@
+<!--
+ ~ 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.
+ -->
+
+<div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Path:</div>
+ <div ><span class="path" ></span></div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Peers only:</div>
+ <div><span class="peersOnly" ></span></div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Java trust store type:</div>
+ <div><span class="trustStoreType" ></span></div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Trust manager factory algorithm:</div>
+ <div><span class="trustManagerFactoryAlgorithm" ></span></div>
+ </div>
+ <div class="clear"></div>
+</div>
+
diff --git a/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java b/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java
index 3f52152..a15de21 100644
--- a/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java
+++ b/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java
@@ -20,7 +20,8 @@
*/
package org.apache.qpid.server.store;
-import org.apache.qpid.server.BrokerOptions;
+import java.util.Map;
+
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.LogRecorder;
@@ -40,10 +41,10 @@
public MemorySystemConfigImpl(final TaskExecutor taskExecutor,
final EventLogger eventLogger,
final LogRecorder logRecorder,
- final BrokerOptions brokerOptions,
+ final Map<String,Object> attributes,
final BrokerShutdownProvider brokerShutdownProvider)
{
- super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);
+ super(taskExecutor, eventLogger, logRecorder, attributes, brokerShutdownProvider);
}
@Override
diff --git a/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/virtualhostnode/memory/MemoryVirtualHostNode.java b/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/virtualhostnode/memory/MemoryVirtualHostNode.java
index f57c0df..10c30cf 100644
--- a/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/virtualhostnode/memory/MemoryVirtualHostNode.java
+++ b/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/virtualhostnode/memory/MemoryVirtualHostNode.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.server.virtualhostnode.memory;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Map;
import org.apache.qpid.server.model.Broker;
@@ -30,7 +32,7 @@
import org.apache.qpid.server.store.MemoryConfigurationStore;
import org.apache.qpid.server.virtualhostnode.AbstractStandardVirtualHostNode;
-@ManagedObject(type=MemoryVirtualHostNode.VIRTUAL_HOST_NODE_TYPE, category=false)
+@ManagedObject(type=MemoryVirtualHostNode.VIRTUAL_HOST_NODE_TYPE, category=false, validChildTypes = "org.apache.qpid.server.virtualhostnode.memory.MemoryVirtualHostNode#getSupportedChildTypes()")
public class MemoryVirtualHostNode extends AbstractStandardVirtualHostNode<MemoryVirtualHostNode>
{
public static final String VIRTUAL_HOST_NODE_TYPE = "Memory";
@@ -51,4 +53,9 @@
{
return new MemoryConfigurationStore(VirtualHost.class);
}
+
+ public static Map<String, Collection<String>> getSupportedChildTypes()
+ {
+ return Collections.singletonMap(VirtualHost.class.getSimpleName(), getSupportedVirtualHostTypes(true));
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
index 76f8485..f4c6926 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
@@ -41,6 +41,7 @@
import org.apache.qpid.common.QpidProperties;
import org.apache.qpid.framing.ProtocolVersion;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.util.FileUtils;
/**
@@ -454,7 +455,17 @@
protected void startBroker(final BrokerOptions options) throws Exception
{
- Broker broker = new Broker(true);
+ Broker broker = new Broker(new Action<Integer>()
+ {
+ @Override
+ public void performAction(final Integer exitStatusCode)
+ {
+ if (exitStatusCode != 0)
+ {
+ shutdown(exitStatusCode);
+ }
+ }
+ });
broker.startup(options);
}
diff --git a/qpid/java/client/example/src/main/java/org/apache/qpid/example/Hello.java b/qpid/java/client/example/src/main/java/org/apache/qpid/example/Hello.java
index 7e95669..109a72b 100644
--- a/qpid/java/client/example/src/main/java/org/apache/qpid/example/Hello.java
+++ b/qpid/java/client/example/src/main/java/org/apache/qpid/example/Hello.java
@@ -42,7 +42,7 @@
{
}
- public static void main(String[] args)
+ public static void main(String[] args)
{
Hello hello = new Hello();
hello.runTest();
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java
index 66cade1..35582d9 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java
@@ -21,16 +21,20 @@
package org.apache.qpid.client;
import java.net.ConnectException;
+import java.nio.ByteBuffer;
import java.nio.channels.UnresolvedAddressException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import javax.jms.JMSException;
import javax.jms.XASession;
+import org.apache.qpid.transport.Receiver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -67,6 +71,9 @@
{
private static final Logger _logger = LoggerFactory.getLogger(AMQConnectionDelegate_8_0.class);
private final AMQConnection _conn;
+ private final long _timeout = Long.getLong(ClientProperties.QPID_SYNC_OP_TIMEOUT,
+ Long.getLong(ClientProperties.AMQJ_DEFAULT_SYNCWRITE_TIMEOUT,
+ ClientProperties.DEFAULT_SYNC_OPERATION_TIMEOUT));
private boolean _messageCompressionSupported;
private boolean _addrSyntaxSupported;
private boolean _confirmedPublishSupported;
@@ -136,7 +143,9 @@
OutgoingNetworkTransport transport = Transport.getOutgoingTransportInstance(getProtocolVersion());
- NetworkConnection network = transport.connect(settings, securityLayer.receiver(_conn.getProtocolHandler()),
+ ReceiverClosedWaiter monitoringReceiver = new ReceiverClosedWaiter(securityLayer.receiver(_conn.getProtocolHandler()));
+
+ NetworkConnection network = transport.connect(settings, monitoringReceiver,
_conn.getProtocolHandler());
try
@@ -171,6 +180,19 @@
network.close();
throw e;
}
+ finally
+ {
+ // await the receiver to finish its execution (and so the IO threads too)
+ if (!_conn.isConnected())
+ {
+ boolean closedWithinTimeout = monitoringReceiver.awaitClose(_timeout);
+ if (!closedWithinTimeout)
+ {
+ _logger.warn("Timed-out waiting for receiver for connection to "
+ + brokerDetail + " to be closed.");
+ }
+ }
+ }
}
@@ -503,4 +525,60 @@
{
return _confirmedPublishNonTransactionalSupported;
}
+
+
+ private static class ReceiverClosedWaiter implements Receiver<ByteBuffer>
+ {
+ private final CountDownLatch _closedWatcher;
+ private final Receiver<ByteBuffer> _receiver;
+
+ public ReceiverClosedWaiter(Receiver<ByteBuffer> receiver)
+ {
+ _receiver = receiver;
+ _closedWatcher = new CountDownLatch(1);
+ }
+
+ @Override
+ public void received(ByteBuffer msg)
+ {
+ _receiver.received(msg);
+ }
+
+ @Override
+ public void exception(Throwable t)
+ {
+ _receiver.exception(t);
+ }
+
+ @Override
+ public void closed()
+ {
+ try
+ {
+ _receiver.closed();
+ }
+ finally
+ {
+ _closedWatcher.countDown();
+ }
+ }
+
+ public boolean awaitClose(long timeout)
+ {
+ try
+ {
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Waiting " + timeout + "ms for receiver to be closed");
+ }
+
+ return _closedWatcher.await(timeout, TimeUnit.MILLISECONDS);
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ return _closedWatcher.getCount() == 0;
+ }
+ }
+ };
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java
index d86a273..bb0f0d9 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java
@@ -824,12 +824,13 @@
throws AMQException, FailoverException
{
_currentPrefetch.set(0);
- BasicQosBody basicQosBody = getProtocolHandler().getMethodRegistry().createBasicQosBody(sizePrefetch, messagePrefetch, false);
+ if(messagePrefetch > 0 || sizePrefetch > 0)
+ {
+ BasicQosBody basicQosBody =
+ getProtocolHandler().getMethodRegistry().createBasicQosBody(sizePrefetch, messagePrefetch, false);
- // todo send low water mark when protocol allows.
- // todo Be aware of possible changes to parameter order as versions change.
- getProtocolHandler().syncWrite(basicQosBody.generateFrame(getChannelId()), BasicQosOkBody.class);
-
+ getProtocolHandler().syncWrite(basicQosBody.generateFrame(getChannelId()), BasicQosOkBody.class);
+ }
}
@@ -842,13 +843,17 @@
public Boolean execute() throws AMQException, FailoverException
{
int currentPrefetch = _currentPrefetch.get();
- if (currentPrefetch >= getPrefetch())
+ if (currentPrefetch >= getPrefetch() && getPrefetch() >= 0)
{
BasicQosBody basicQosBody = getProtocolHandler().getMethodRegistry()
.createBasicQosBody(0, currentPrefetch + 1, false);
getProtocolHandler().syncWrite(basicQosBody.generateFrame(getChannelId()),
BasicQosOkBody.class);
+ if(currentPrefetch == 0 && !isSuspended())
+ {
+ sendSuspendChannel(false);
+ }
_creditChanged.set(true);
return true;
}
@@ -863,8 +868,7 @@
protected void reduceCreditAfterAcknowledge() throws AMQException
{
- int acknowledgeMode = getAcknowledgeMode();
- boolean manageCredit = acknowledgeMode == javax.jms.Session.CLIENT_ACKNOWLEDGE || acknowledgeMode == javax.jms.Session.SESSION_TRANSACTED;
+ boolean manageCredit = isManagingCredit();
if(manageCredit && _creditChanged.compareAndSet(true,false))
{
@@ -873,18 +877,40 @@
{
public Void execute() throws AMQException, FailoverException
{
- BasicQosBody basicQosBody =
- getProtocolHandler().getMethodRegistry()
- .createBasicQosBody(0, getPrefetch(), false);
+ int prefetch = getPrefetch();
+ if(prefetch == 0)
+ {
+ sendSuspendChannel(true);
+ }
+ else
+ {
+ BasicQosBody basicQosBody =
+ getProtocolHandler().getMethodRegistry()
+ .createBasicQosBody(0, prefetch == -1 ? 0 : prefetch, false);
- getProtocolHandler().syncWrite(basicQosBody.generateFrame(getChannelId()),
- BasicQosOkBody.class);
+ getProtocolHandler().syncWrite(basicQosBody.generateFrame(getChannelId()),
+ BasicQosOkBody.class);
+ }
return null;
}
}, getProtocolHandler().getConnection()).execute();
}
}
+ protected void reduceCreditInPostDeliver()
+ {
+ int acknowledgeMode = getAcknowledgeMode();
+ boolean manageCredit = (acknowledgeMode == AUTO_ACKNOWLEDGE || acknowledgeMode == DUPS_OK_ACKNOWLEDGE) && getPrefetch() == 0;
+
+ if(manageCredit && _creditChanged.compareAndSet(true,false))
+ {
+ ChannelFlowBody body = getMethodRegistry().createChannelFlowBody(false);
+ AMQFrame channelFlowFrame = body.generateFrame(getChannelId());
+ getProtocolHandler().writeFrame(channelFlowFrame, true);
+ }
+ }
+
+
protected void updateCurrentPrefetch(int delta)
{
_currentPrefetch.addAndGet(delta);
@@ -1414,6 +1440,15 @@
}
}
+ boolean isManagingCredit()
+ {
+ int acknowledgeMode = getAcknowledgeMode();
+ return acknowledgeMode == CLIENT_ACKNOWLEDGE
+ || acknowledgeMode == SESSION_TRANSACTED
+ || ((acknowledgeMode == AUTO_ACKNOWLEDGE || acknowledgeMode == DUPS_OK_ACKNOWLEDGE) && getPrefetch() == 0);
+ }
+
+
public boolean isFlowBlocked()
{
synchronized (_flowControl)
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
index 3d0e972..b1e606b 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
@@ -645,6 +645,12 @@
_receivingThread.interrupt();
}
+
+
+ if(!(isBrowseOnly() || getSession().isClosing()))
+ {
+ rollback();
+ }
}
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java
index 6718121..1d7bb60 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java
@@ -170,8 +170,7 @@
@Override
public Message receive(final long l) throws JMSException
{
- int acknowledgeMode = getSession().getAcknowledgeMode();
- boolean manageCredit = acknowledgeMode == Session.CLIENT_ACKNOWLEDGE || acknowledgeMode == Session.SESSION_TRANSACTED;
+ boolean manageCredit = getSession().isManagingCredit();
boolean creditModified = false;
try
{
@@ -184,7 +183,8 @@
{
getSession().reduceCreditAfterAcknowledge();
}
- if (manageCredit && message != null)
+ if (manageCredit && !(getSession().getAcknowledgeMode() == Session.AUTO_ACKNOWLEDGE
+ || getSession().getAcknowledgeMode() == Session.DUPS_OK_ACKNOWLEDGE) && message != null)
{
getSession().updateCurrentPrefetch(1);
}
@@ -199,8 +199,7 @@
@Override
public Message receiveNoWait() throws JMSException
{
- int acknowledgeMode = getSession().getAcknowledgeMode();
- boolean manageCredit = acknowledgeMode == Session.CLIENT_ACKNOWLEDGE || acknowledgeMode == Session.SESSION_TRANSACTED;
+ boolean manageCredit = getSession().isManagingCredit();
boolean creditModified = false;
try
{
@@ -217,7 +216,8 @@
{
getSession().reduceCreditAfterAcknowledge();
}
- if (manageCredit && message != null)
+ if (manageCredit && !(getSession().getAcknowledgeMode() == Session.AUTO_ACKNOWLEDGE
+ || getSession().getAcknowledgeMode() == Session.DUPS_OK_ACKNOWLEDGE) && message != null)
{
getSession().updateCurrentPrefetch(1);
}
@@ -228,4 +228,11 @@
throw new JMSAMQException(e);
}
}
+
+
+ void postDeliver(AbstractJMSMessage msg)
+ {
+ getSession().reduceCreditInPostDeliver();
+ super.postDeliver(msg);
+ }
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
index 0fe2ce2..d5e3027 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
@@ -240,7 +240,7 @@
}
catch (Exception e)
{
- _logger.warn("Exception occured on closing the sender", e);
+ _logger.warn("Exception occurred on closing the sender", e);
}
if (_connection.failoverAllowed())
{
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/properties/ConnectionStartProperties.java b/qpid/java/common/src/main/java/org/apache/qpid/properties/ConnectionStartProperties.java
index 4f88fe7..3569b4b 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/properties/ConnectionStartProperties.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/properties/ConnectionStartProperties.java
@@ -20,9 +20,6 @@
*/
package org.apache.qpid.properties;
-import java.lang.management.ManagementFactory;
-import java.lang.management.RuntimeMXBean;
-
import org.apache.qpid.transport.util.Logger;
import org.apache.qpid.util.SystemUtils;
@@ -62,30 +59,18 @@
public static final String QPID_CONFIRMED_PUBLISH_SUPPORTED = "qpid.confirmed_publish_supported";
- public static int _pid;
+ public static final int _pid;
public static final String _platformInfo;
static
{
- RuntimeMXBean rtb = ManagementFactory.getRuntimeMXBean();
- String processName = rtb.getName();
- if (processName != null && processName.indexOf('@') > 0)
+
+ _pid = SystemUtils.getProcessPidAsInt();
+
+ if (_pid == -1)
{
- try
- {
- _pid = Integer.parseInt(processName.substring(0,processName.indexOf('@')));
- }
- catch(Exception e)
- {
- LOGGER.warn("Unable to get the PID due to error",e);
- _pid = -1;
- }
- }
- else
- {
- LOGGER.warn("Unable to get the PID due to unsupported format : " + processName);
- _pid = -1;
+ LOGGER.warn("Unable to get the process's PID");
}
StringBuilder fullSystemInfo = new StringBuilder(System.getProperty("java.runtime.name"));
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java
index 0dccf37..c61684e 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java
@@ -27,6 +27,7 @@
import javax.net.ssl.X509ExtendedKeyManager;
import java.io.IOException;
import java.net.Socket;
+import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Principal;
@@ -50,6 +51,16 @@
this.delegate = (X509ExtendedKeyManager)kmf.getKeyManagers()[0];
}
+ public QpidClientX509KeyManager(String alias, URL keyStoreUrl, String keyStoreType,
+ String keyStorePassword, String keyManagerFactoryAlgorithmName) throws GeneralSecurityException, IOException
+ {
+ this.alias = alias;
+ KeyStore ks = SSLUtil.getInitializedKeyStore(keyStoreUrl,keyStorePassword,keyStoreType);
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(keyManagerFactoryAlgorithmName);
+ kmf.init(ks, keyStorePassword.toCharArray());
+ this.delegate = (X509ExtendedKeyManager)kmf.getKeyManagers()[0];
+ }
+
public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket)
{
log.debug("chooseClientAlias:Returning alias " + alias);
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java
index 98229fd..b6ae2ab 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java
@@ -24,6 +24,7 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Principal;
@@ -248,6 +249,23 @@
return ks;
}
+ public static KeyStore getInitializedKeyStore(URL storePath, String storePassword, String keyStoreType) throws GeneralSecurityException, IOException
+ {
+ KeyStore ks = KeyStore.getInstance(keyStoreType);
+ try(InputStream in = storePath.openStream())
+ {
+ if (in == null && !"PKCS11".equalsIgnoreCase(keyStoreType)) // PKCS11 will not require an explicit path
+ {
+ throw new IOException("Unable to load keystore resource: " + storePath);
+ }
+
+ char[] storeCharPassword = storePassword == null ? null : storePassword.toCharArray();
+
+ ks.load(in, storeCharPassword);
+ }
+ return ks;
+ }
+
public static void removeSSLv3Support(final SSLEngine engine)
{
List<String> enabledProtocols = Arrays.asList(engine.getEnabledProtocols());
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java b/qpid/java/common/src/main/java/org/apache/qpid/util/DataUrlUtils.java
similarity index 69%
copy from qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
copy to qpid/java/common/src/main/java/org/apache/qpid/util/DataUrlUtils.java
index 75c6c19..16c5012 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestEnum.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/DataUrlUtils.java
@@ -17,16 +17,16 @@
* under the License.
*/
-package org.apache.qpid.server.model.testmodel;
+package org.apache.qpid.util;
+import javax.xml.bind.DatatypeConverter;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-public enum TestEnum
+public class DataUrlUtils
{
- TEST_ENUM1,
- TEST_ENUM2,
- TEST_ENUM3;
+ public static String getDataUrlForBytes(final byte[] bytes)
+ {
+ StringBuilder inlineURL = new StringBuilder("data:;base64,");
+ inlineURL.append(DatatypeConverter.printBase64Binary(bytes));
+ return inlineURL.toString();
+ }
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/FileUtils.java b/qpid/java/common/src/main/java/org/apache/qpid/util/FileUtils.java
index dd347b5..70607f4 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/FileUtils.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/FileUtils.java
@@ -22,6 +22,7 @@
import java.io.BufferedInputStream;
import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -51,39 +52,32 @@
*
* @return The contents of the file.
*/
- public static String readFileAsString(String filename)
+ public static byte[] readFileAsBytes(String filename)
{
- BufferedInputStream is = null;
- try
+ try(BufferedInputStream is = new BufferedInputStream(new FileInputStream(filename)))
{
- try
- {
- is = new BufferedInputStream(new FileInputStream(filename));
- }
- catch (FileNotFoundException e)
- {
- throw new RuntimeException(e);
- }
-
return readStreamAsString(is);
}
- finally
+ catch (IOException e)
{
- if (is != null)
- {
- try
- {
- is.close();
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
- }
+ throw new RuntimeException(e);
}
}
+
+ /**
+ * Reads a text file as a string.
+ *
+ * @param filename The name of the file.
+ *
+ * @return The contents of the file.
+ */
+ public static String readFileAsString(String filename)
+ {
+ return new String(readFileAsBytes(filename));
+ }
+
/**
* Reads a text file as a string.
*
@@ -93,18 +87,15 @@
*/
public static String readFileAsString(File file)
{
- BufferedInputStream is = null;
-
- try
+ try(BufferedInputStream is = new BufferedInputStream(new FileInputStream(file)))
{
- is = new BufferedInputStream(new FileInputStream(file));
+
+ return new String(readStreamAsString(is));
}
- catch (FileNotFoundException e)
+ catch (IOException e)
{
throw new RuntimeException(e);
}
-
- return readStreamAsString(is);
}
/**
@@ -115,23 +106,20 @@
*
* @return The contents of the reader.
*/
- private static String readStreamAsString(BufferedInputStream is)
+ private static byte[] readStreamAsString(BufferedInputStream is)
{
- try
+ try(ByteArrayOutputStream inBuffer = new ByteArrayOutputStream())
{
byte[] data = new byte[4096];
- StringBuffer inBuffer = new StringBuffer();
-
int read;
while ((read = is.read(data)) != -1)
{
- String s = new String(data, 0, read);
- inBuffer.append(s);
+ inBuffer.write(data, 0, read);
}
- return inBuffer.toString();
+ return inBuffer.toByteArray();
}
catch (IOException e)
{
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/SystemUtils.java b/qpid/java/common/src/main/java/org/apache/qpid/util/SystemUtils.java
index 55c7ae9..5825276 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/SystemUtils.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/SystemUtils.java
@@ -20,6 +20,9 @@
*/
package org.apache.qpid.util;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+
/**
* SystemUtils provides some simple helper methods for working with the current
* Operating System.
@@ -38,9 +41,29 @@
private static final String _osName = System.getProperty("os.name", UNKNOWN_OS);
private static final String _osVersion = System.getProperty("os.version", UNKNOWN_VERSION);
private static final String _osArch = System.getProperty("os.arch", UNKNOWN_ARCH);
-
private static final boolean _isWindows = _osName.toLowerCase().contains("windows");
+ /** Process identifier of underlying process or null if it cannot be determined */
+ private static final String _osPid;
+ private static int _osPidInt;
+
+ static
+ {
+ RuntimeMXBean rtb = ManagementFactory.getRuntimeMXBean();
+ String processName = rtb.getName();
+ int atIndex;
+ if(processName != null && (atIndex = processName.indexOf('@')) > 0)
+ {
+ _osPid = processName.substring(0, atIndex);
+ _osPidInt = parseInt(_osPid, -1);
+ }
+ else
+ {
+ _osPid = null;
+ }
+ }
+
+
private SystemUtils()
{
}
@@ -60,6 +83,16 @@
return _osArch;
}
+ public final static String getProcessPid()
+ {
+ return _osPid;
+ }
+
+ public final static int getProcessPidAsInt()
+ {
+ return _osPidInt;
+ }
+
public final static boolean isWindows()
{
return _isWindows;
@@ -78,4 +111,17 @@
{
return _osName + " " + _osVersion + " " + _osArch;
}
+
+ private static int parseInt(String str, int defaultVal)
+ {
+ try
+ {
+ return Integer.parseInt(str);
+ }
+ catch(NumberFormatException e)
+ {
+ return defaultVal;
+ }
+ }
+
}
diff --git a/qpid/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef b/qpid/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef
index 7561ea3..0d11f70 100644
--- a/qpid/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef
+++ b/qpid/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef
@@ -20,7 +20,7 @@
chartType=XYLINE
chartTitle=Varying number of producers - transacted
chartSubtitle=Persistent 1KB messages
-chartDescription=1,2,5,10 P/Cs, single queue, persistent, transacted, with message payload 1KB.
+chartDescription=1,2,5,10,20,40 P/Cs, single queue, persistent, transacted, with message payload 1KB.
xAxisTitle=Producers
yAxisTitle=Throughput (messages/s)
@@ -40,8 +40,18 @@
series.3.dir=${csvCurrentDir}
series.3.colourName=green
-series.4.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '1' and acknowledgeMode = '0'
-series.4.legend=1 Consumer (baseline ${baselineName})
-series.4.dir=${csvBaselineDir}
-series.4.colourName=dark_red
-series.4.strokeWidth=-1
+series.4.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '20' and acknowledgeMode = '0'
+series.4.legend=20 Consumer
+series.4.dir=${csvCurrentDir}
+series.4.colourName=magenta
+
+series.5.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '40' and acknowledgeMode = '0'
+series.5.legend=40 Consumer
+series.5.dir=${csvCurrentDir}
+series.5.colourName=orange
+
+series.6.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '1' and acknowledgeMode = '0'
+series.6.legend=1 Consumer (baseline ${baselineName})
+series.6.dir=${csvBaselineDir}
+series.6.colourName=dark_red
+series.6.strokeWidth=-1
diff --git a/qpid/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef b/qpid/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef
index f567ffa..bd3f6a4 100644
--- a/qpid/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef
+++ b/qpid/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef
@@ -20,7 +20,7 @@
chartType=XYLINE
chartTitle=Varying number of consumers - transacted
chartSubtitle=Persistent 1KB messages
-chartDescription=1,2,5,10 P/Cs, single queue, persistent, transacted, with message payload 1KB.
+chartDescription=1,2,5,10,20,40 P/Cs, single queue, persistent, transacted, with message payload 1KB.
xAxisTitle=Consumers
yAxisTitle=Throughput (messages/s)
@@ -40,8 +40,18 @@
series.3.dir=${csvCurrentDir}
series.3.colourName=red
-series.4.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '10' and acknowledgeMode = '0'
-series.4.legend=10 Producers (baseline ${baselineName})
-series.4.dir=${csvBaselineDir}
-series.4.colourName=dark_red
-series.4.strokeWidth=-1
+series.4.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '20' and acknowledgeMode = '0'
+series.4.legend=20 Producers
+series.4.dir=${csvCurrentDir}
+series.4.colourName=magenta
+
+series.5.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '40' and acknowledgeMode = '0'
+series.5.legend=40 Producers
+series.5.dir=${csvCurrentDir}
+series.5.colourName=yellow
+
+series.6.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '10' and acknowledgeMode = '0'
+series.6.legend=10 Producers (baseline ${baselineName})
+series.6.dir=${csvBaselineDir}
+series.6.colourName=dark_red
+series.6.strokeWidth=-1
diff --git a/qpid/java/perftests/etc/chartdefs/1060-SSLConnections.chartdef b/qpid/java/perftests/etc/chartdefs/1060-SSLConnections.chartdef
new file mode 100644
index 0000000..90cb06d
--- /dev/null
+++ b/qpid/java/perftests/etc/chartdefs/1060-SSLConnections.chartdef
@@ -0,0 +1,49 @@
+#
+# 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.
+#
+
+chartType=LINE
+chartTitle=Effect of SSL - transacted
+chartSubtitle=Persistent 1KB messages
+chartDescription=Matching number of P/Cs, single queue, persistent, transacted, with message payload 1KB.
+
+xAxisTitle=Number of producers and consumers on separate connections
+yAxisTitle=Throughput (messages/s)
+
+series.1.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = totalNumberOfProducers and acknowledgeMode = '0'
+series.1.legend=Plain
+series.1.dir=${csvCurrentDir}
+series.1.colourName=red
+
+series.2.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = totalNumberOfProducers and acknowledgeMode = '0'
+series.2.legend=Plain (baseline ${baselineName})
+series.2.dir=${csvBaselineDir}
+series.2.colourName=dark_red
+series.2.strokeWidth=-1
+
+series.3.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM VaryingNumberOfParticipantsSSL WHERE participantName = 'All' and totalNumberOfConsumers = totalNumberOfProducers and acknowledgeMode = '0'
+series.3.legend=SSL
+series.3.dir=${csvCurrentDir}
+series.3.colourName=blue
+
+series.4.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM VaryingNumberOfParticipantsSSL WHERE participantName = 'All' and totalNumberOfConsumers = totalNumberOfProducers and acknowledgeMode = '0'
+series.4.legend=SSL (baseline ${baselineName})
+series.4.dir=${csvBaselineDir}
+series.4.colourName=dark_blue
+series.4.strokeWidth=-1
+
diff --git a/qpid/java/perftests/etc/json_config_tool.py b/qpid/java/perftests/etc/json_config_tool.py
new file mode 100755
index 0000000..38a994f
--- /dev/null
+++ b/qpid/java/perftests/etc/json_config_tool.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+from StringIO import StringIO
+import json
+import sys
+import re
+
+objname = None
+attrname = None
+attrvalue = None
+
+try:
+ import argparse
+
+ parser = argparse.ArgumentParser(description='Adds (or updates) a attribute name/value pair of an existing object within a Java Broker config.json')
+ parser.add_argument("objectname", help='Name of the object e.g. httpManagement')
+ parser.add_argument("attrname", help='Name of the attribute to add or update e.g. httpBasicAuthenticationEnabled')
+ parser.add_argument("attrvalue", help='Value of the attribute e.g. true')
+ args = parser.parse_args()
+
+ objname = args.objectname
+ attrname = args.attrname
+ attrvalue = args.attrvalue
+except ImportError:
+ objname = sys.argv[1]
+ attrname = sys.argv[2]
+ attrvalue = sys.argv[3]
+ pass
+
+
+def transform(data):
+ if isinstance(data, tuple):
+ (k, v) = data;
+ return k, transform(v)
+ elif isinstance(data, list):
+ return [transform(i) for i in data]
+ elif isinstance(data, dict):
+ if "name" in data and data["name"] == objname:
+ data[attrname] = attrvalue
+ return data
+ else:
+ return data
+
+# Expects a config.json to be provided on stdin, write the resulting json to stdout.
+
+lines = []
+for line in sys.stdin:
+ lines.append(line.rstrip())
+
+# naive strip C style comments - this deals with the Apache licence comment present on the default config
+input = re.sub("/\*.*?\*/", " ", "".join(lines), re.S)
+
+data = json.load(StringIO(input))
+data = dict([transform((k, v)) for k,v in data.items()])
+
+json.dump(data, sys.stdout, sort_keys=True, indent=2)
diff --git a/qpid/java/perftests/etc/perftests-jndi.properties b/qpid/java/perftests/etc/perftests-jndi.properties
index 173606c..deb0a8d 100644
--- a/qpid/java/perftests/etc/perftests-jndi.properties
+++ b/qpid/java/perftests/etc/perftests-jndi.properties
@@ -18,6 +18,7 @@
java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextFactory
connectionfactory.connectionfactory = amqp://guest:guest@clientid/?brokerlist='tcp://localhost:5672'
+connectionfactory.sslconnectionfactory = amqp://guest:guest@clientid/?ssl='true'&brokerlist='tcp://localhost:5671'
destination.controllerqueue = direct://amq.direct//controllerqueue?autodelete='true'
diff --git a/qpid/java/perftests/etc/testdefs/VaryingNumberOfParticipants.js b/qpid/java/perftests/etc/testdefs/VaryingNumberOfParticipants.js
index 4e557e3..1e04a89 100644
--- a/qpid/java/perftests/etc/testdefs/VaryingNumberOfParticipants.js
+++ b/qpid/java/perftests/etc/testdefs/VaryingNumberOfParticipants.js
@@ -25,8 +25,8 @@
var duration = 30000;
var queueName = "direct://amq.direct//varNumOfParticipants?durable='true'";
-var numbersOfProducers = [1, 2, 5, 10];
-var numbersOfConsumers = [1, 2, 5, 10];
+var numbersOfProducers = [1, 2, 5, 10, 20, 40];
+var numbersOfConsumers = [1, 2, 5, 10, 20, 40];
for(producersIndex=0; producersIndex < numbersOfProducers.length; producersIndex++)
{
diff --git a/qpid/java/perftests/etc/testdefs/VaryingNumberOfParticipantsSSL.js b/qpid/java/perftests/etc/testdefs/VaryingNumberOfParticipantsSSL.js
new file mode 100644
index 0000000..03d94c5
--- /dev/null
+++ b/qpid/java/perftests/etc/testdefs/VaryingNumberOfParticipantsSSL.js
@@ -0,0 +1,104 @@
+/*
+ *
+ * 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.
+ *
+ */
+var jsonObject = {
+ _tests:[]
+};
+
+var duration = 30000;
+var queueName = "direct://amq.direct//varNumOfParticipantsSsl?durable='true'";
+
+var numbersOfProducers = [1, 2, 5, 10, 20, 40];
+var numbersOfConsumers = [1, 2, 5, 10, 20, 40];
+
+for(producersIndex=0; producersIndex < numbersOfProducers.length; producersIndex++)
+{
+ for(consumersIndex=0; consumersIndex < numbersOfConsumers.length; consumersIndex++)
+ {
+ var numberOfProducers = numbersOfProducers[producersIndex];
+ var numberOfConsumers = numbersOfConsumers[consumersIndex];
+ var test = {
+ "_name": "Varying number of participants: " + numberOfConsumers + " consumers - " + numberOfProducers + " producers - PERSISTENT",
+ "_queues":[
+ {
+ "_name": queueName,
+ "_durable": true
+ }
+ ],
+ "_iterations":[
+ {
+ "_acknowledgeMode": 0
+ }
+ ],
+ "_clients":
+ QPID.times(numberOfProducers,
+ {
+ "_name": "producingClient__PRODUCING_CLIENT_INDEX",
+ "_connections":[
+ {
+ "_name": "connection1",
+ "_factory": "sslconnectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_producers": [
+ {
+ "_name": "Producer__PRODUCING_CLIENT_INDEX",
+ "_destinationName": queueName,
+ "_maximumDuration": duration,
+ "_deliveryMode": 2,
+ "_messageSize": 1024
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "__PRODUCING_CLIENT_INDEX")
+ .concat(QPID.times(numberOfConsumers,
+ {
+ "_name": "consumingClient__CONSUMING_CLIENT_INDEX",
+ "_connections":[
+ {
+ "_name": "connection1",
+ "_factory": "sslconnectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_consumers": [
+ {
+ "_name": "Consumer__CONSUMING_CLIENT_INDEX",
+ "_destinationName": queueName,
+ "_maximumDuration": duration
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "__CONSUMING_CLIENT_INDEX"))
+ };
+
+ jsonObject._tests= jsonObject._tests.concat(test);
+
+ }
+}
diff --git a/qpid/java/perftests/etc/visualisation-timeseries.sh b/qpid/java/perftests/etc/visualisation-timeseries.sh
deleted file mode 100755
index 3f35b90..0000000
--- a/qpid/java/perftests/etc/visualisation-timeseries.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env bash
-#
-# 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.
-#
-
-# Runs the visualisation tool against perftest output assumed to be in a Derby database in the current directory
-
-BASE_DIR=`dirname $0`
-
-# Uncomment to read perftest data from a Derby database
-JDBC_URL=jdbcUrl=jdbc:derby:perftestResultsDb
-JDBC_DRIVER=jdbcDriverClass=org.apache.derby.jdbc.EmbeddedDriver
-
-java -cp "${BASE_DIR}:${BASE_DIR}/../../build/lib/*" \
- -Djava.awt.headless=true -Dlog4j.configuration=file:log4j.properties \
- org.apache.qpid.disttest.charting.ChartingUtil \
- chart-defs=chartdefs/timeseries \
- ${JDBC_DRIVER} ${JDBC_URL}
diff --git a/qpid/java/perftests/etc/visualisation.sh b/qpid/java/perftests/etc/visualisation.sh
deleted file mode 100755
index 4c10d7e..0000000
--- a/qpid/java/perftests/etc/visualisation.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env bash
-#
-# 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.
-#
-
-# Runs the visualisation tool against perftest CSV output assumed to be in the current directory
-
-BASE_DIR=`dirname $0`
-
-# Uncomment to read perftest data from a Derby database
-# JDBC_URL=jdbcUrl=jdbc:derby:perftestResultsDb
-# JDBC_DRIVER=jdbcDriverClass=org.apache.derby.jdbc.EmbeddedDriver
-
-java -cp "${BASE_DIR}:${BASE_DIR}/../../build/lib/*" \
- -Djava.awt.headless=true -Dlog4j.configuration=file:log4j.properties \
- -DcsvCurrentDir=/home/V510279/tasks/_old/PerfTestDryRun/etc/ \
- -DcsvBaselineDir=/home/V510279/tasks/_old/PerfTestDryRun/etc/ \
- -DbaselineName=${BASELINE_NAME} \
- org.apache.qpid.disttest.charting.ChartingUtil \
- chart-defs=chartdefs \
- ${JDBC_DRIVER} ${JDBC_URL}
diff --git a/qpid/java/perftests/visualisation-jfc/pom.xml b/qpid/java/perftests/visualisation-jfc/pom.xml
index e99bde0..2d0ccb6 100644
--- a/qpid/java/perftests/visualisation-jfc/pom.xml
+++ b/qpid/java/perftests/visualisation-jfc/pom.xml
@@ -120,6 +120,52 @@
<skip>true</skip>
</configuration>
</plugin>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.3.2</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>java</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <mainClass>org.apache.qpid.disttest.charting.ChartingUtil</mainClass>
+ <includePluginDependencies>true</includePluginDependencies>
+ <arguments>
+ <argument>chart-defs=${basedir}/../etc/chartdefs</argument>
+ </arguments>
+ <systemProperties>
+ <systemProperty>
+ <key>log4j.configuration</key><value>file:log4j.properties</value>
+ </systemProperty>
+ <systemProperty>
+ <key>java.awt.headless</key><value>true</value>
+ </systemProperty>
+ <systemProperty>
+ <key>csvCurrentDir</key><value>${basedir}/../target/data/current</value>
+ </systemProperty>
+ <systemProperty>
+ <key>csvBaselineDir</key><value>${basedir}/../target/data/baseline</value>
+ </systemProperty>
+ </systemProperties>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>net.sourceforge.csvjdbc</groupId>
+ <artifactId>csvjdbc</artifactId>
+ <version>${csvjdbc-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>jfree</groupId>
+ <artifactId>jfreechart</artifactId>
+ <version>${jfreechart-version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
</plugins>
</build>
diff --git a/qpid/java/pom.xml b/qpid/java/pom.xml
index d2d1322..6e0cde4 100644
--- a/qpid/java/pom.xml
+++ b/qpid/java/pom.xml
@@ -54,7 +54,7 @@
<!-- test profile properties and defaults-->
<qpid.home>${basedir}</qpid.home> <!-- override for broker tests -->
- <qpid.home.qbtc.output>${qpid.home}${file.separator}target${file.separator}qbtc-output</qpid.home.qbtc.output> <!-- override for broker tests -->
+ <qpid.home.qbtc.output>${qpid.home}${file.separator}target${file.separator}qbtc-test-config</qpid.home.qbtc.output> <!-- override for broker tests -->
<qpid.work>${project.build.directory}${file.separator}QPID_WORK</qpid.work>
<profile>java-mms.0-10</profile>
@@ -73,6 +73,7 @@
<profile.broker.clean.between.tests>true</profile.broker.clean.between.tests>
<dollar.sign>$</dollar.sign>
<at.sign>@</at.sign>
+ <bdb-version>5.0.104</bdb-version>
</properties>
<modules>
@@ -218,9 +219,6 @@
<amqj.server.logging.level>debug</amqj.server.logging.level>
<amqj.protocol.logging.level>debug</amqj.protocol.logging.level>
<root.logging.level>warn</root.logging.level>
- <log4j.configuration.file>${project.basedir}${file.separator}test-profiles${file.separator}log4j-test.xml</log4j.configuration.file>
- <log4j.configuration>log4j-test.xml</log4j.configuration>
- <log4j.debug>false</log4j.debug>
<test.port>15672</test.port>
<test.mport>18999</test.mport>
<test.cport>19099</test.cport>
diff --git a/qpid/java/qpid-perftests-systests/pom.xml b/qpid/java/qpid-perftests-systests/pom.xml
index 64a5708..e3c5232 100644
--- a/qpid/java/qpid-perftests-systests/pom.xml
+++ b/qpid/java/qpid-perftests-systests/pom.xml
@@ -110,6 +110,14 @@
</dependencies>
<build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>${test.resource.directory}/test-profiles/test_resources</directory>
+ </resource>
+ </resources>
<testResources>
<testResource>
<directory>src/test/java</directory>
diff --git a/qpid/java/qpid-systests-parent/pom.xml b/qpid/java/qpid-systests-parent/pom.xml
index 88c0c45..fc76cce 100644
--- a/qpid/java/qpid-systests-parent/pom.xml
+++ b/qpid/java/qpid-systests-parent/pom.xml
@@ -34,8 +34,9 @@
<broker.home.dir>target${file.separator}qpid-broker${file.separator}${project.version}</broker.home.dir>
<!-- test properties -->
<qpid.home>${basedir}${file.separator}${broker.home.dir}</qpid.home>
- <qpid.home.qbtc.output>${qpid.home}${file.separator}qbtc-output</qpid.home.qbtc.output>
- <test.log4j.configuration.file>${project.basedir}${file.separator}..${file.separator}test-profiles${file.separator}log4j-test.xml</test.log4j.configuration.file>
+ <qpid.home.qbtc.output>${qpid.home}${file.separator}qbtc-test-config</qpid.home.qbtc.output>
+ <test.output.dir>${basedir}${file.separator}target${file.separator}surefire-reports</test.output.dir>
+
<test.working.directory>${basedir}/..</test.working.directory>
<test.resource.directory>${basedir}/..</test.resource.directory>
<test.systest.resource.directory>${basedir}</test.systest.resource.directory>
@@ -83,7 +84,14 @@
integration-test phase below instead -->
<skip>true</skip>
<systemPropertyVariables>
- <log4j.configuration.file>${test.log4j.configuration.file}</log4j.configuration.file>
+ <test.output.dir>${test.output.dir}</test.output.dir>
+ <log4j.configuration.file>${basedir}${file.separator}target${file.separator}classes/log4j.xml</log4j.configuration.file>
+ <!-- Let the tests themselves configure logging so that we can have a separate log file per test
+ named after the test. -->
+ <log4j.debug>false</log4j.debug>
+ <log4j.defaultInitOverride>true</log4j.defaultInitOverride>
+ <!-- A log4j config file that sends all the Broker's output to stdout -->
+ <spawnedbroker.log4j.configuration.file>${basedir}${file.separator}target${file.separator}classes/spawned-broker-log4j.xml</spawnedbroker.log4j.configuration.file>
</systemPropertyVariables>
</configuration>
<executions>
diff --git a/qpid/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java b/qpid/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java
index 5c9dc12..9238224 100644
--- a/qpid/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java
+++ b/qpid/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java
@@ -46,7 +46,7 @@
public static final String TEST_RESOURCES_DIR = QPID_HOME + "/../test-profiles/test_resources/";
public static final String TEST_PROFILES_DIR = QPID_HOME + "/../test-profiles/";
public static final String TMP_FOLDER = System.getProperty("java.io.tmpdir");
- public static final String LOG4J_CONFIG_FILE_PATH = System.getProperty("log4j.configuration.file");
+ public static final String SPAWNED_BROKER_LOG4J_CONFIG_FILE_PATH = System.getProperty("spawnedbroker.log4j.configuration.file");
private static final Logger _logger = Logger.getLogger(QpidTestCase.class);
diff --git a/qpid/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/TestSSLConstants.java b/qpid/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/TestSSLConstants.java
index c48f164..96eef79 100644
--- a/qpid/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/TestSSLConstants.java
+++ b/qpid/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/TestSSLConstants.java
@@ -28,6 +28,7 @@
String BROKER_KEYSTORE = "test-profiles/test_resources/ssl/java_broker_keystore.jks";
String BROKER_KEYSTORE_PASSWORD = "password";
+ Object BROKER_KEYSTORE_ALIAS = "rootca";
String BROKER_PEERSTORE = "test-profiles/test_resources/ssl/java_broker_peerstore.jks";
String BROKER_PEERSTORE_PASSWORD = "password";
diff --git a/qpid/java/systests/pom.xml b/qpid/java/systests/pom.xml
index d6c095d..26e1d5b 100644
--- a/qpid/java/systests/pom.xml
+++ b/qpid/java/systests/pom.xml
@@ -189,4 +189,15 @@
</dependencies>
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>${test.resource.directory}/test-profiles/test_resources</directory>
+ </resource>
+ </resources>
+ </build>
+
</project>
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java
index 2c3ad1f..e609d73 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java
@@ -76,7 +76,6 @@
ConfiguredObject.DESCRIPTION,
ConfiguredObject.CONTEXT,
ConfiguredObject.DESIRED_STATE,
- VirtualHost.SUPPORTED_QUEUE_TYPES,
VirtualHost.TYPE);
assertEquals("Unexpected value of attribute " + VirtualHost.NAME,
@@ -93,12 +92,6 @@
virtualHost.get(VirtualHost.QUEUE_DEAD_LETTER_QUEUE_ENABLED));
@SuppressWarnings("unchecked")
- Collection<String> exchangeTypes = (Collection<String>) virtualHost.get(VirtualHost.SUPPORTED_EXCHANGE_TYPES);
- assertEquals("Unexpected value of attribute " + VirtualHost.SUPPORTED_EXCHANGE_TYPES,
- new HashSet<String>(Arrays.asList("headers", "topic", "direct", "fanout")),
- new HashSet<String>(exchangeTypes));
-
- @SuppressWarnings("unchecked")
Map<String, Object> statistics = (Map<String, Object>) virtualHost.get(STATISTICS_ATTRIBUTE);
Asserts.assertAttributesPresent(statistics,
"queueCount","exchangeCount","bytesIn","bytesOut","messagesIn", "messagesOut");
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerHolder.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerHolder.java
index 3af5732..4537d1a 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerHolder.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerHolder.java
@@ -20,10 +20,19 @@
*/
package org.apache.qpid.test.utils;
+import org.apache.qpid.server.BrokerOptions;
+
public interface BrokerHolder
{
- String getWorkingDirectory();
+ public void start(BrokerOptions options) throws Exception;
void shutdown();
void kill();
String dumpThreads();
+
+ enum BrokerType
+ {
+ EXTERNAL /** Test case relies on a Broker started independently of the test-suite */,
+ INTERNAL /** Test case starts an embedded broker within this JVM */,
+ SPAWNED /** Test case spawns a new broker as a separate process */
+ }
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java
index f980453..a76f79f 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java
@@ -21,12 +21,13 @@
package org.apache.qpid.test.utils;
import java.security.PrivilegedAction;
+import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import org.apache.qpid.server.Broker;
-import org.apache.qpid.server.security.auth.TaskPrincipal;
+import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.security.SecurityManager;
import javax.security.auth.Subject;
@@ -35,27 +36,22 @@
{
private static final Logger LOGGER = Logger.getLogger(InternalBrokerHolder.class);
- private final Broker _broker;
- private final String _workingDirectory;
+ private Broker _broker;
private Set<Integer> _portsUsedByBroker;
- public InternalBrokerHolder(final Broker broker, String workingDirectory, Set<Integer> portsUsedByBroker)
+ public InternalBrokerHolder(Set<Integer> portsUsedByBroker)
{
- if(broker == null)
- {
- throw new IllegalArgumentException("Broker must not be null");
- }
-
- _broker = broker;
- _workingDirectory = workingDirectory;
_portsUsedByBroker = portsUsedByBroker;
}
@Override
- public String getWorkingDirectory()
+ public void start(BrokerOptions options) throws Exception
{
- return _workingDirectory;
+ LOGGER.info("Starting internal broker (same JVM)");
+
+ _broker = new Broker();
+ _broker.startup(options);
}
public void shutdown()
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/Piper.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/Piper.java
index 9413e38..12be233 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/Piper.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/Piper.java
@@ -35,27 +35,21 @@
private static final Logger LOGGER = Logger.getLogger(Piper.class);
private final BufferedReader _in;
- private final PrintStream _out;
+ private final Logger _out;
private final String _ready;
private final CountDownLatch _latch;
private final String _stopped;
- private final String _prefix;
private volatile boolean _seenReady;
private volatile String _stopLine;
- public Piper(InputStream in, PrintStream out, String ready, String stopped)
+ public Piper(InputStream in, String ready, String stopped, String threadName, String loggerName)
{
- this(in, out, ready, stopped, null);
- }
-
- public Piper(InputStream in, PrintStream out, String ready, String stopped, String prefix)
- {
+ super(threadName);
_in = new BufferedReader(new InputStreamReader(in));
- _out = out;
+ _out = Logger.getLogger(loggerName);
_ready = ready;
_stopped = stopped;
_seenReady = false;
- _prefix = prefix;
if (this._ready != null && !this._ready.equals(""))
{
@@ -87,11 +81,7 @@
String line;
while ((line = _in.readLine()) != null)
{
- if (_prefix != null)
- {
- line = _prefix + line;
- }
- _out.println(line);
+ _out.info(line);
if (_latch != null && line.contains(_ready))
{
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
index 369a76a..9a33086 100755
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
@@ -18,9 +18,7 @@
package org.apache.qpid.test.utils;
import java.io.File;
-import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -28,7 +26,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.TimeUnit;
import javax.jms.BytesMessage;
import javax.jms.Connection;
@@ -48,8 +45,10 @@
import javax.naming.InitialContext;
import javax.naming.NamingException;
-import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.FileAppender;
+import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
+import org.apache.log4j.xml.DOMConfigurator;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.AMQConnectionFactory;
@@ -60,7 +59,6 @@
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.jms.BrokerDetails;
import org.apache.qpid.jms.ConnectionURL;
-import org.apache.qpid.server.Broker;
import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.configuration.BrokerProperties;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
@@ -83,19 +81,11 @@
{
private TaskExecutor _taskExecutor;
- public enum BrokerType
- {
- EXTERNAL /** Test case relies on a Broker started independently of the test-suite */,
- INTERNAL /** Test case starts an embedded broker within this JVM */,
- SPAWNED /** Test case spawns a new broker as a separate process */
- }
-
public static final String GUEST_USERNAME = "guest";
public static final String GUEST_PASSWORD = "guest";
- protected final static String QpidHome = System.getProperty("QPID_HOME");
private final File _configFile = new File(System.getProperty("broker.config"));
- private File _logConfigFile;
+ private File _spawnedBrokerLogConfigFile;
protected final String _brokerStoreType = System.getProperty("broker.config-store-type", "JSON");
protected static final Logger _logger = Logger.getLogger(QpidBrokerTestCase.class);
protected static final int LOGMONITOR_TIMEOUT = 5000;
@@ -128,11 +118,7 @@
private static final String BROKER_COMMAND_PLATFORM = "broker.command." + SystemUtils.getOSConfigSuffix();
private static final String BROKER_CLEAN_BETWEEN_TESTS = "broker.clean.between.tests";
private static final String BROKER_VERSION = "broker.version";
- protected static final String BROKER_READY = "broker.ready";
- private static final String BROKER_STOPPED = "broker.stopped";
private static final String TEST_OUTPUT = "test.output";
- private static final String BROKER_LOG_INTERLEAVE = "broker.log.interleave";
- private static final String BROKER_LOG_PREFIX = "broker.log.prefix";
private static final String BROKER_PERSITENT = "broker.persistent";
public static final String PROFILE_USE_SSL = "profile.use_ssl";
@@ -141,41 +127,30 @@
public static final int DEFAULT_JMXPORT_REGISTRYSERVER = 8999;
public static final int JMXPORT_CONNECTORSERVER_OFFSET = 100;
public static final int DEFAULT_HTTP_MANAGEMENT_PORT_VALUE = 8080;
- public static final int DEFAULT_HTTPS_MANAGEMENT_PORT_VALUE = 8443;
public static final String TEST_AMQP_PORT_PROTOCOLS_PROPERTY="test.amqp_port_protocols";
// values
protected static final String JAVA = "java";
- protected static final String CPP = "cpp";
-
- protected static final String QPID_HOME = "QPID_HOME";
public static final int DEFAULT_PORT = Integer.getInteger("test.port", DEFAULT_PORT_VALUE);
public static final int FAILING_PORT = Integer.parseInt(System.getProperty("test.port.alt"));
public static final int DEFAULT_MANAGEMENT_PORT = Integer.getInteger("test.mport", DEFAULT_JMXPORT_REGISTRYSERVER);
public static final int DEFAULT_HTTP_MANAGEMENT_PORT = Integer.getInteger("test.hport", DEFAULT_HTTP_MANAGEMENT_PORT_VALUE);
- public static final int DEFAULT_HTTPS_MANAGEMENT_PORT = Integer.getInteger("test.hsport", DEFAULT_HTTPS_MANAGEMENT_PORT_VALUE);
public static final int DEFAULT_SSL_PORT = Integer.getInteger("test.port.ssl", DEFAULT_SSL_PORT_VALUE);
protected String _brokerLanguage = System.getProperty(BROKER_LANGUAGE, JAVA);
- protected BrokerType _brokerType = BrokerType.valueOf(System.getProperty(BROKER_TYPE, "").toUpperCase());
+ protected BrokerHolder.BrokerType _brokerType = BrokerHolder.BrokerType.valueOf(System.getProperty(BROKER_TYPE, "").toUpperCase());
private static final String BROKER_COMMAND_TEMPLATE = System.getProperty(BROKER_COMMAND_PLATFORM, System.getProperty(BROKER_COMMAND));
- protected BrokerCommandHelper _brokerCommandHelper = new BrokerCommandHelper(BROKER_COMMAND_TEMPLATE);
private Boolean _brokerCleanBetweenTests = Boolean.getBoolean(BROKER_CLEAN_BETWEEN_TESTS);
private final Protocol _brokerProtocol = Protocol.valueOf("AMQP_" + System.getProperty(BROKER_VERSION, " ").substring(1));
protected String _output = System.getProperty(TEST_OUTPUT, System.getProperty("java.io.tmpdir"));
protected Boolean _brokerPersistent = Boolean.getBoolean(BROKER_PERSITENT);
- protected static String _brokerLogPrefix = System.getProperty(BROKER_LOG_PREFIX,"BROKER: ");
- protected static boolean _interleaveBrokerLog = Boolean.valueOf(System.getProperty(BROKER_LOG_INTERLEAVE,"true"));
-
protected File _outputFile;
- protected PrintStream _testcaseOutputStream;
-
protected Map<Integer, BrokerHolder> _brokers = new HashMap<Integer, BrokerHolder>();
protected InitialContext _initialContext;
@@ -195,6 +170,8 @@
/** Size to create our message*/
private int _messageSize = DEFAULT_MESSAGE_SIZE;
+ private String _brokerCommandTemplate;
+
/** Type of message*/
protected enum MessageType
{
@@ -210,7 +187,8 @@
{
super();
_brokerConfigurations = new HashMap<Integer, TestBrokerConfiguration>();
- initialiseLogConfigFile();
+ initialiseSpawnedBrokerLogConfigFile();
+ _brokerCommandTemplate = BROKER_COMMAND_TEMPLATE;
}
public TestBrokerConfiguration getBrokerConfiguration(int port)
@@ -259,12 +237,12 @@
return configuration;
}
- private void initialiseLogConfigFile()
+ private void initialiseSpawnedBrokerLogConfigFile()
{
- _logConfigFile = new File(LOG4J_CONFIG_FILE_PATH);
- if(!_logConfigFile.exists())
+ _spawnedBrokerLogConfigFile = new File(SPAWNED_BROKER_LOG4J_CONFIG_FILE_PATH);
+ if(!_spawnedBrokerLogConfigFile.exists())
{
- throw new RuntimeException("Log config file " + _logConfigFile.getAbsolutePath() + " does not exist");
+ throw new RuntimeException("Log config file " + _spawnedBrokerLogConfigFile.getAbsolutePath() + " does not exist");
}
}
@@ -276,36 +254,18 @@
@Override
public void runBare() throws Throwable
{
- String qname = getClass().getName() + "." + getName();
-
// Initialize this for each test run
_env = new HashMap<String, String>();
- PrintStream oldOut = System.out;
- PrintStream oldErr = System.err;
- PrintStream out = null;
- PrintStream err = null;
+ // Log4j properties expects this to be set
+ System.setProperty("qpid.testMethod", "-" + getName());
+ System.setProperty("qpid.testClass", getClass().getName());
- boolean redirected = _output != null && _output.length() > 0;
- if (redirected)
- {
- _outputFile = new File(String.format("%s/TEST-%s.out", _output, qname));
- out = new PrintStream(new FileOutputStream(_outputFile), true);
- err = new PrintStream(String.format("%s/TEST-%s.err", _output, qname));
+ String log4jConfigFile = System.getProperty("log4j.configuration.file");
+ DOMConfigurator.configure(log4jConfigFile);
- System.setOut(out);
- System.setErr(err);
-
- if (_interleaveBrokerLog)
- {
- _testcaseOutputStream = out;
- }
- else
- {
- _testcaseOutputStream = new PrintStream(new FileOutputStream(String
- .format("%s/TEST-%s.broker.out", _output, qname)), true);
- }
- }
+ // get log file from file appender
+ _outputFile = new File(((FileAppender)LogManager.getRootLogger().getAllAppenders().nextElement()).getFile());
try
{
@@ -324,7 +284,7 @@
revertSystemProperties();
revertLoggingLevels();
- if(_brokerCleanBetweenTests)
+ if (_brokerCleanBetweenTests)
{
final String qpidWork = System.getProperty("QPID_WORK");
cleanBrokerWork(qpidWork);
@@ -333,17 +293,7 @@
_logger.info("========== stop " + getTestName() + " ==========");
- if (redirected)
- {
- System.setErr(oldErr);
- System.setOut(oldOut);
- err.close();
- out.close();
- if (!_interleaveBrokerLog)
- {
- _testcaseOutputStream.close();
- }
- }
+ LogManager.resetConfiguration();
}
}
@@ -403,7 +353,7 @@
protected int getPort(int port)
{
- if (!_brokerType.equals(BrokerType.EXTERNAL))
+ if (!_brokerType.equals(BrokerHolder.BrokerType.EXTERNAL))
{
return port == 0 ? DEFAULT_PORT : port;
}
@@ -425,28 +375,33 @@
public void startBroker(int port, boolean managementMode) throws Exception
{
+ startBroker(port, managementMode, null);
+ }
+
+ public void startBroker(int port, boolean managementMode, String log4jFile) throws Exception
+ {
int actualPort = getPort(port);
TestBrokerConfiguration configuration = getBrokerConfiguration(actualPort);
- startBroker(actualPort, configuration, managementMode);
+ startBroker(actualPort, configuration, managementMode, log4jFile);
}
protected File getBrokerCommandLog4JFile()
{
- return _logConfigFile;
+ return _spawnedBrokerLogConfigFile;
}
protected void setBrokerCommandLog4JFile(File file)
{
- _logConfigFile = file;
+ _spawnedBrokerLogConfigFile = file;
_logger.info("Modified log config file to: " + file);
}
- public void startBroker(int port, TestBrokerConfiguration testConfiguration) throws Exception
+ public void startBroker(int port, TestBrokerConfiguration testConfiguration, String log4jFile) throws Exception
{
- startBroker(port, testConfiguration, false);
+ startBroker(port, testConfiguration, false, log4jFile);
}
- public void startBroker(int port, TestBrokerConfiguration testConfiguration, boolean managementMode) throws Exception
+ protected void startBroker(int port, TestBrokerConfiguration testConfiguration, boolean managementMode, String log4jFile) throws Exception
{
port = getPort(port);
@@ -455,181 +410,12 @@
throw new IllegalStateException("There is already an existing broker running on port " + port);
}
- Set<Integer> portsUsedByBroker = guessAllPortsUsedByBroker(port);
String testConfig = saveTestConfiguration(port, testConfiguration);
-
- if (_brokerType.equals(BrokerType.INTERNAL) && !existingInternalBroker())
- {
- setSystemProperty(BrokerProperties.PROPERTY_USE_CUSTOM_RMI_SOCKET_FACTORY, "false");
- BrokerOptions options = new BrokerOptions();
-
- options.setConfigurationStoreType(_brokerStoreType);
- options.setConfigurationStoreLocation(testConfig);
- options.setManagementMode(managementMode);
- if (managementMode)
- {
- options.setManagementModePassword(MANAGEMENT_MODE_PASSWORD);
- }
-
- //Set the log config file, relying on the log4j.configuration system property
- //set on the JVM by the JUnit runner task in module.xml.
- options.setLogConfigFileLocation(_logConfigFile.getAbsolutePath());
-
- Broker broker = new Broker();
- _logger.info("Starting internal broker (same JVM)");
- broker.startup(options);
-
- _brokers.put(port, new InternalBrokerHolder(broker, System.getProperty("QPID_WORK"), portsUsedByBroker));
- }
- else if (!_brokerType.equals(BrokerType.EXTERNAL))
- {
- // Add the port to QPID_WORK to ensure unique working dirs for multi broker tests
- final String qpidWork = getQpidWork(_brokerType, port);
-
- String[] cmd = _brokerCommandHelper.getBrokerCommand(port, testConfig, _brokerStoreType, _logConfigFile);
- if (managementMode)
- {
- String[] newCmd = new String[cmd.length + 3];
- System.arraycopy(cmd, 0, newCmd, 0, cmd.length);
- newCmd[cmd.length] = "-mm";
- newCmd[cmd.length + 1] = "-mmpass";
- newCmd[cmd.length + 2] = MANAGEMENT_MODE_PASSWORD;
- cmd = newCmd;
- }
- _logger.info("Starting spawn broker using command: " + StringUtils.join(cmd, ' '));
- ProcessBuilder pb = new ProcessBuilder(cmd);
- pb.redirectErrorStream(true);
- Map<String, String> processEnv = pb.environment();
- String qpidHome = System.getProperty(QPID_HOME);
- processEnv.put(QPID_HOME, qpidHome);
- //Augment Path with bin directory in QPID_HOME.
- boolean foundPath = false;
- final String pathEntry = qpidHome + File.separator + "bin";
- for(Map.Entry<String,String> entry : processEnv.entrySet())
- {
- if(entry.getKey().equalsIgnoreCase("path"))
- {
- entry.setValue(entry.getValue().concat(File.pathSeparator + pathEntry));
- foundPath = true;
- }
- }
- if(!foundPath)
- {
- processEnv.put("PATH", pathEntry);
-
- }
- //Add the test name to the broker run.
- // DON'T change PNAME, qpid.stop needs this value.
- processEnv.put("QPID_PNAME", "-DPNAME=QPBRKR -DTNAME=\"" + getTestName() + "\"");
- processEnv.put("QPID_WORK", qpidWork);
-
- // Use the environment variable to set amqj.logging.level for the broker
- // The value used is a 'server' value in the test configuration to
- // allow a differentiation between the client and broker logging levels.
- if (System.getProperty("amqj.server.logging.level") != null)
- {
- setBrokerEnvironment("AMQJ_LOGGING_LEVEL", System.getProperty("amqj.server.logging.level"));
- }
-
- // Add all the environment settings the test requested
- if (!_env.isEmpty())
- {
- for (Map.Entry<String, String> entry : _env.entrySet())
- {
- processEnv.put(entry.getKey(), entry.getValue());
- }
- }
-
- String qpidOpts = "";
-
- // a synchronized hack to avoid adding into QPID_OPTS the values
- // of JVM properties "test.virtualhosts" and "test.config" set by a concurrent startup process
- synchronized (_propertiesSetForBroker)
- {
- // Add default test logging levels that are used by the log4j-test
- // Use the convenience methods to push the current logging setting
- // in to the external broker's QPID_OPTS string.
- setSystemProperty("amqj.protocol.logging.level");
- setSystemProperty("root.logging.level");
-
- setSystemProperty("test.port");
- setSystemProperty("test.mport");
- setSystemProperty("test.cport");
- setSystemProperty("test.hport");
- setSystemProperty("test.hsport");
- setSystemProperty("test.port.ssl");
- setSystemProperty("test.port.alt");
- setSystemProperty("test.port.alt.ssl");
- setSystemProperty("test.amqp_port_protocols");
-
- setSystemProperty("virtualhostnode.type");
- setSystemProperty("virtualhostnode.context.blueprint");
-
- // Add all the specified system properties to QPID_OPTS
- if (!_propertiesSetForBroker.isEmpty())
- {
- for (String key : _propertiesSetForBroker.keySet())
- {
- qpidOpts += " -D" + key + "=" + _propertiesSetForBroker.get(key);
- }
- }
- }
- if (processEnv.containsKey("QPID_OPTS"))
- {
- qpidOpts = processEnv.get("QPID_OPTS") + qpidOpts;
- }
- processEnv.put("QPID_OPTS", qpidOpts);
-
- // cpp broker requires that the work directory is created
- createBrokerWork(qpidWork);
-
- Process process = pb.start();
-
- Piper p = new Piper(process.getInputStream(),
- _testcaseOutputStream,
- System.getProperty(BROKER_READY),
- System.getProperty(BROKER_STOPPED),
- _interleaveBrokerLog ? _brokerLogPrefix : null);
-
- p.start();
- StringBuilder cmdLine = new StringBuilder(cmd[0]);
- for(int i = 1; i< cmd.length; i++)
- {
- cmdLine.append(' ');
- cmdLine.append(cmd[i]);
- }
-
- SpawnedBrokerHolder holder = new SpawnedBrokerHolder(process, qpidWork, portsUsedByBroker, cmdLine.toString());
- if (!p.await(30, TimeUnit.SECONDS))
- {
- _logger.info("broker failed to become ready (" + p.getReady() + "):" + p.getStopLine());
- String threadDump = holder.dumpThreads();
- if (!threadDump.isEmpty())
- {
- _logger.info("the result of a try to capture thread dump:" + threadDump);
- }
- //Ensure broker has stopped
- process.destroy();
- cleanBrokerWork(qpidWork);
- throw new RuntimeException("broker failed to become ready:"
- + p.getStopLine());
- }
-
- try
- {
- //test that the broker is still running and hasn't exited unexpectedly
- int exit = process.exitValue();
- _logger.info("broker aborted: " + exit);
- cleanBrokerWork(qpidWork);
- throw new RuntimeException("broker aborted: " + exit);
- }
- catch (IllegalThreadStateException e)
- {
- // this is expect if the broker started successfully
- }
-
- _brokers.put(port, holder);
- }
+ String log4jConfig = log4jFile == null ? getBrokerCommandLog4JFile().getAbsolutePath() : log4jFile;
+ BrokerOptions options = getBrokerOptions(managementMode, testConfig, log4jConfig, log4jFile == null);
+ BrokerHolder holder = new BrokerHolderFactory().create(_brokerType, port, this);
+ _brokers.put(port, holder);
+ holder.start(options);
}
private boolean existingInternalBroker()
@@ -645,21 +431,6 @@
return false;
}
- private String getQpidWork(BrokerType broker, int port)
- {
- if (!broker.equals(BrokerType.EXTERNAL))
- {
- return System.getProperty("QPID_WORK")+ "/" + port;
- }
-
- return System.getProperty("QPID_WORK");
- }
-
- public String getTestConfigFile()
- {
- return getTestConfigFile(getPort());
- }
-
public String getTestConfigFile(int port)
{
return _output + File.separator + getTestQueueName() + "-" + port + "-config";
@@ -1035,7 +806,7 @@
protected boolean isInternalBroker()
{
- return _brokerType.equals(BrokerType.INTERNAL);
+ return _brokerType.equals(BrokerHolder.BrokerType.INTERNAL);
}
protected boolean isBrokerStorePersistent()
@@ -1397,16 +1168,6 @@
return message;
}
- protected int getMessageSize()
- {
- return _messageSize;
- }
-
- protected void setMessageSize(int byteSize)
- {
- _messageSize = byteSize;
- }
-
public BrokerDetails getBroker()
{
try
@@ -1453,4 +1214,91 @@
session.commit();
session.close();
}
+
+ protected BrokerOptions getBrokerOptions( boolean managementMode, String testConfig, String log4jConfig, boolean skipLoggingConfiguration)
+ {
+ BrokerOptions options = new BrokerOptions();
+
+ options.setConfigurationStoreType(_brokerStoreType);
+ options.setConfigurationStoreLocation(testConfig);
+ options.setManagementMode(managementMode);
+ if (managementMode)
+ {
+ options.setManagementModePassword(MANAGEMENT_MODE_PASSWORD);
+ }
+ options.setSkipLoggingConfiguration(skipLoggingConfiguration);
+ options.setLogConfigFileLocation(log4jConfig);
+ options.setStartupLoggedToSystemOut(false);
+ return options;
+ }
+
+ private Map<String, String> getJvmProperties()
+ {
+ Map<String,String> jvmOptions = new HashMap();
+ synchronized (_propertiesSetForBroker)
+ {
+ jvmOptions.putAll(_propertiesSetForBroker);
+
+ copySystemProperty("amqj.protocol.logging.level", jvmOptions);
+ copySystemProperty("root.logging.level", jvmOptions);
+
+ copySystemProperty("test.port", jvmOptions);
+ copySystemProperty("test.mport", jvmOptions);
+ copySystemProperty("test.cport", jvmOptions);
+ copySystemProperty("test.hport", jvmOptions);
+ copySystemProperty("test.hsport", jvmOptions);
+ copySystemProperty("test.port.ssl", jvmOptions);
+ copySystemProperty("test.port.alt", jvmOptions);
+ copySystemProperty("test.port.alt.ssl", jvmOptions);
+ copySystemProperty("test.amqp_port_protocols", jvmOptions);
+
+ copySystemProperty("virtualhostnode.type", jvmOptions);
+ copySystemProperty("virtualhostnode.context.blueprint", jvmOptions);
+ }
+ return jvmOptions;
+ }
+
+ private void copySystemProperty(String name, Map<String, String> jvmOptions)
+ {
+ String value = System.getProperty(name);
+ if (value != null)
+ {
+ jvmOptions.put(name, value);
+ }
+ }
+
+ private Map<String, String> getEnvironmentProperties()
+ {
+ return new HashMap<>(_env);
+ }
+
+ private String getBrokerCommandTemplate()
+ {
+ return _brokerCommandTemplate;
+ }
+
+ public static class BrokerHolderFactory
+ {
+
+ public BrokerHolder create(BrokerHolder.BrokerType brokerType, int port, QpidBrokerTestCase testCase)
+ {
+ Set<Integer> portsUsedByBroker = testCase.guessAllPortsUsedByBroker(port);
+ BrokerHolder holder = null;
+ if (brokerType.equals(BrokerHolder.BrokerType.INTERNAL) && !testCase.existingInternalBroker())
+ {
+ testCase.setSystemProperty(BrokerProperties.PROPERTY_USE_CUSTOM_RMI_SOCKET_FACTORY, "false");
+ holder = new InternalBrokerHolder(portsUsedByBroker);
+ }
+ else if (!brokerType.equals(BrokerHolder.BrokerType.EXTERNAL))
+ {
+
+ Map<String,String> jvmOptions = testCase.getJvmProperties();
+ Map<String,String> environmentProperties = testCase.getEnvironmentProperties();
+
+ holder = new SpawnedBrokerHolder(testCase.getBrokerCommandTemplate(), port, testCase.getTestName(), jvmOptions, environmentProperties, brokerType, portsUsedByBroker);
+ }
+ return holder;
+ }
+ }
+
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java
index 4b747e8..2581093 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java
@@ -22,6 +22,7 @@
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -30,39 +31,215 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
+import org.apache.qpid.server.BrokerOptions;
+import org.apache.qpid.server.configuration.BrokerProperties;
+import org.apache.qpid.server.logging.messages.BrokerMessages;
+import org.apache.qpid.util.FileUtils;
import org.apache.qpid.util.SystemUtils;
public class SpawnedBrokerHolder implements BrokerHolder
{
private static final Logger LOGGER = Logger.getLogger(SpawnedBrokerHolder.class);
+ protected static final String BROKER_READY = System.getProperty("broker.ready", BrokerMessages.READY().toString());
+ private static final String BROKER_STOPPED = System.getProperty("broker.stopped", BrokerMessages.STOPPED().toString());
- private final Process _process;
- private final Integer _pid;
- private final String _workingDirectory;
+ private final BrokerType _type;
+ private final int _port;
+ private final String _name;
+ private final Map<String, String> _jvmOptions;
+ private final Map<String, String> _environmentSettings;
+ protected BrokerCommandHelper _brokerCommandHelper;
+
+ private Process _process;
+ private Integer _pid;
private Set<Integer> _portsUsedByBroker;
- private final String _brokerCommand;
+ private String _brokerCommand;
- public SpawnedBrokerHolder(final Process process, final String workingDirectory, Set<Integer> portsUsedByBroker,
- String brokerCmd)
+ public SpawnedBrokerHolder(String brokerCommandTemplate, int port, String name, Map<String, String> jvmOptions, Map<String, String> environmentSettings, BrokerType type, Set<Integer> portsUsedByBroker)
{
- if(process == null)
- {
- throw new IllegalArgumentException("Process must not be null");
- }
-
- _process = process;
- _pid = retrieveUnixPidIfPossible();
- _workingDirectory = workingDirectory;
+ _type = type;
_portsUsedByBroker = portsUsedByBroker;
- _brokerCommand = brokerCmd;
+ _port = port;
+ _name = name;
+ _jvmOptions = jvmOptions;
+ _environmentSettings = environmentSettings;
+ _brokerCommandHelper = new BrokerCommandHelper(brokerCommandTemplate);
}
+
@Override
- public String getWorkingDirectory()
+ public void start(BrokerOptions brokerOptions) throws Exception
{
- return _workingDirectory;
+ // Add the port to QPID_WORK to ensure unique working dirs for multi broker tests
+ final String qpidWork = getQpidWork(_type, _port);
+
+ String[] cmd = _brokerCommandHelper.getBrokerCommand(_port, brokerOptions.getConfigurationStoreLocation(), brokerOptions.getConfigurationStoreType(),
+ new File(brokerOptions.getLogConfigFileLocation()));
+ if (brokerOptions.isManagementMode())
+ {
+ String[] newCmd = new String[cmd.length + 3];
+ System.arraycopy(cmd, 0, newCmd, 0, cmd.length);
+ newCmd[cmd.length] = "-mm";
+ newCmd[cmd.length + 1] = "-mmpass";
+ newCmd[cmd.length + 2] = brokerOptions.getManagementModePassword();
+ cmd = newCmd;
+ }
+ ProcessBuilder pb = new ProcessBuilder(cmd);
+ pb.redirectErrorStream(true);
+ Map<String, String> processEnv = pb.environment();
+ String qpidHome = System.getProperty(BrokerProperties.PROPERTY_QPID_HOME);
+ processEnv.put(BrokerProperties.PROPERTY_QPID_HOME, qpidHome);
+
+ //Augment Path with bin directory in QPID_HOME.
+ boolean foundPath = false;
+ final String pathEntry = qpidHome + File.separator + "bin";
+ for(Map.Entry<String,String> entry : processEnv.entrySet())
+ {
+ if(entry.getKey().equalsIgnoreCase("path"))
+ {
+ entry.setValue(entry.getValue().concat(File.pathSeparator + pathEntry));
+ foundPath = true;
+ }
+ }
+ if(!foundPath)
+ {
+ processEnv.put("PATH", pathEntry);
+ }
+ //Add the test name to the broker run.
+ // DON'T change PNAME, qpid.stop needs this value.
+ processEnv.put("QPID_PNAME", "-DPNAME=QPBRKR -DTNAME=\"" + _name + "\"");
+ processEnv.put("QPID_WORK", qpidWork);
+
+ // Use the environment variable to set amqj.logging.level for the broker
+ // The value used is a 'server' value in the test configuration to
+ // allow a differentiation between the client and broker logging levels.
+ if (System.getProperty("amqj.server.logging.level") != null)
+ {
+ processEnv.put("AMQJ_LOGGING_LEVEL", System.getProperty("amqj.server.logging.level"));
+ }
+
+ // Add all the environment settings the test requested
+ if (!_environmentSettings.isEmpty())
+ {
+ for (Map.Entry<String, String> entry : _environmentSettings.entrySet())
+ {
+ processEnv.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ String qpidOpts = "";
+
+ // Add all the specified system properties to QPID_OPTS
+ if (!_jvmOptions.isEmpty())
+ {
+ for (String key : _jvmOptions.keySet())
+ {
+ qpidOpts += " -D" + key + "=" + _jvmOptions.get(key);
+ }
+ }
+
+ if (processEnv.containsKey("QPID_OPTS"))
+ {
+ qpidOpts = processEnv.get("QPID_OPTS") + qpidOpts;
+ }
+ processEnv.put("QPID_OPTS", qpidOpts);
+
+ // cpp broker requires that the work directory is created
+ createBrokerWork(qpidWork);
+
+ _process = pb.start();
+
+ Piper standardOutputPiper = new Piper(_process.getInputStream(),
+ BROKER_READY,
+ BROKER_STOPPED,
+ "STD", "BROKER-" + _port);
+
+ standardOutputPiper.start();
+
+ new Piper(_process.getErrorStream(), null, null, "ERROR", "BROKER-" + _port).start();
+
+ StringBuilder cmdLine = new StringBuilder(cmd[0]);
+ for(int i = 1; i< cmd.length; i++)
+ {
+ cmdLine.append(' ');
+ cmdLine.append(cmd[i]);
+ }
+
+ _brokerCommand = cmdLine.toString();
+ _pid = retrieveUnixPidIfPossible();
+
+ if (!standardOutputPiper.await(30, TimeUnit.SECONDS))
+ {
+ LOGGER.info("broker failed to become ready (" + standardOutputPiper.getReady() + "):" + standardOutputPiper.getStopLine());
+ String threadDump = dumpThreads();
+ if (!threadDump.isEmpty())
+ {
+ LOGGER.info("the result of a try to capture thread dump:" + threadDump);
+ }
+ //Ensure broker has stopped
+ _process.destroy();
+ cleanBrokerWork(qpidWork);
+ throw new RuntimeException("broker failed to become ready:"
+ + standardOutputPiper.getStopLine());
+ }
+
+ try
+ {
+ //test that the broker is still running and hasn't exited unexpectedly
+ int exit = _process.exitValue();
+ LOGGER.info("broker aborted: " + exit);
+ cleanBrokerWork(qpidWork);
+ throw new RuntimeException("broker aborted: " + exit);
+ }
+ catch (IllegalThreadStateException e)
+ {
+ // this is expect if the broker started successfully
+ }
+
+ }
+
+ protected void createBrokerWork(final String qpidWork)
+ {
+ if (qpidWork != null)
+ {
+ final File dir = new File(qpidWork);
+ dir.mkdirs();
+ if (!dir.isDirectory())
+ {
+ throw new RuntimeException("Failed to created Qpid work directory : " + qpidWork);
+ }
+ }
+ }
+
+ private String getQpidWork(BrokerType broker, int port)
+ {
+ if (!broker.equals(BrokerType.EXTERNAL))
+ {
+ return System.getProperty(BrokerProperties.PROPERTY_QPID_WORK) + File.separator + port;
+ }
+
+ return System.getProperty(BrokerProperties.PROPERTY_QPID_WORK);
+ }
+
+ private void cleanBrokerWork(final String qpidWork)
+ {
+ if (qpidWork != null)
+ {
+ LOGGER.info("Cleaning broker work dir: " + qpidWork);
+
+ File file = new File(qpidWork);
+ if (file.exists())
+ {
+ final boolean success = FileUtils.delete(file, true);
+ if(!success)
+ {
+ throw new RuntimeException("Failed to recursively delete beneath : " + file);
+ }
+ }
+ }
}
public void shutdown()
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java
index fb254f5..549edcd 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java
@@ -44,21 +44,7 @@
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.AbstractSystemConfig;
-import org.apache.qpid.server.model.AccessControlProvider;
-import org.apache.qpid.server.model.AuthenticationProvider;
-import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.model.BrokerModel;
-import org.apache.qpid.server.model.BrokerShutdownProvider;
-import org.apache.qpid.server.model.ConfiguredObject;
-import org.apache.qpid.server.model.GroupProvider;
-import org.apache.qpid.server.model.JsonSystemConfigImpl;
-import org.apache.qpid.server.model.Plugin;
-import org.apache.qpid.server.model.PreferencesProvider;
-import org.apache.qpid.server.model.SystemConfig;
-import org.apache.qpid.server.model.UUIDGenerator;
-import org.apache.qpid.server.model.VirtualHostAlias;
-import org.apache.qpid.server.model.VirtualHostNode;
+import org.apache.qpid.server.model.*;
import org.apache.qpid.server.model.adapter.FileBasedGroupProvider;
import org.apache.qpid.server.model.adapter.FileBasedGroupProviderImpl;
import org.apache.qpid.server.plugin.PluggableFactoryLoader;
@@ -108,7 +94,7 @@
final AbstractSystemConfig parentObject = new JsonSystemConfigImpl(taskExecutor,
mock(EventLogger.class),
mock(LogRecorder.class),
- brokerOptions,
+ brokerOptions.convertToSystemConfigAttributes(),
mock(BrokerShutdownProvider.class));
ConfiguredObjectRecordConverter converter = new ConfiguredObjectRecordConverter(BrokerModel.getInstance());
@@ -216,10 +202,13 @@
SystemConfigFactory configFactory =
(new PluggableFactoryLoader<>(SystemConfigFactory.class)).get(_storeType);
+ Map<String, Object> attributes = new HashMap<>(brokerOptions.convertToSystemConfigAttributes());
+ attributes.put(SystemConfig.STARTUP_LOGGED_TO_SYSTEM_OUT, false);
+ attributes.put(ConfiguredObject.DESIRED_STATE, State.QUIESCED);
final SystemConfig parentObject = configFactory.newInstance(_taskExecutor,
mock(EventLogger.class),
mock(LogRecorder.class),
- brokerOptions,
+ attributes,
mock(BrokerShutdownProvider.class));
parentObject.open();
@@ -252,6 +241,7 @@
configurationStore.openConfigurationStore(parentObject,true,initialRecords.toArray(new ConfiguredObjectRecord[initialRecords.size()]));
configurationStore.closeConfigurationStore();
+ parentObject.close();
return true;
}
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/client/HeartbeatTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/client/HeartbeatTest.java
index 881a37a..6612fed 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/client/HeartbeatTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/client/HeartbeatTest.java
@@ -120,12 +120,15 @@
sendConn.setHeartbeatListener(sendListener);
receiveConn.start();
+ // Start the flow of messages to the consumer
+ consumer.receiveNoWait();
+
for(int i = 0; i < 5; i++)
{
producer.send(senderSession.createTextMessage("Msg " + i));
Thread.sleep(500);
assertNotNull("Expected to received message", consumer.receive(500));
- // Consumer does not ack the message in order to generate no bytes from consumer back to Broker
+ // Consumer does not ack the message in order that no bytes flow from consumer connection back to Broker
}
assertTrue("Too few heartbeats sent "+ receiveListener.getHeartbeatsSent() +" (expected at least 2)", receiveListener.getHeartbeatsSent()>=2);
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/client/failover/MultipleBrokersFailoverTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/client/failover/MultipleBrokersFailoverTest.java
index 15ec0f9..c59b0ec 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/client/failover/MultipleBrokersFailoverTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/client/failover/MultipleBrokersFailoverTest.java
@@ -38,7 +38,6 @@
import org.apache.qpid.client.AMQConnectionURL;
import org.apache.qpid.jms.ConnectionListener;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
-import org.apache.qpid.test.utils.TestUtils;
import org.apache.qpid.util.FileUtils;
public class MultipleBrokersFailoverTest extends QpidBrokerTestCase implements ConnectionListener
@@ -48,9 +47,10 @@
private static final String FAILOVER_VIRTUAL_HOST = "failover";
private static final String NON_FAILOVER_VIRTUAL_HOST = "nonfailover";
private static final String BROKER_PORTION_FORMAT = "tcp://localhost:%d?connectdelay='%d',retries='%d'";
- private static final int FAILOVER_RETRIES = 1;
- private static final int FAILOVER_CONNECTDELAY = 1000;
- private static final int FAILOVER_FACTOR = 4;
+ private static final int FAILOVER_RETRIES = 0;
+ private static final int FAILOVER_CONNECTDELAY = 0;
+ private static final int FAILOVER_AWAIT_TIME = 10000;
+
private int[] _brokerPorts;
private AMQConnectionURL _connectionURL;
@@ -169,7 +169,7 @@
killBroker(_brokerPorts[1]);
- awaitForFailoverCompletion(FAILOVER_CONNECTDELAY * _brokerPorts.length * FAILOVER_FACTOR);
+ awaitForFailoverCompletion(FAILOVER_AWAIT_TIME);
assertEquals("Failover is not started as expected", 0, _failoverStarted.getCount());
assertSendReceive(2);
@@ -185,7 +185,7 @@
stopBroker(_brokerPorts[1]);
- awaitForFailoverCompletion(FAILOVER_CONNECTDELAY * _brokerPorts.length * FAILOVER_FACTOR);
+ awaitForFailoverCompletion(FAILOVER_AWAIT_TIME);
assertEquals("Failover is not started as expected", 0, _failoverStarted.getCount());
assertSendReceive(1);
@@ -214,20 +214,12 @@
}
}
- private void awaitForFailoverCompletion(long delay)
+ private void awaitForFailoverCompletion(long delay) throws Exception
{
_logger.info("Awaiting Failover completion..");
- try
+ if (!_failoverComplete.await(delay, TimeUnit.MILLISECONDS))
{
- if (!_failoverComplete.await(delay, TimeUnit.MILLISECONDS))
- {
- _logger.warn("Test thread stack:\n\n" + TestUtils.dumpThreads());
- fail("Failover did not complete");
- }
- }
- catch (InterruptedException e)
- {
- fail("Test was interrupted:" + e.getMessage());
+ fail("Failover did not complete within " + delay + "ms.");
}
}
@@ -239,7 +231,7 @@
receivedMessage instanceof TextMessage);
}
- private void init(int acknowledgeMode, boolean startConnection) throws JMSException
+ private void init(int acknowledgeMode, boolean startConnection) throws Exception
{
boolean isTransacted = acknowledgeMode == Session.SESSION_TRANSACTED ? true : false;
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/client/ssl/SSLTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/client/ssl/SSLTest.java
index 1dba5ce..7c82ea8 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/client/ssl/SSLTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/client/ssl/SSLTest.java
@@ -94,6 +94,29 @@
}
}
+ public void testSSLConnectionToPlainPortRejected() throws Exception
+ {
+ if (shouldPerformTest())
+ {
+ super.setUp();
+
+ String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s" +
+ "?ssl='true''";
+
+ url = String.format(url,QpidBrokerTestCase.DEFAULT_PORT);
+
+ try
+ {
+ getConnection(new AMQConnectionURL(url));
+ fail("Exception not thrown");
+ }
+ catch (JMSException e)
+ {
+ assertTrue("Unexpected exception message", e.getMessage().contains("Unrecognized SSL message, plaintext connection?"));
+ }
+ }
+ }
+
public void testHostVerificationIsOnByDefault() throws Exception
{
if (shouldPerformTest())
@@ -116,6 +139,7 @@
try
{
getConnection(new AMQConnectionURL(url));
+ fail("Exception not thrown");
}
catch(JMSException e)
{
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/server/BrokerStartupTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/server/BrokerStartupTest.java
index e267bf4..c475432 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/server/BrokerStartupTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/server/BrokerStartupTest.java
@@ -77,7 +77,7 @@
brokerConfigFile.delete();
}
- startBroker(port, null);
+ startBroker(port, null, null);
AMQConnectionURL url = new AMQConnectionURL(String.format("amqp://"
+ GUEST_USERNAME
@@ -209,7 +209,7 @@
brokerConfigFile.delete();
}
- startBroker(port, null);
+ startBroker(port, null, null);
AMQConnectionURL url = new AMQConnectionURL(String.format("amqp://"
+ GUEST_USERNAME
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/server/logging/BrokerLoggingTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/server/logging/BrokerLoggingTest.java
index 4952c4e..f7953e5 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/server/logging/BrokerLoggingTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/server/logging/BrokerLoggingTest.java
@@ -22,13 +22,15 @@
import junit.framework.AssertionFailedError;
-import org.apache.qpid.server.BrokerOptions;
+import org.apache.log4j.FileAppender;
+import org.apache.log4j.LogManager;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.Transport;
import org.apache.qpid.test.utils.TestBrokerConfiguration;
import org.apache.qpid.transport.ConnectionException;
import org.apache.qpid.util.LogMonitor;
+import java.io.File;
import java.io.IOException;
import java.net.Socket;
import java.util.Collections;
@@ -59,6 +61,7 @@
private static final Pattern BROKER_MESSAGE_LOG_PATTERN = Pattern.compile(BROKER_MESSAGE_LOG_REG_EXP);
private static final String BRK_LOG_PREFIX = "BRK-";
+ @Override
public void setUp() throws Exception
{
setLogMessagePrefix();
@@ -146,94 +149,6 @@
/**
* Description:
- * On startup the broker must report correctly report the log4j file in use. This is important as it can help diagnose why logging messages are not being reported.
- * Input:
- * No custom -l value should be provided on the command line so that the default value is correctly reported.
- * Output:
- *
- * <date> MESSAGE BRK-1007 : Using logging configuration : <$QPID_HOME>/etc/log4j.xml
- *
- * Validation Steps:
- *
- * 1. The BRK ID is correct
- * 2. This occurs before the BRK-1001 startup message.
- * 3. The log4j file is the full path to the file specified on the commandline.
- *
- * @throws Exception caused by broker startup
- */
- public void testBrokerStartupDefaultLog4j() throws Exception
- {
- if (isJavaBroker() && isExternalBroker() && !isInternalBroker())
- {
- String TESTID = "BRK-1007";
-
- _brokerCommandHelper.removeBrokerCommandLog4JFile();
-
- startBroker();
-
- // Now we can create the monitor as _outputFile will now be defined
- _monitor = new LogMonitor(_outputFile);
-
- // Ensure broker has fully started up.
- getConnection();
-
- // Ensure we wait for TESTID to be logged
- waitAndFindMatches(TESTID);
-
- List<String> results = waitAndFindMatches(BRK_LOG_PREFIX);
- try
- {
- // Validation
-
- assertTrue("BRKer message not logged", results.size() > 0);
-
- boolean validation = false;
- for (String rawLog : results)
- {
- // We don't care about messages after we have our log config
- if (validation)
- {
- break;
- }
-
- String log = getLog(rawLog);
-
- // Ensure we do not have a BRK-1001 message before
- if (!getMessageID(log).equals(TESTID))
- {
- assertFalse(getMessageID(log).equals("BRK-1001"));
- continue;
- }
-
- //1
- validateMessageID(TESTID, log);
-
- //2
- //There will be 1 copy of this startup message (via SystemOut)
- assertEquals("Unexpected log4j configuration message count.",
- 1, findMatches(TESTID).size());
-
- //3
- String defaultLog4j = System.getProperty(QPID_HOME) + "/" + BrokerOptions.DEFAULT_LOG_CONFIG_FILE;
- assertTrue("Log4j file(" + defaultLog4j + ") details not correctly logged:" + getMessageString(log),
- getMessageString(log).endsWith(defaultLog4j));
-
- validation = true;
- }
-
- assertTrue("Validation not performed: " + TESTID + " not logged", validation);
- }
- catch (AssertionFailedError afe)
- {
- dumpLogs(results, _monitor);
-
- throw afe;
- }
- }
- }
-
- /**
- * Description:
* On startup the broker must report correctly report the log4j file in use. This is important as it can help diagnose why logging messages are not being reported. The broker must also be capable of correctly recognising the command line property to specify the custom logging configuration.
* Input:
* The value of -l specified on the command line.
@@ -254,11 +169,17 @@
// This logging startup code only occurs when you run a Java broker
if (isJavaBroker())
{
- String customLog4j = getBrokerCommandLog4JFile().getAbsolutePath();
+ // Log4j properties expects this to be set
+ System.setProperty("qpid.testMethod", "-" + getName() + ".customLog4j");
+ System.setProperty("qpid.testClass", getClass().getName() );
+
+ String customLog4j = System.getProperty("log4j.configuration.file");
String TESTID = "BRK-1007";
- startBroker();
+ startBroker(0, false, customLog4j);
+ _outputFile = new File(((FileAppender) LogManager.getRootLogger().getAllAppenders().nextElement()).getFile());
+
// Now we can create the monitor as _outputFile will now be defined
_monitor = new LogMonitor(_outputFile);
@@ -385,7 +306,7 @@
//2
//There will be 2 copies of the startup message (one via SystemOut, and one via Log4J)
assertEquals("Unexpected startup message count",
- 2, findMatches(TESTID).size());
+ 1, findMatches(TESTID).size());
validation = true;
}
@@ -471,9 +392,8 @@
assertEquals("Incorrect message", TESTID, id);
//2
- //There will be 2 copies of the startup message (one via SystemOut, and one via Log4J)
assertEquals("Unexpected listen message count",
- 2, findMatches(TESTID).size());
+ 1, findMatches(TESTID).size());
//3
String message = getMessageString(log);
@@ -587,7 +507,7 @@
//There will be 4 copies of the startup message (two via SystemOut, and two via Log4J)
List<String> listenMessages = findMatches(TESTID);
assertEquals("Four listen messages should be found.",
- 4, listenMessages .size());
+ 2, listenMessages .size());
int tcpStarted = 0;
int sslStarted = 0;
@@ -604,8 +524,8 @@
}
}
- assertEquals("Unexpected number of logs 'Listening on TCP port'", 2, tcpStarted);
- assertEquals("Unexpected number of logs 'Listening on SSL port'", 2, sslStarted);
+ assertEquals("Unexpected number of logs 'Listening on TCP port'", 1, tcpStarted);
+ assertEquals("Unexpected number of logs 'Listening on SSL port'", 1, sslStarted);
//4 Test ports open
testSocketOpen(getPort());
@@ -690,10 +610,9 @@
//2
assertEquals("Ready message not present", "Qpid Broker Ready", getMessageString(log));
- //There will be 2 copies of the startup message (one via SystemOut, and one via Log4J)
assertEquals("Unexpected ready message count",
- 2, findMatches(TESTID).size());
- assertEquals("The ready messages should have been the last 2 messages", results.size() - 2, i);
+ 1, findMatches(TESTID).size());
+ assertEquals("The ready messages should have been the last 2 messages", results.size() - 1, i);
validationComplete = true;
break;
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java b/qpid/java/systests/src/test/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java
index 789ad42..f7722a8 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java
@@ -59,7 +59,7 @@
@Override
public void setUp() throws Exception
{
- getBrokerConfiguration().addGroupFileConfiguration(System.getProperty(QPID_HOME) + "/etc/groups-systests");
+ getBrokerConfiguration().addGroupFileConfiguration(QPID_HOME + "/etc/groups-systests");
// run test specific setup
String testSetup = StringUtils.replace(getName(), "test", "setUp");
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java
index 3717c15..a06ed7b 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java
@@ -25,6 +25,7 @@
import javax.management.openmbean.TabularData;
import org.apache.qpid.management.common.mbeans.LoggingManagement;
+import org.apache.qpid.server.configuration.BrokerProperties;
import org.apache.qpid.server.logging.log4j.LoggingManagementFacadeTest;
import org.apache.qpid.test.utils.JMXTestUtils;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
@@ -35,7 +36,6 @@
* System test for Logging Management. <b>These tests rely on value set within
* test-profiles/log4j-test.xml</b>.
*
- * @see LoggingManagementMBeanTest
* @see LoggingManagementFacadeTest
*
*/
@@ -44,7 +44,9 @@
private JMXTestUtils _jmxUtils;
private LoggingManagement _loggingManagement;
private LogMonitor _monitor;
+ private File _logConfig;
+ @Override
public void setUp() throws Exception
{
getBrokerConfiguration().addJmxManagementConfiguration();
@@ -56,8 +58,9 @@
File tmpLogFile = File.createTempFile("log4j" + "." + getName(), ".xml");
tmpLogFile.deleteOnExit();
- FileUtils.copy(getBrokerCommandLog4JFile(), tmpLogFile);
+ FileUtils.copy(new File(System.getProperty("log4j.configuration.file")), tmpLogFile);
setBrokerCommandLog4JFile(tmpLogFile);
+ _logConfig = tmpLogFile;
super.setUp();
_jmxUtils.open();
@@ -66,6 +69,12 @@
_monitor = new LogMonitor(_outputFile);
}
+ public void startBroker() throws Exception
+ {
+ super.startBroker(0, false, _logConfig.getAbsolutePath());
+ }
+
+ @Override
public void tearDown() throws Exception
{
try
@@ -74,6 +83,11 @@
{
_jmxUtils.close();
}
+
+ if (_logConfig != null)
+ {
+ _logConfig.delete();
+ }
}
finally
{
@@ -122,7 +136,7 @@
_loggingManagement.setConfigFileLoggerLevel(operationalLoggingLogger, "OFF");
List<String> matches = _monitor.waitAndFindMatches("Setting level to OFF for logger 'qpid.message'", 5000);
- assertEquals(1, matches.size());
+ assertTrue(matches.size()>=1);
assertEffectiveLoggingLevel(operationalLoggingLogger, "INFO");
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java
index cb6eae0..4df8184 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java
@@ -104,7 +104,7 @@
//There will be 2 copies of the startup message (one via SystemOut, and one via Log4J)
results = findMatches("MNG-1001");
assertEquals("Unexpected startup message count.",
- 2, results.size());
+ 1, results.size());
//3
assertEquals("Startup log message is not 'Startup'.", "JMX Management Startup",
@@ -185,7 +185,7 @@
// Validation
//There will be 4 startup messages (two via SystemOut, and two via Log4J)
- assertEquals("Unexpected MNG-1002 message count", 4, results.size());
+ assertEquals("Unexpected MNG-1002 message count", 2, results.size());
String log = getLogMessage(results, 0);
@@ -197,7 +197,7 @@
assertTrue("RMI Registry port not as expected(" + mPort + ").:" + getMessageString(log),
getMessageString(log).endsWith(String.valueOf(mPort)));
- log = getLogMessage(results, 2);
+ log = getLogMessage(results, 1);
//1
validateMessageID("MNG-1002", log);
@@ -243,7 +243,7 @@
// Validate we only have two MNG-1002 (one via stdout, one via log4j)
results = findMatches("MNG-1006");
assertEquals("Upexpected SSL Keystore message count",
- 2, results.size());
+ 1, results.size());
// Validate the keystore path is as expected
assertTrue("SSL Keystore entry expected.:" + getMessageString(log),
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/prefetch/ZeroPrefetchTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/prefetch/ZeroPrefetchTest.java
new file mode 100644
index 0000000..6a9fa01
--- /dev/null
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/prefetch/ZeroPrefetchTest.java
@@ -0,0 +1,83 @@
+/*
+ *
+ * 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.systest.prefetch;
+
+import java.util.UUID;
+
+import javax.jms.Connection;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+
+import org.apache.qpid.configuration.ClientProperties;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
+public class ZeroPrefetchTest extends QpidBrokerTestCase
+{
+
+ private static final String TEST_PROPERTY_NAME = "testProp";
+
+ // send two messages to the queue, consume and acknowledge one message on connection 1
+ // create a second connection and attempt to consume the second message - this will only be possible
+ // if the first connection has no prefetch
+ public void testZeroPrefetch() throws Exception
+ {
+ setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, "0");
+ Connection prefetch1Connection = getConnection();
+
+ prefetch1Connection.start();
+
+ final Session prefetch1session = prefetch1Connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ Queue queue = prefetch1session.createQueue(getTestQueueName());
+ MessageConsumer prefetch1consumer = prefetch1session.createConsumer(queue);
+
+
+ Session producerSession = prefetch1Connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ MessageProducer producer = producerSession.createProducer(queue);
+ Message firstMessage = producerSession.createMessage();
+ String firstPropertyValue = UUID.randomUUID().toString();
+ firstMessage.setStringProperty(TEST_PROPERTY_NAME, firstPropertyValue);
+ producer.send(firstMessage);
+
+ Message secondMessage = producerSession.createMessage();
+ String secondPropertyValue = UUID.randomUUID().toString();
+ secondMessage.setStringProperty(TEST_PROPERTY_NAME, secondPropertyValue);
+ producer.send(secondMessage);
+
+
+ Message receivedMessage = prefetch1consumer.receive(2000l);
+ assertNotNull("First message was not received", receivedMessage);
+ assertEquals("Message property was not as expected", firstPropertyValue, receivedMessage.getStringProperty(TEST_PROPERTY_NAME));
+
+ Connection prefetch2Connection = getConnection();
+
+ prefetch2Connection.start();
+ final Session prefetch2session = prefetch2Connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ MessageConsumer prefetch2consumer = prefetch2session.createConsumer(queue);
+
+ receivedMessage = prefetch2consumer.receive(2000l);
+ assertNotNull("Second message was not received", receivedMessage);
+ assertEquals("Message property was not as expected", secondPropertyValue, receivedMessage.getStringProperty(TEST_PROPERTY_NAME));
+
+ }
+}
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/AccessControlProviderRestTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/AccessControlProviderRestTest.java
index 4140c9c..0dda8e0 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/AccessControlProviderRestTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/AccessControlProviderRestTest.java
@@ -125,34 +125,28 @@
public void testReplaceAccessControlProvider() throws Exception
{
- String accessControlProviderName1 = getTestName() + "1";
- //verify that the access control provider doesn't exist, and
- //in doing so implicitly verify that the 'denied' user can
- //actually currently connect because no ACL is in effect yet
- getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
- assertAccessControlProviderExistence(accessControlProviderName1, false);
//create the access control provider using the 'allowed' user
getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
- int responseCode = createAccessControlProvider(accessControlProviderName1, _aclFileContent1);
+ int responseCode = createAccessControlProvider(getTestName(), _aclFileContent1);
assertEquals("Access control provider creation should be allowed", 201, responseCode);
//verify it exists with the 'allowed' user
- assertAccessControlProviderExistence(accessControlProviderName1, true);
+ assertAccessControlProviderExistence(getTestName(), true);
//verify the 'denied' and 'other' user can no longer access the management
//interface due to the just-created ACL file now preventing them
getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
- assertCanAccessManagementInterface(accessControlProviderName1, false);
+ assertCanAccessManagementInterface(getTestName(), false);
getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
- assertCanAccessManagementInterface(accessControlProviderName1, false);
+ assertCanAccessManagementInterface(getTestName(), false);
//create the replacement access control provider using the 'allowed' user.
String accessControlProviderName2 = getTestName() + "2";
getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
- responseCode = createAccessControlProvider(accessControlProviderName2, _aclFileContent2);
- assertEquals("Access control provider creation should be allowed", 201, responseCode);
+ responseCode = createAccessControlProvider(getTestName(), _aclFileContent2);
+ assertEquals("Access control provider creation should be allowed", 200, responseCode);
//Verify that it took effect immediately, replacing the first access control provider
@@ -162,11 +156,6 @@
getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
assertCanAccessManagementInterface(accessControlProviderName2, true);
- //remove the original access control provider using the 'allowed' user
- getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
- responseCode = getRestTestHelper().submitRequest("accesscontrolprovider/" + accessControlProviderName1, "DELETE");
- assertEquals("Access control provider deletion should be allowed", 200, responseCode);
- assertAccessControlProviderExistence(accessControlProviderName1, false);
//verify the 'denied' user still can't access the management interface, the 'other' user still can, thus
//confirming that the second access control provider is still in effect
@@ -177,61 +166,6 @@
}
- public void testAddAndRemoveSecondAccessControlProviderReinstatesOriginal() throws Exception
- {
- String accessControlProviderName1 = getTestName() + "1";
-
- //verify that the access control provider doesn't exist, and
- //in doing so implicitly verify that the 'denied' user can
- //actually currently connect because no ACL is in effect yet
- getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
- assertAccessControlProviderExistence(accessControlProviderName1, false);
-
- //create the access control provider using the 'allowed' user
- getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
- int responseCode = createAccessControlProvider(accessControlProviderName1, _aclFileContent1);
- assertEquals("Access control provider creation should be allowed", 201, responseCode);
-
- //verify it exists with the 'allowed' user
- assertAccessControlProviderExistence(accessControlProviderName1, true);
-
- //verify the 'denied' and 'other' user can no longer access the management
- //interface due to the just-created ACL file now preventing them
- getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
- assertCanAccessManagementInterface(accessControlProviderName1, false);
- getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
- assertCanAccessManagementInterface(accessControlProviderName1, false);
-
- //create the replacement access control provider using the 'allowed' user.
- String accessControlProviderName2 = getTestName() + "2";
- getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
- responseCode = createAccessControlProvider(accessControlProviderName2, _aclFileContent2);
- assertEquals("Access control provider creation should be allowed", 201, responseCode);
-
- //Verify that it took effect immediately, replacing the first access control provider
-
- //verify the 'denied' user still can't access the management interface, but the 'other' user now CAN.
- getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
- assertCanAccessManagementInterface(accessControlProviderName2, false);
- getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
- assertCanAccessManagementInterface(accessControlProviderName2, true);
-
- //remove the second access control provider using the 'allowed' user
- getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
- responseCode = getRestTestHelper().submitRequest("accesscontrolprovider/" + accessControlProviderName2, "DELETE");
- assertEquals("Access control provider deletion should be allowed", 200, responseCode);
- assertAccessControlProviderExistence(accessControlProviderName2, false);
-
- //verify the 'denied' user still can't access the management interface, the
- //'other' now CANT again, the 'allowed' still can, thus confirming that the
- //first access control provider is now in effect once again
- getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
- assertCanAccessManagementInterface(accessControlProviderName2, false);
- getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
- assertCanAccessManagementInterface(accessControlProviderName2, false);
- getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
- assertCanAccessManagementInterface(accessControlProviderName2, true);
- }
public void testRemovalOfAccessControlProviderInErrorStateUsingManagementMode() throws Exception
{
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/BrokerRestTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/BrokerRestTest.java
index ba95eec..4023830 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/BrokerRestTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/BrokerRestTest.java
@@ -235,9 +235,6 @@
assertNotNull("Unexpected value of attribute ports", brokerDetails.get(BROKER_PORTS_ATTRIBUTE));
assertNotNull("Unexpected value of attribute authenticationproviders", brokerDetails.get(BROKER_AUTHENTICATIONPROVIDERS_ATTRIBUTE));
- assertNotNull("Unexpected value of attribute supportedVirtualHostTypes", brokerDetails.get(Broker.SUPPORTED_VIRTUALHOST_TYPES));
- assertNotNull("Unexpected value of attribute supportedVirtualHostNodeTypes", brokerDetails.get(Broker.SUPPORTED_VIRTUALHOSTNODE_TYPES));
-
}
}
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/KeyStoreRestTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/KeyStoreRestTest.java
index 4b881d1..03b0a7a 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/KeyStoreRestTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/KeyStoreRestTest.java
@@ -20,23 +20,20 @@
*/
package org.apache.qpid.systest.rest;
-import java.io.IOException;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.codehaus.jackson.JsonGenerationException;
-import org.codehaus.jackson.JsonParseException;
-import org.codehaus.jackson.map.JsonMappingException;
+import javax.servlet.http.HttpServletResponse;
+
import org.apache.qpid.server.model.AbstractConfiguredObject;
import org.apache.qpid.server.model.KeyStore;
-import org.apache.qpid.server.model.Port;
-import org.apache.qpid.server.model.Transport;
import org.apache.qpid.server.security.FileKeyStore;
import org.apache.qpid.test.utils.TestBrokerConfiguration;
import org.apache.qpid.test.utils.TestSSLConstants;
+import org.apache.qpid.util.DataUrlUtils;
+import org.apache.qpid.util.FileUtils;
public class KeyStoreRestTest extends QpidRestTestCase
{
@@ -56,7 +53,7 @@
Map<String, Object> keystore = keyStores.get(0);
assertKeyStoreAttributes(keystore, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE,
- System.getProperty(QPID_HOME) + "/../" + TestSSLConstants.BROKER_KEYSTORE, null);
+ QPID_HOME + "/../" + TestSSLConstants.BROKER_KEYSTORE, null);
}
public void testCreate() throws Exception
@@ -67,7 +64,7 @@
String certAlias = "app2";
assertNumberOfKeyStores(1);
- createKeyStore(name, certAlias);
+ createKeyStore(name, certAlias, TestSSLConstants.KEYSTORE, TestSSLConstants.KEYSTORE_PASSWORD);
assertNumberOfKeyStores(2);
List<Map<String, Object>> keyStores = getRestTestHelper().getJsonAsList("keystore/" + name);
@@ -76,6 +73,24 @@
assertKeyStoreAttributes(keyStores.get(0), name, TestSSLConstants.KEYSTORE, certAlias);
}
+ public void testCreateWithDataUrl() throws Exception
+ {
+ super.setUp();
+
+ String name = getTestName();
+ byte[] keystoreAsBytes = FileUtils.readFileAsBytes(TestSSLConstants.KEYSTORE);
+ String dataUrlForKeyStore = DataUrlUtils.getDataUrlForBytes(keystoreAsBytes);
+
+ assertNumberOfKeyStores(1);
+ createKeyStore(name, null, dataUrlForKeyStore, TestSSLConstants.KEYSTORE_PASSWORD);
+ assertNumberOfKeyStores(2);
+
+ List<Map<String, Object>> keyStores = getRestTestHelper().getJsonAsList("keystore/" + name);
+ assertNotNull("details cannot be null", keyStores);
+
+ assertKeyStoreAttributes(keyStores.get(0), name, dataUrlForKeyStore, null);
+ }
+
public void testDelete() throws Exception
{
super.setUp();
@@ -84,11 +99,10 @@
String certAlias = "app2";
assertNumberOfKeyStores(1);
- createKeyStore(name, certAlias);
+ createKeyStore(name, certAlias, TestSSLConstants.KEYSTORE, TestSSLConstants.KEYSTORE_PASSWORD);
assertNumberOfKeyStores(2);
- int responseCode = getRestTestHelper().submitRequest("keystore/" + name , "DELETE");
- assertEquals("Unexpected response code for provider deletion", 200, responseCode);
+ getRestTestHelper().submitRequest("keystore/" + name, "DELETE", HttpServletResponse.SC_OK);
List<Map<String, Object>> keyStore = getRestTestHelper().getJsonAsList("keystore/" + name);
assertNotNull("details should not be null", keyStore);
@@ -98,65 +112,24 @@
List<Map<String, Object>> keyStores = assertNumberOfKeyStores(1);
Map<String, Object> keystore = keyStores.get(0);
assertKeyStoreAttributes(keystore, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE,
- System.getProperty(QPID_HOME) + "/../" + TestSSLConstants.BROKER_KEYSTORE, null);
+ QPID_HOME + "/../" + TestSSLConstants.BROKER_KEYSTORE, null);
}
- public void testDeleteFailsWhenKeyStoreInUse() throws Exception
- {
- String name = "testDeleteFailsWhenKeyStoreInUse";
-
- //add a new key store config to use
- Map<String, Object> sslKeyStoreAttributes = new HashMap<String, Object>();
- sslKeyStoreAttributes.put(KeyStore.NAME, name);
- sslKeyStoreAttributes.put(FileKeyStore.PATH, TestSSLConstants.BROKER_KEYSTORE);
- sslKeyStoreAttributes.put(FileKeyStore.PASSWORD, TestSSLConstants.BROKER_KEYSTORE_PASSWORD);
- getBrokerConfiguration().addObjectConfiguration(KeyStore.class,sslKeyStoreAttributes);
-
- //add the SSL port using it
- Map<String, Object> sslPortAttributes = new HashMap<String, Object>();
- sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
- sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT);
- sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT);
- sslPortAttributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER);
- sslPortAttributes.put(Port.KEY_STORE, name);
- getBrokerConfiguration().addObjectConfiguration(Port.class,sslPortAttributes);
-
- super.setUp();
-
- //verify the keystore is there
- assertNumberOfKeyStores(2);
-
- List<Map<String, Object>> keyStore = getRestTestHelper().getJsonAsList("keystore/" + name);
- assertNotNull("details should not be null", keyStore);
- assertKeyStoreAttributes(keyStore.get(0), name, TestSSLConstants.BROKER_KEYSTORE, null);
-
- //try to delete it, which should fail as it is in use
- int responseCode = getRestTestHelper().submitRequest("keystore/" + name , "DELETE");
- assertEquals("Unexpected response code for provider deletion", 409, responseCode);
-
- //check its still there
- assertNumberOfKeyStores(2);
- keyStore = getRestTestHelper().getJsonAsList("keystore/" + name);
- assertNotNull("details should not be null", keyStore);
- assertKeyStoreAttributes(keyStore.get(0), name, TestSSLConstants.BROKER_KEYSTORE, null);
- }
-
- public void testUpdateWithGoodPathSucceeds() throws Exception
+ public void testUpdate() throws Exception
{
super.setUp();
String name = getTestName();
assertNumberOfKeyStores(1);
- createKeyStore(name, null);
+ createKeyStore(name, null, TestSSLConstants.KEYSTORE, TestSSLConstants.KEYSTORE_PASSWORD);
assertNumberOfKeyStores(2);
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put(KeyStore.NAME, name);
attributes.put(FileKeyStore.PATH, TestSSLConstants.UNTRUSTED_KEYSTORE);
- int responseCode = getRestTestHelper().submitRequest("keystore/" + name , "PUT", attributes);
- assertEquals("Unexpected response code for keystore update", 200, responseCode);
+ getRestTestHelper().submitRequest("keystore/" + name, "PUT", attributes, HttpServletResponse.SC_OK);
List<Map<String, Object>> keyStore = getRestTestHelper().getJsonAsList("keystore/" + name);
assertNotNull("details should not be null", keyStore);
@@ -164,73 +137,8 @@
assertKeyStoreAttributes(keyStore.get(0), name, TestSSLConstants.UNTRUSTED_KEYSTORE, null);
}
- public void testUpdateWithNonExistentPathFails() throws Exception
- {
- super.setUp();
- String name = getTestName();
-
- assertNumberOfKeyStores(1);
- createKeyStore(name, null);
- assertNumberOfKeyStores(2);
-
- Map<String, Object> attributes = new HashMap<String, Object>();
- attributes.put(KeyStore.NAME, name);
- attributes.put(FileKeyStore.PATH, "does.not.exist");
-
- int responseCode = getRestTestHelper().submitRequest("keystore/" + name , "PUT", attributes);
- assertEquals("Unexpected response code for keystore update", 409, responseCode);
-
- List<Map<String, Object>> keyStore = getRestTestHelper().getJsonAsList("keystore/" + name);
- assertNotNull("details should not be null", keyStore);
-
- //verify the details remain unchanged
- assertKeyStoreAttributes(keyStore.get(0), name, TestSSLConstants.KEYSTORE, null);
- }
-
- public void testUpdateCertificateAlias() throws Exception
- {
- super.setUp();
-
- String name = getTestName();
-
- assertNumberOfKeyStores(1);
- createKeyStore(name, "app1");
- assertNumberOfKeyStores(2);
-
- List<Map<String, Object>> keyStore = getRestTestHelper().getJsonAsList("keystore/" + name);
- assertNotNull("details should not be null", keyStore);
- assertKeyStoreAttributes(keyStore.get(0), name, TestSSLConstants.KEYSTORE, "app1");
-
- //Update the certAlias from app1 to app2
- Map<String, Object> attributes = new HashMap<String, Object>();
- attributes.put(KeyStore.NAME, name);
- attributes.put(FileKeyStore.CERTIFICATE_ALIAS, "app2");
-
- int responseCode = getRestTestHelper().submitRequest("keystore/" + name , "PUT", attributes);
- assertEquals("Unexpected response code for keystore update", 200, responseCode);
-
- keyStore = getRestTestHelper().getJsonAsList("keystore/" + name);
- assertNotNull("details should not be null", keyStore);
-
- assertKeyStoreAttributes(keyStore.get(0), name, TestSSLConstants.KEYSTORE, "app2");
-
- //Update the certAlias to clear it (i.e go from from app1 to null)
- attributes = new HashMap<String, Object>();
- attributes.put(KeyStore.NAME, name);
- attributes.put(FileKeyStore.CERTIFICATE_ALIAS, null);
-
- responseCode = getRestTestHelper().submitRequest("keystore/" + name , "PUT", attributes);
- assertEquals("Unexpected response code for keystore update", 200, responseCode);
-
- keyStore = getRestTestHelper().getJsonAsList("keystore/" + name);
- assertNotNull("details should not be null", keyStore);
-
- assertKeyStoreAttributes(keyStore.get(0), name, TestSSLConstants.KEYSTORE, null);
- }
-
- private List<Map<String, Object>> assertNumberOfKeyStores(int numberOfKeystores) throws IOException,
- JsonParseException, JsonMappingException
+ private List<Map<String, Object>> assertNumberOfKeyStores(int numberOfKeystores) throws Exception
{
List<Map<String, Object>> keyStores = getRestTestHelper().getJsonAsList("keystore");
assertNotNull("keystores should not be null", keyStores);
@@ -239,16 +147,18 @@
return keyStores;
}
- private void createKeyStore(String name, String certAlias) throws IOException, JsonGenerationException, JsonMappingException
+ private void createKeyStore(String name, String certAlias, final String keyStorePath, final String keystorePassword) throws Exception
{
- Map<String, Object> keyStoreAttributes = new HashMap<String, Object>();
+ Map<String, Object> keyStoreAttributes = new HashMap<>();
keyStoreAttributes.put(KeyStore.NAME, name);
- keyStoreAttributes.put(FileKeyStore.PATH, TestSSLConstants.KEYSTORE);
- keyStoreAttributes.put(FileKeyStore.PASSWORD, TestSSLConstants.KEYSTORE_PASSWORD);
- keyStoreAttributes.put(FileKeyStore.CERTIFICATE_ALIAS, certAlias);
+ keyStoreAttributes.put(FileKeyStore.PATH, keyStorePath);
+ keyStoreAttributes.put(FileKeyStore.PASSWORD, keystorePassword);
+ if (certAlias != null)
+ {
+ keyStoreAttributes.put(FileKeyStore.CERTIFICATE_ALIAS, certAlias);
+ }
- int responseCode = getRestTestHelper().submitRequest("keystore/" + name, "PUT", keyStoreAttributes);
- assertEquals("Unexpected response code", 201, responseCode);
+ getRestTestHelper().submitRequest("keystore/" + name, "PUT", keyStoreAttributes, HttpServletResponse.SC_CREATED);
}
private void assertKeyStoreAttributes(Map<String, Object> keystore, String name, String path, String certAlias)
@@ -261,12 +171,16 @@
AbstractConfiguredObject.SECURED_STRING_VALUE, keystore.get(FileKeyStore.PASSWORD));
assertEquals("unexpected type of default systests key store",
java.security.KeyStore.getDefaultType(), keystore.get(FileKeyStore.KEY_STORE_TYPE));
- assertEquals("unexpected certificateAlias value",
- certAlias, keystore.get(FileKeyStore.CERTIFICATE_ALIAS));
if(certAlias == null)
{
assertFalse("should not be a certificateAlias attribute",
keystore.containsKey(FileKeyStore.CERTIFICATE_ALIAS));
}
+ else
+ {
+ assertEquals("unexpected certificateAlias value",
+ certAlias, keystore.get(FileKeyStore.CERTIFICATE_ALIAS));
+
+ }
}
}
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/LogViewerTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/LogViewerTest.java
index f2fb258..a7bf743 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/LogViewerTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/LogViewerTest.java
@@ -28,25 +28,40 @@
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
-import org.apache.qpid.server.BrokerOptions;
+import org.apache.log4j.FileAppender;
+import org.apache.log4j.Logger;
+import org.apache.log4j.SimpleLayout;
+import org.apache.qpid.server.configuration.BrokerProperties;
public class LogViewerTest extends QpidRestTestCase
{
- public static final String DEFAULT_FILE_APPENDER_NAME = "FileAppender";
private String _expectedLogFileName;
+ private FileAppender _fileAppender;
+ private String _appenderName;
+ @Override
public void setUp() throws Exception
{
- setSystemProperty("logsuffix", "-" + getTestQueueName());
- _expectedLogFileName = System.getProperty("logprefix", "") + "qpid" + System.getProperty("logsuffix", "") + ".log";
+ _appenderName = getTestQueueName();
+ _expectedLogFileName = "qpid-" + _appenderName + ".log";
- // use real broker log file
- File brokerLogFile = new File(System.getProperty(QPID_HOME), BrokerOptions.DEFAULT_LOG_CONFIG_FILE);
- setBrokerCommandLog4JFile(brokerLogFile);
-
+ _fileAppender = new FileAppender(new SimpleLayout(),
+ System.getProperty(BrokerProperties.PROPERTY_QPID_WORK) + File.separator + _expectedLogFileName, false);
+ _fileAppender.setName(_appenderName);
+ Logger.getRootLogger().addAppender(_fileAppender);
super.setUp();
}
+ @Override
+ public void tearDown() throws Exception
+ {
+ if (_fileAppender != null)
+ {
+ Logger.getRootLogger().removeAppender(_fileAppender);
+ }
+ super.tearDown();
+ }
+
public void testGetLogFiles() throws Exception
{
List<Map<String, Object>> logFiles = getRestTestHelper().getJsonAsList("/service/logfilenames");
@@ -54,24 +69,32 @@
// 1 file appender is configured in QPID default log4j xml:
assertTrue("Unexpected number of log files", logFiles.size() > 0);
+ Map<String, Object> logFileDetails = null;
+ for (Map<String, Object> appenderDetails: logFiles)
+ {
+ if (_appenderName.equals(appenderDetails.get("appenderName")))
+ {
+ logFileDetails = appenderDetails;
+ break;
+ }
+ }
- Map<String, Object> logFileDetails = logFiles.get(0);
assertEquals("Unexpected log file name", _expectedLogFileName, logFileDetails.get("name"));
assertEquals("Unexpected log file mime type", "text/plain", logFileDetails.get("mimeType"));
- assertEquals("Unexpected log file appender",DEFAULT_FILE_APPENDER_NAME, logFileDetails.get("appenderName"));
+ assertEquals("Unexpected log file appender",_appenderName, logFileDetails.get("appenderName"));
assertTrue("Unexpected log file size", ((Number)logFileDetails.get("size")).longValue()>0);
assertTrue("Unexpected log file modification time", ((Number)logFileDetails.get("lastModified")).longValue()>0);
}
public void testDownloadExistingLogFiles() throws Exception
{
- byte[] bytes = getRestTestHelper().getBytes("/service/logfile?l=" + DEFAULT_FILE_APPENDER_NAME + "%2F" + _expectedLogFileName);
+ byte[] bytes = getRestTestHelper().getBytes("/service/logfile?l=" + _appenderName + "%2F" + _expectedLogFileName);
ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(bytes));
try
{
ZipEntry entry = zis.getNextEntry();
- assertEquals("Unexpected broker log file name", DEFAULT_FILE_APPENDER_NAME + "/" + _expectedLogFileName, entry.getName());
+ assertEquals("Unexpected broker log file name", _appenderName + "/" + _expectedLogFileName, entry.getName());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
@@ -91,7 +114,7 @@
public void testDownloadNonExistingLogFiles() throws Exception
{
- int responseCode = getRestTestHelper().submitRequest("/service/logfile?l=" + DEFAULT_FILE_APPENDER_NAME + "%2F"
+ int responseCode = getRestTestHelper().submitRequest("/service/logfile?l=" + _appenderName + "%2F"
+ _expectedLogFileName + "_" + System.currentTimeMillis(), "GET");
assertEquals("Unexpected response code", 404, responseCode);
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/TrustStoreRestTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/TrustStoreRestTest.java
index 5d2e9de..6cca3fc 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/TrustStoreRestTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/TrustStoreRestTest.java
@@ -20,23 +20,19 @@
*/
package org.apache.qpid.systest.rest;
-import java.io.IOException;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.codehaus.jackson.JsonGenerationException;
-import org.codehaus.jackson.JsonParseException;
-import org.codehaus.jackson.map.JsonMappingException;
+import javax.servlet.http.HttpServletResponse;
import org.apache.qpid.server.model.AbstractConfiguredObject;
-import org.apache.qpid.server.model.Port;
-import org.apache.qpid.server.model.Transport;
import org.apache.qpid.server.model.TrustStore;
import org.apache.qpid.server.security.FileTrustStore;
import org.apache.qpid.test.utils.TestBrokerConfiguration;
import org.apache.qpid.test.utils.TestSSLConstants;
+import org.apache.qpid.util.DataUrlUtils;
+import org.apache.qpid.util.FileUtils;
public class TrustStoreRestTest extends QpidRestTestCase
{
@@ -56,7 +52,7 @@
Map<String, Object> truststore = trustStores.get(0);
assertTrustStoreAttributes(truststore, TestBrokerConfiguration.ENTRY_NAME_SSL_TRUSTSTORE,
- System.getProperty(QPID_HOME) + "/../" + TestSSLConstants.BROKER_TRUSTSTORE, false);
+ QPID_HOME + "/../" + TestSSLConstants.BROKER_TRUSTSTORE, false);
}
public void testCreate() throws Exception
@@ -66,7 +62,7 @@
String name = getTestName();
assertNumberOfTrustStores(1);
- createTrustStore(name, true);
+ createTrustStore(name, true, TestSSLConstants.TRUSTSTORE, TestSSLConstants.TRUSTSTORE_PASSWORD);
assertNumberOfTrustStores(2);
List<Map<String, Object>> trustStores = getRestTestHelper().getJsonAsList("truststore/" + name);
@@ -75,6 +71,26 @@
assertTrustStoreAttributes(trustStores.get(0), name, TestSSLConstants.TRUSTSTORE, true);
}
+ public void testCreateUsingDataUrl() throws Exception
+ {
+ super.setUp();
+
+ String name = getTestName();
+ byte[] trustStoreAsBytes = FileUtils.readFileAsBytes(TestSSLConstants.TRUSTSTORE);
+ String dataUrlForTruststore = DataUrlUtils.getDataUrlForBytes(trustStoreAsBytes);
+
+ assertNumberOfTrustStores(1);
+
+ createTrustStore(name, false, dataUrlForTruststore, TestSSLConstants.TRUSTSTORE_PASSWORD);
+
+ assertNumberOfTrustStores(2);
+
+ List<Map<String, Object>> trustStores = getRestTestHelper().getJsonAsList("truststore/" + name);
+ assertNotNull("details cannot be null", trustStores);
+
+ assertTrustStoreAttributes(trustStores.get(0), name, dataUrlForTruststore, false);
+ }
+
public void testDelete() throws Exception
{
super.setUp();
@@ -82,11 +98,10 @@
String name = getTestName();
assertNumberOfTrustStores(1);
- createTrustStore(name, false);
+ createTrustStore(name, false, TestSSLConstants.TRUSTSTORE, TestSSLConstants.TRUSTSTORE_PASSWORD);
assertNumberOfTrustStores(2);
- int responseCode = getRestTestHelper().submitRequest("truststore/" + name , "DELETE");
- assertEquals("Unexpected response code for provider deletion", 200, responseCode);
+ getRestTestHelper().submitRequest("truststore/" + name , "DELETE", HttpServletResponse.SC_OK);
List<Map<String, Object>> trustStore = getRestTestHelper().getJsonAsList("truststore/" + name);
assertNotNull("details should not be null", trustStore);
@@ -96,66 +111,25 @@
List<Map<String, Object>> trustStores = assertNumberOfTrustStores(1);
Map<String, Object> truststore = trustStores.get(0);
assertTrustStoreAttributes(truststore, TestBrokerConfiguration.ENTRY_NAME_SSL_TRUSTSTORE,
- System.getProperty(QPID_HOME) + "/../" + TestSSLConstants.BROKER_TRUSTSTORE, false);
+ QPID_HOME + "/../" + TestSSLConstants.BROKER_TRUSTSTORE, false);
}
- public void testDeleteFailsWhenTrustStoreInUse() throws Exception
- {
- String name = "testDeleteFailsWhenTrustStoreInUse";
- //add a new trust store config to use
- Map<String, Object> sslTrustStoreAttributes = new HashMap<String, Object>();
- sslTrustStoreAttributes.put(TrustStore.NAME, name);
- sslTrustStoreAttributes.put(FileTrustStore.PATH, TestSSLConstants.TRUSTSTORE);
- sslTrustStoreAttributes.put(FileTrustStore.PASSWORD, TestSSLConstants.TRUSTSTORE_PASSWORD);
- getBrokerConfiguration().addObjectConfiguration(TrustStore.class,sslTrustStoreAttributes);
-
- //add the SSL port using it
- Map<String, Object> sslPortAttributes = new HashMap<String, Object>();
- sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
- sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT);
- sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT);
- sslPortAttributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER);
- sslPortAttributes.put(Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE);
- sslPortAttributes.put(Port.TRUST_STORES, Collections.singleton(name));
- getBrokerConfiguration().addObjectConfiguration(Port.class, sslPortAttributes);
-
- super.setUp();
-
- //verify the truststore is there
- assertNumberOfTrustStores(2);
-
- List<Map<String, Object>> trustStore = getRestTestHelper().getJsonAsList("truststore/" + name);
- assertNotNull("details should not be null", trustStore);
- assertTrustStoreAttributes(trustStore.get(0), name, TestSSLConstants.TRUSTSTORE, false);
-
- //try to delete it, which should fail as it is in use
- int responseCode = getRestTestHelper().submitRequest("truststore/" + name , "DELETE");
- assertEquals("Unexpected response code for provider deletion", 409, responseCode);
-
- //check its still there
- assertNumberOfTrustStores(2);
- trustStore = getRestTestHelper().getJsonAsList("truststore/" + name);
- assertNotNull("details should not be null", trustStore);
- assertTrustStoreAttributes(trustStore.get(0), name, TestSSLConstants.TRUSTSTORE, false);
- }
-
- public void testUpdateWithGoodPathSucceeds() throws Exception
+ public void testUpdate() throws Exception
{
super.setUp();
String name = getTestName();
assertNumberOfTrustStores(1);
- createTrustStore(name, false);
+ createTrustStore(name, false, TestSSLConstants.TRUSTSTORE, TestSSLConstants.TRUSTSTORE_PASSWORD);
assertNumberOfTrustStores(2);
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put(TrustStore.NAME, name);
attributes.put(FileTrustStore.PATH, TestSSLConstants.TRUSTSTORE);
- int responseCode = getRestTestHelper().submitRequest("truststore/" + name , "PUT", attributes);
- assertEquals("Unexpected response code for truststore update", 200, responseCode);
+ getRestTestHelper().submitRequest("truststore/" + name , "PUT", attributes, HttpServletResponse.SC_OK);
List<Map<String, Object>> trustStore = getRestTestHelper().getJsonAsList("truststore/" + name);
assertNotNull("details should not be null", trustStore);
@@ -163,69 +137,7 @@
assertTrustStoreAttributes(trustStore.get(0), name, TestSSLConstants.TRUSTSTORE, false);
}
- public void testUpdateWithNonExistentPathFails() throws Exception
- {
- super.setUp();
-
- String name = getTestName();
-
- assertNumberOfTrustStores(1);
- createTrustStore(name, false);
- assertNumberOfTrustStores(2);
-
- Map<String, Object> attributes = new HashMap<String, Object>();
- attributes.put(TrustStore.NAME, name);
- attributes.put(FileTrustStore.PATH, "does.not.exist");
-
- int responseCode = getRestTestHelper().submitRequest("truststore/" + name , "PUT", attributes);
- assertEquals("Unexpected response code for trust store update", 409, responseCode);
-
- List<Map<String, Object>> trustStore = getRestTestHelper().getJsonAsList("truststore/" + name);
- assertNotNull("details should not be null", trustStore);
-
- //verify the details remain unchanged
- assertTrustStoreAttributes(trustStore.get(0), name, TestSSLConstants.TRUSTSTORE, false);
- }
-
- public void testUpdatePeersOnly() throws Exception
- {
- super.setUp();
-
- String name = getTestName();
-
- assertNumberOfTrustStores(1);
- createTrustStore(name, false);
- assertNumberOfTrustStores(2);
-
- //update the peersOnly attribute from false to true
- Map<String, Object> attributes = new HashMap<String, Object>();
- attributes.put(TrustStore.NAME, name);
- attributes.put(FileTrustStore.PEERS_ONLY, true);
-
- int responseCode = getRestTestHelper().submitRequest("truststore/" + name , "PUT", attributes);
- assertEquals("Unexpected response code for trust store update", 200, responseCode);
-
- List<Map<String, Object>> trustStore = getRestTestHelper().getJsonAsList("truststore/" + name);
- assertNotNull("details should not be null", trustStore);
-
- assertTrustStoreAttributes(trustStore.get(0), name, TestSSLConstants.TRUSTSTORE, true);
-
- //Update peersOnly to clear it (i.e go from from true to null, which will default to false)
- attributes = new HashMap<String, Object>();
- attributes.put(TrustStore.NAME, name);
- attributes.put(FileTrustStore.PEERS_ONLY, null);
-
- responseCode = getRestTestHelper().submitRequest("truststore/" + name , "PUT", attributes);
- assertEquals("Unexpected response code for trust store update", 200, responseCode);
-
- trustStore = getRestTestHelper().getJsonAsList("truststore/" + name);
- assertNotNull("details should not be null", trustStore);
-
- assertTrustStoreAttributes(trustStore.get(0), name, TestSSLConstants.TRUSTSTORE, false);
- }
-
- private List<Map<String, Object>> assertNumberOfTrustStores(int numberOfTrustStores) throws IOException,
- JsonParseException, JsonMappingException
+ private List<Map<String, Object>> assertNumberOfTrustStores(int numberOfTrustStores) throws Exception
{
List<Map<String, Object>> trustStores = getRestTestHelper().getJsonAsList("truststore");
assertNotNull("trust stores should not be null", trustStores);
@@ -234,17 +146,16 @@
return trustStores;
}
- private void createTrustStore(String name, boolean peersOnly) throws IOException, JsonGenerationException, JsonMappingException
+ private void createTrustStore(String name, boolean peersOnly, final String truststorePath, final String truststorePassword) throws Exception
{
Map<String, Object> trustStoreAttributes = new HashMap<String, Object>();
trustStoreAttributes.put(TrustStore.NAME, name);
//deliberately using the client trust store to differentiate from the one we are already for broker
- trustStoreAttributes.put(FileTrustStore.PATH, TestSSLConstants.TRUSTSTORE);
- trustStoreAttributes.put(FileTrustStore.PASSWORD, TestSSLConstants.TRUSTSTORE_PASSWORD);
+ trustStoreAttributes.put(FileTrustStore.PATH, truststorePath);
+ trustStoreAttributes.put(FileTrustStore.PASSWORD, truststorePassword);
trustStoreAttributes.put(FileTrustStore.PEERS_ONLY, peersOnly);
- int responseCode = getRestTestHelper().submitRequest("truststore/" + name, "PUT", trustStoreAttributes);
- assertEquals("Unexpected response code", 201, responseCode);
+ getRestTestHelper().submitRequest("truststore/" + name, "PUT", trustStoreAttributes, HttpServletResponse.SC_CREATED);
}
private void assertTrustStoreAttributes(Map<String, Object> truststore, String name, String path, boolean peersOnly)
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java
index 8c4effd..86ebf11 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java
@@ -714,19 +714,6 @@
/* === AccessControlProvider === */
- public void testCreateAccessControlProviderAllowed() throws Exception
- {
- getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
-
- String accessControlProviderName = getTestName();
-
- assertAccessControlProviderExistence(accessControlProviderName, false);
-
- int responseCode = createAccessControlProvider(accessControlProviderName);
- assertEquals("Access control provider creation should be allowed", 201, responseCode);
-
- assertAccessControlProviderExistence(accessControlProviderName, true);
- }
public void testCreateAccessControlProviderDenied() throws Exception
{
@@ -746,18 +733,13 @@
{
getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
- String accessControlProviderName = getTestName();
-
- assertAccessControlProviderExistence(accessControlProviderName, false);
-
- int responseCode = createAccessControlProvider(accessControlProviderName);
- assertEquals("Access control provider creation should be allowed", 201, responseCode);
+ String accessControlProviderName = TestBrokerConfiguration.ENTRY_NAME_ACL_FILE;
assertAccessControlProviderExistence(accessControlProviderName, true);
getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
- responseCode = getRestTestHelper().submitRequest("accesscontrolprovider/" + accessControlProviderName, "DELETE");
+ int responseCode = getRestTestHelper().submitRequest("accesscontrolprovider/" + accessControlProviderName, "DELETE");
assertEquals("Access control provider deletion should be denied", 403, responseCode);
assertAccessControlProviderExistence(accessControlProviderName, true);
@@ -767,16 +749,12 @@
{
getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
- String accessControlProviderName = getTestName();
+ String accessControlProviderName = TestBrokerConfiguration.ENTRY_NAME_ACL_FILE;
- assertAccessControlProviderExistence(accessControlProviderName, false);
-
- int responseCode = createAccessControlProvider(accessControlProviderName);
- assertEquals("Access control provider creation should be allowed", 201, responseCode);
assertAccessControlProviderExistence(accessControlProviderName, true);
- responseCode = getRestTestHelper().submitRequest("accesscontrolprovider/" + accessControlProviderName, "DELETE");
+ int responseCode = getRestTestHelper().submitRequest("accesscontrolprovider/" + accessControlProviderName, "DELETE");
assertEquals("Access control provider deletion should be allowed", 200, responseCode);
assertAccessControlProviderExistence(accessControlProviderName, false);
@@ -786,20 +764,16 @@
{
getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
- String accessControlProviderName = getTestName();
-
- assertAccessControlProviderExistence(accessControlProviderName, false);
-
- int responseCode = createAccessControlProvider(accessControlProviderName);
- assertEquals("Access control provider creation should be allowed", 201, responseCode);
+ String accessControlProviderName = TestBrokerConfiguration.ENTRY_NAME_ACL_FILE;
assertAccessControlProviderExistence(accessControlProviderName, true);
+ File aclFile = TestFileUtils.createTempFile(this, ".acl", "ACL ALLOW all all");
+
Map<String, Object> attributes = new HashMap<String, Object>();
- attributes.put(GroupProvider.NAME, accessControlProviderName);
- attributes.put(GroupProvider.TYPE, FileBasedGroupProviderImpl.GROUP_FILE_PROVIDER_TYPE);
- attributes.put(FileBasedGroupProvider.PATH, "/path/to/file");
- responseCode = getRestTestHelper().submitRequest("accesscontrolprovider/" + accessControlProviderName, "PUT", attributes);
+ attributes.put(AccessControlProvider.NAME, accessControlProviderName);
+ attributes.put(FileBasedGroupProvider.PATH, aclFile.getAbsolutePath());
+ int responseCode = getRestTestHelper().submitRequest("accesscontrolprovider/" + accessControlProviderName, "PUT", attributes);
assertEquals("Setting of access control provider attributes should be allowed", 200, responseCode);
}
@@ -807,12 +781,7 @@
{
getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
- String accessControlProviderName = getTestName();
-
- assertAccessControlProviderExistence(accessControlProviderName, false);
-
- int responseCode = createAccessControlProvider(accessControlProviderName);
- assertEquals("Access control provider creation should be allowed", 201, responseCode);
+ String accessControlProviderName = TestBrokerConfiguration.ENTRY_NAME_ACL_FILE;
assertAccessControlProviderExistence(accessControlProviderName, true);
@@ -822,7 +791,7 @@
attributes.put(GroupProvider.NAME, accessControlProviderName);
attributes.put(GroupProvider.TYPE, FileBasedGroupProviderImpl.GROUP_FILE_PROVIDER_TYPE);
attributes.put(FileBasedGroupProvider.PATH, "/path/to/file");
- responseCode = getRestTestHelper().submitRequest("accesscontrolprovider/" + accessControlProviderName, "PUT", attributes);
+ int responseCode = getRestTestHelper().submitRequest("accesscontrolprovider/" + accessControlProviderName, "PUT", attributes);
assertEquals("Setting of access control provider attributes should be denied", 403, responseCode);
}
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java
index ed03e83..191f9d7 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java
@@ -81,7 +81,6 @@
+ "&temporaryQueueExchange='tmp.direct'"
+ "&temporaryTopicExchange='tmp.topic'");
- System.err.println(url.toString());
conn = new AMQConnection(url);
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java
index 3fe4514..dfec1a8 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java
@@ -106,7 +106,7 @@
}
catch (Exception e)
{
- assertTrue("Exception should say the exchange is not known.", e.getMessage().contains("Unknown exchange: " + EXCHANGE_NAME));
+ assertTrue("Exception should say the exchange is not known.", e.getMessage().contains("Unknown exchange: '" + EXCHANGE_NAME + "'"));
}
try
@@ -119,7 +119,7 @@
}
catch (Exception e)
{
- assertTrue("Exception should say the exchange is not known.", e.getMessage().contains("Unknown exchange: " + EXCHANGE_NAME));
+ assertTrue("Exception should say the exchange is not known.", e.getMessage().contains("Unknown exchange: '" + EXCHANGE_NAME + "'"));
}
}
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/close/MessageConsumerCloseTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/close/MessageConsumerCloseTest.java
index df32bd7..de30a98 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/close/MessageConsumerCloseTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/close/MessageConsumerCloseTest.java
@@ -35,7 +35,7 @@
public class MessageConsumerCloseTest extends QpidBrokerTestCase
{
- Exception _exception;
+ private volatile Exception _exception;
public void testConsumerCloseAndSessionRollback() throws Exception
{
@@ -65,7 +65,7 @@
boolean messageReceived = receiveLatch.await(1l, TimeUnit.SECONDS);
consumer.close();
- assertNull("Exception occured on rollback:" + _exception, _exception);
+ assertNull("Exception occurred on rollback:" + _exception, _exception);
assertTrue("Message is not received", messageReceived);
consumer = session.createConsumer(destination);
@@ -74,4 +74,38 @@
Message message2 = consumer.receive(1000l);
assertNotNull("message2 is not received", message2);
}
+
+ public void testPrefetchedMessagesReleasedOnConsumerClose() throws Exception
+ {
+ Connection connection = getConnection();
+ final Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
+
+ Destination destination = getTestQueue();
+ MessageConsumer consumer = session.createConsumer(destination);
+
+ sendMessage(session, destination, 3);
+
+ connection.start();
+
+ Message msg1 = consumer.receive(1000);
+ assertNotNull("Message one was null", msg1);
+ assertEquals("Message one has unexpected content", 0, msg1.getIntProperty(INDEX));
+ session.commit();
+
+ // Messages two and three will have been prefetched by the consumer.
+ // Closing the consumer must make the available for delivery elsewhere
+
+ consumer.close();
+
+ MessageConsumer consumer2 = session.createConsumer(destination);
+
+ Message msg2 = consumer2.receive(1000);
+ Message msg3 = consumer2.receive(1000);
+ assertNotNull("Message two was null", msg2);
+ assertEquals("Message two has unexpected content", 1, msg2.getIntProperty(INDEX));
+
+ assertNotNull("Message three was null", msg3);
+ assertEquals("Message three has unexpected content", 2, msg3.getIntProperty(INDEX));
+ session.commit();
+ }
}
diff --git a/qpid/java/test-profiles/JavaExcludes b/qpid/java/test-profiles/JavaExcludes
index c4b864f..b52987f 100644
--- a/qpid/java/test-profiles/JavaExcludes
+++ b/qpid/java/test-profiles/JavaExcludes
@@ -24,9 +24,6 @@
org.apache.qpid.test.client.queue.QueuePolicyTest#testRingPolicy
org.apache.qpid.test.client.queue.QueuePolicyTest#testRejectPolicy
-//QPID-3605 Durable subscriber with no-local true receives messages on re-connection
-org.apache.qpid.test.unit.topic.DurableSubscriptionTest#testNoLocalMessagesNotDeliveredAfterReconnection
-
//QPID-4153 Messages causing a runtime selector error should be dead-lettered (or something similar)
org.apache.qpid.test.client.message.SelectorTest#testRuntimeSelectorError
diff --git a/qpid/java/test-profiles/python_tests/Java010PythonExcludes b/qpid/java/test-profiles/python_tests/Java010PythonExcludes
index 9008254..530caad 100644
--- a/qpid/java/test-profiles/python_tests/Java010PythonExcludes
+++ b/qpid/java/test-profiles/python_tests/Java010PythonExcludes
@@ -53,6 +53,8 @@
qpid_tests.broker_0_10.priority.PriorityTests.test_ring_queue*
qpid_tests.broker_0_10.priority.PriorityTests.test_fairshare*
qpid_tests.broker_0_10.priority.PriorityTests.test_prioritised_delivery_with_alias
+#QPID-6299 broker does not support ring queue on lvq
+qpid_tests.broker_0_10.lvq.LVQTests.test_ring_lvq2
#The broker does not support the autodelete property on exchanges
qpid_tests.broker_0_10.exchange.AutodeleteTests.testAutodelete*
diff --git a/qpid/java/test-profiles/test_resources/log4j.xml b/qpid/java/test-profiles/test_resources/log4j.xml
new file mode 100644
index 0000000..8c59ffd
--- /dev/null
+++ b/qpid/java/test-profiles/test_resources/log4j.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ --><!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="null" threshold="null">
+
+
+
+ <appender class="org.apache.log4j.FileAppender" name="TestAppender">
+ <param name="File" value="${test.output.dir}${file.separator}TEST-${qpid.testClass}${qpid.testMethod}.txt"/>
+ <param name="Append" value="false"/>
+
+
+ <!-- TODO date not interesting for test debugging. log only the time to save width -->
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%d %-5p [%t] (%c{2}) - %m%n"/>
+ </layout>
+ </appender>
+
+
+ <!-- General logging hierarchy -->
+ <logger name="org.apache.qpid">
+ <level value="${amqj.logging.level}"/>
+ </logger>
+
+ <logger name="qpid.message">
+ <level value="INFO"/>
+ </logger>
+
+
+ <!-- Log all info events to file -->
+ <root>
+ <level value="debug"/>
+ <appender-ref ref="TestAppender"/>
+ </root>
+
+</log4j:configuration>
diff --git a/qpid/java/test-profiles/log4j-test.xml b/qpid/java/test-profiles/test_resources/spawned-broker-log4j.xml
similarity index 87%
rename from qpid/java/test-profiles/log4j-test.xml
rename to qpid/java/test-profiles/test_resources/spawned-broker-log4j.xml
index a393fa0..eb75e74 100644
--- a/qpid/java/test-profiles/log4j-test.xml
+++ b/qpid/java/test-profiles/test_resources/spawned-broker-log4j.xml
@@ -32,7 +32,7 @@
<param name="ImmediateFlush" value="true"/>
<param name="Follow" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern" value="%t %d %p [%c{4}] %m%n"/>
+ <param name="ConversionPattern" value="%d %-5p [%t] (%c{2}) - %m%n"/>
</layout>
</appender>
@@ -48,18 +48,10 @@
<level value="${amqj.protocol.logging.level}"/>
</logger>
- <logger name="org.apache.qpid.test.utils.QpidTestCase">
- <level value="ALL"/>
- </logger>
-
<logger name="org.apache.commons">
<level value="WARN"/>
</logger>
- <logger name="apache.commons.configuration.ConfigurationFactory">
- <level value="ERROR"/>
- </logger>
-
<root>
<level value="${root.logging.level}"/>
<appender-ref ref="console" />
diff --git a/qpid/python/qpid/codec010.py b/qpid/python/qpid/codec010.py
index 94a1cd4..f4dc60f 100644
--- a/qpid/python/qpid/codec010.py
+++ b/qpid/python/qpid/codec010.py
@@ -225,6 +225,9 @@
def write_vbin32(self, b):
if isinstance(b, buffer):
b = str(b)
+ # Allow unicode values in connection 'response' field
+ if isinstance(b, unicode):
+ b = b.encode('utf8')
self.write_uint32(len(b))
self.write(b)
diff --git a/qpid/python/qpid/sasl.py b/qpid/python/qpid/sasl.py
index 85e31e3..a2147e3 100644
--- a/qpid/python/qpid/sasl.py
+++ b/qpid/python/qpid/sasl.py
@@ -28,6 +28,9 @@
self._cli = _Client()
def setAttr(self, name, value):
+ # Allow unicode user names and passwords
+ if isinstance(value, unicode):
+ value = value.encode('utf8')
status = self._cli.setAttr(str(name), str(value))
if status and name == 'username':
status = self._cli.setAttr('externaluser', str(value))
diff --git a/qpid/tests/src/py/qpid_tests/broker_0_10/lvq.py b/qpid/tests/src/py/qpid_tests/broker_0_10/lvq.py
index 476b6ee..07a8906 100644
--- a/qpid/tests/src/py/qpid_tests/broker_0_10/lvq.py
+++ b/qpid/tests/src/py/qpid_tests/broker_0_10/lvq.py
@@ -6,9 +6,9 @@
# 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
@@ -20,18 +20,19 @@
from qpid.tests.messaging.implementation import *
from qpid.tests.messaging import Base
import math
+import random
class LVQTests (Base):
"""
Test last value queue behaviour
- """
+ """
def setup_connection(self):
return Connection.establish(self.broker, **self.connection_options())
def setup_session(self):
return self.conn.session()
-
+
def test_simple(self):
snd = self.ssn.sender("lvq; {create: sender, delete: sender, node: {x-declare:{arguments:{'qpid.last_value_queue_key':lvq-key}}}}",
durable=self.durable())
@@ -59,6 +60,42 @@
rcv = self.ssn.receiver("lvq; {mode: browse}")
assert (fetch_all(rcv) == ["a-3", "c-3", "d-1", "b-3"])
+ def check_ring_lvq(self, ring_size, keys, message_count):
+ address = "lvq; {create: sender, delete: sender, node: {x-declare:{arguments:{'qpid.last_value_queue_key':lvq-key,'qpid.policy_type':'ring','qpid.max_count':%i}}}}" % ring_size
+ snd = self.ssn.sender(address, durable=self.durable())
+ counters = {}
+ for k in keys:
+ counters[k] = 0
+ messages = []
+ for i in range(message_count):
+ k = random.choice(keys)
+ counters[k] += 1
+ messages.append(create_message(k, "%s-%i" % (k, counters[k])))
+ # make sure we have sent at least one message for every key
+ for k, v in counters.iteritems():
+ if v == 0:
+ counters[k] += 1
+ messages.append(create_message(k, "%s-%i" % (k, counters[k])))
+
+ for m in messages:
+ snd.send(m)
+
+ rcv = self.ssn.receiver("lvq; {mode: browse}")
+ retrieved = fetch_all_as_tuples(rcv)
+ print [v for k, v in retrieved]
+
+ for k, v in retrieved:
+ assert v == "%s-%i" % (k, counters[k])
+ assert len(retrieved) <= ring_size
+
+ def test_ring_lvq1(self):
+ self.check_ring_lvq(25, ["a","b","c","d"], 50)
+
+ def test_ring_lvq2(self):
+ self.check_ring_lvq(5, ["a","b","c","d","e","f","g"], 50)
+
+ def test_ring_lvq3(self):
+ self.check_ring_lvq(49, ["a"], 50)
def create_message(key, content):
msg = Message(content=content, properties={"lvq-key":key})
@@ -72,3 +109,14 @@
except Empty:
break
return content
+
+def fetch_all_as_tuples(rcv):
+ content = []
+ while True:
+ try:
+ m = rcv.fetch(0)
+ k = m.properties["lvq-key"]
+ content.append((k, m.content))
+ except Empty:
+ break
+ return content
diff --git a/qpid/tools/src/py/qlslibs/anal.py b/qpid/tools/src/py/qlslibs/analyze.py
similarity index 95%
rename from qpid/tools/src/py/qlslibs/anal.py
rename to qpid/tools/src/py/qlslibs/analyze.py
index df51c1b..a67e17e 100644
--- a/qpid/tools/src/py/qlslibs/anal.py
+++ b/qpid/tools/src/py/qlslibs/analyze.py
@@ -18,7 +18,7 @@
#
"""
-Module: qlslibs.anal
+Module: qlslibs.analyze
Classes for recovery and analysis of a Qpid Linear Store (QLS).
"""
@@ -41,8 +41,8 @@
return self.num
class JournalRecoveryManager(object):
- TPL_DIR_NAME = 'tpl'
- JRNL_DIR_NAME = 'jrnl'
+ TPL_DIR_NAME = 'tpl2'
+ JRNL_DIR_NAME = 'jrnl2'
def __init__(self, directory, args):
if not os.path.exists(directory):
raise qlslibs.err.InvalidQlsDirectoryNameError(directory)
@@ -55,15 +55,15 @@
def report(self, print_stats_flag):
self._reconcile_transactions(self.prepared_list, self.args.txn)
if self.tpl is not None:
- self.tpl.report(print_stats_flag)
+ self.tpl.report(print_stats_flag, self.args.show_recovered_recs)
for queue_name in sorted(self.journals.keys()):
- self.journals[queue_name].report(print_stats_flag)
+ self.journals[queue_name].report(print_stats_flag, self.args.show_recovered_recs)
def run(self):
tpl_dir = os.path.join(self.directory, JournalRecoveryManager.TPL_DIR_NAME)
if os.path.exists(tpl_dir):
self.tpl = Journal(tpl_dir, None, self.args)
self.tpl.recover(self.high_rid_counter)
- if self.args.show_recs or self.args.show_all_recs:
+ if self.args.show_recovery_recs or self.args.show_all_recs:
print
jrnl_dir = os.path.join(self.directory, JournalRecoveryManager.JRNL_DIR_NAME)
self.prepared_list = self.tpl.txn_map.get_prepared_list() if self.tpl is not None else {}
@@ -72,8 +72,9 @@
jrnl = Journal(os.path.join(jrnl_dir, dir_entry), self.prepared_list, self.args)
jrnl.recover(self.high_rid_counter)
self.journals[jrnl.get_queue_name()] = jrnl
- if self.args.show_recs or self.args.show_all_recs:
+ if self.args.show_recovery_recs or self.args.show_all_recs:
print
+ print
def _reconcile_transactions(self, prepared_list, txn_flag):
print 'Transaction reconciliation report:'
print '=================================='
@@ -315,6 +316,7 @@
"""
Instance of a Qpid Linear Store (QLS) journal.
"""
+ JRNL_SUFFIX = 'jrnl'
def __init__(self, directory, xid_prepared_list, args):
self.directory = directory
self.queue_name = os.path.basename(directory)
@@ -350,7 +352,7 @@
def get_queue_name(self):
return self.queue_name
def recover(self, high_rid_counter):
- print 'Recovering', self.queue_name
+ print 'Recovering %s...' % self.queue_name,
self._analyze_files()
try:
while self._get_next_record(high_rid_counter):
@@ -362,6 +364,7 @@
print '0x%08x: **** FRO ERROR: queue=\"%s\" fid=0x%x fro actual=0x%08x expected=0x%08x' % \
(err.get_expected_fro(), err.get_queue_name(), err.get_file_number(), err.get_record_offset(),
err.get_expected_fro())
+ print 'done'
def reconcile_transactions(self, prepared_list, txn_flag):
xid_list = self.txn_map.get_xid_list()
if len(xid_list) > 0:
@@ -385,13 +388,13 @@
print ' ', qlslibs.utils.format_xid(xid), '- Ignoring, not in prepared transaction list'
if txn_flag:
self.txn_map.abort(xid)
- def report(self, print_stats_flag):
+ def report(self, print_stats_flag, show_recovered_records):
print 'Journal "%s":' % self.queue_name
print '=' * (11 + len(self.queue_name))
if print_stats_flag:
print str(self.statistics)
- print self.enq_map.report_str(True, True)
- print self.txn_map.report_str(True, True)
+ print self.enq_map.report_str(True, show_recovered_records)
+ print self.txn_map.report_str(True, show_recovered_records)
JournalFile.report_header()
for file_num in sorted(self.files.keys()):
self.files[file_num].report()
@@ -405,7 +408,7 @@
def _analyze_files(self):
for dir_entry in os.listdir(self.directory):
dir_entry_bits = dir_entry.split('.')
- if len(dir_entry_bits) == 2 and dir_entry_bits[1] == JournalRecoveryManager.JRNL_DIR_NAME:
+ if len(dir_entry_bits) == 2 and dir_entry_bits[1] == Journal.JRNL_SUFFIX:
fq_file_name = os.path.join(self.directory, dir_entry)
file_handle = open(fq_file_name)
args = qlslibs.utils.load_args(file_handle, qlslibs.jrnl.RecordHeader)
@@ -413,7 +416,7 @@
file_hdr.init(file_handle, *qlslibs.utils.load_args(file_handle, qlslibs.jrnl.FileHeader))
if file_hdr.is_header_valid(file_hdr):
file_hdr.load(file_handle)
- if file_hdr.is_valid():
+ if file_hdr.is_valid(False):
qlslibs.utils.skip(file_handle,
file_hdr.file_header_size_sblks * qlslibs.utils.DEFAULT_SBLK_SIZE)
self.files[file_hdr.file_num] = JournalFile(file_hdr)
@@ -430,7 +433,7 @@
qlslibs.utils.DEFAULT_DBLK_SIZE
self.fill_to_offset = self.last_record_offset + \
(self.num_filler_records_required * qlslibs.utils.DEFAULT_DBLK_SIZE)
- if self.args.show_recs or self.args.show_all_recs:
+ if self.args.show_recovery_recs or self.args.show_all_recs:
print '0x%x:0x%08x: %d filler records required for DBLK alignment to 0x%08x' % \
(self.current_journal_file.file_header.file_num, self.last_record_offset,
self.num_filler_records_required, self.fill_to_offset)
@@ -460,7 +463,7 @@
return False
self.current_journal_file = self.files[file_num]
self.first_rec_flag = True
- if self.args.show_recs or self.args.show_all_recs:
+ if self.args.show_recovery_recs or self.args.show_all_recs:
file_header = self.current_journal_file.file_header
print '0x%x:%s' % (file_header.file_num, file_header.to_string())
return True
@@ -480,18 +483,18 @@
if isinstance(this_record, qlslibs.jrnl.EnqueueRecord):
ok_flag = self._handle_enqueue_record(this_record, start_journal_file)
high_rid_counter.check(this_record.record_id)
- if self.args.show_recs or self.args.show_all_recs:
+ if self.args.show_recovery_recs or self.args.show_all_recs:
print '0x%x:%s' % (start_journal_file.file_header.file_num, \
this_record.to_string(self.args.show_xids, self.args.show_data))
elif isinstance(this_record, qlslibs.jrnl.DequeueRecord):
ok_flag = self._handle_dequeue_record(this_record, start_journal_file)
high_rid_counter.check(this_record.record_id)
- if self.args.show_recs or self.args.show_all_recs:
+ if self.args.show_recovery_recs or self.args.show_all_recs:
print '0x%x:%s' % (start_journal_file.file_header.file_num, this_record.to_string(self.args.show_xids))
elif isinstance(this_record, qlslibs.jrnl.TransactionRecord):
ok_flag = self._handle_transaction_record(this_record, start_journal_file)
high_rid_counter.check(this_record.record_id)
- if self.args.show_recs or self.args.show_all_recs:
+ if self.args.show_recovery_recs or self.args.show_all_recs:
print '0x%x:%s' % (start_journal_file.file_header.file_num, this_record.to_string(self.args.show_xids))
else:
self.statistics.filler_record_count += 1
diff --git a/qpid/tools/src/py/qlslibs/efp.py b/qpid/tools/src/py/qlslibs/efp.py
index 0fa27b3..1c751c3 100644
--- a/qpid/tools/src/py/qlslibs/efp.py
+++ b/qpid/tools/src/py/qlslibs/efp.py
@@ -85,15 +85,16 @@
self.efp_partitions.remove(self.current_efp_partition)
shutil.rmtree(os.path.join(self.current_efp_partition.efp_directory, dir_name))
def report(self):
- print 'Empty File Pool (EFP) report:'
- print '============================='
- print 'Found', len(self.efp_partitions), 'partition(s).'
+ print 'Empty File Pool (EFP) report'
+ print '============================'
+ print 'Found', len(self.efp_partitions), 'partition(s)'
if (len(self.efp_partitions)) > 0:
+ sorted_efp_partitions = sorted(self.efp_partitions, key=lambda x: x.partition_number)
EfpPartition.print_report_table_header()
- for ptn in self.efp_partitions:
+ for ptn in sorted_efp_partitions:
ptn.print_report_table_line()
print
- for ptn in self.efp_partitions:
+ for ptn in sorted_efp_partitions:
ptn.report()
def run(self, arg_tup):
self._analyze_efp()
@@ -182,9 +183,12 @@
self.tot_file_size_kb, self.directory)
def report(self):
print 'Partition %s:' % os.path.basename(self.directory)
- EmptyFilePool.print_report_table_header()
- for dir_name in self.efp_pools.keys():
- self.efp_pools[dir_name].print_report_table_line()
+ if len(self.efp_pools) > 0:
+ EmptyFilePool.print_report_table_header()
+ for dir_name in self.efp_pools.keys():
+ self.efp_pools[dir_name].print_report_table_line()
+ else:
+ print '<empty - no EFPs found in this partition>'
print
def scan(self):
if os.path.exists(self.directory):
@@ -217,13 +221,16 @@
"""
EFP_DIR_SUFFIX = 'k'
EFP_JRNL_EXTENTION = '.jrnl'
+ EFP_INUSE_DIRNAME = 'in_use'
+ EFP_RETURNED_DIRNAME = 'returned'
def __init__(self, directory, partition_number):
self.base_dir_name = os.path.basename(directory)
self.directory = directory
self.partition_number = partition_number
self.data_size_kb = None
- self.files = []
- self.tot_file_size_kb = 0
+ self.efp_files = []
+ self.in_use_files = []
+ self.returned_files = []
self._validate_efp_directory()
def create_new_efp_files(self, num_files):
""" Create one or more new empty journal files of the prescribed size for this EFP """
@@ -238,24 +245,37 @@
""" Static function to create an EFP directory name from the size of the files it contains """
return '%dk' % file_size_kb
def get_tot_file_count(self):
- return len(self.files)
+ return len(self.efp_files)
def get_tot_file_size_kb(self):
- return self.data_size_kb * len(self.files)
+ return self.data_size_kb * len(self.efp_files)
@staticmethod
def print_report_table_header():
- print 'data_size_kb file_count tot_file_size_kb efp_directory'
- print '------------ ---------- ---------------- -------------'
+ print ' ---------- efp ------------ --------- in_use ---------- -------- returned ---------'
+ print 'data_size_kb file_count tot_file_size_kb file_count tot_file_size_kb file_count tot_file_size_kb efp_directory'
+ print '------------ ---------- ---------------- ---------- ---------------- ---------- ---------------- -------------'
def print_report_table_line(self):
- print '%12d %10d %16d %s' % (self.data_size_kb, self.get_tot_file_count(),
- self.get_tot_file_size_kb(), self.get_directory())
+ print '%12d %10d %16d %10d %16d %10d %16d %s' % (self.data_size_kb, len(self.efp_files),
+ self.data_size_kb * len(self.efp_files),
+ len(self.in_use_files),
+ self.data_size_kb * len(self.in_use_files),
+ len(self.returned_files),
+ self.data_size_kb * len(self.returned_files),
+ self.get_directory())
def scan(self):
for efp_file in os.listdir(self.directory):
+ if efp_file == self.EFP_INUSE_DIRNAME:
+ for in_use_file in os.listdir(os.path.join(self.directory, self.EFP_INUSE_DIRNAME)):
+ self.in_use_files.append(in_use_file)
+ continue
+ if efp_file == self.EFP_RETURNED_DIRNAME:
+ for returned_file in os.listdir(os.path.join(self.directory, self.EFP_RETURNED_DIRNAME)):
+ self.returned_files.append(returned_file)
+ continue
if self._validate_efp_file(os.path.join(self.directory, efp_file)):
- self.files.append(efp_file)
+ self.efp_files.append(efp_file)
def _add_efp_file(self, efp_file_name):
""" Add a single journal file of the appropriate size to this EFP. No file size check is made here. """
- self.files.append(efp_file_name)
- self.tot_file_size_kb += os.path.getsize(efp_file_name)
+ self.efp_files.append(efp_file_name)
def _create_new_efp_file(self):
""" Create a single new empty journal file of the prescribed size for this EFP """
file_name = str(uuid.uuid4()) + EmptyFilePool.EFP_JRNL_EXTENTION
@@ -296,7 +316,7 @@
return False
file_hdr.load(file_handle)
file_handle.close()
- if not file_hdr.is_valid():
+ if not file_hdr.is_valid(True):
return False
return True
diff --git a/qpid/tools/src/py/qlslibs/jrnl.py b/qpid/tools/src/py/qlslibs/jrnl.py
index 555cf6a..ee25015 100644
--- a/qpid/tools/src/py/qlslibs/jrnl.py
+++ b/qpid/tools/src/py/qlslibs/jrnl.py
@@ -155,19 +155,24 @@
self.queue_name = file_handle.read(self.queue_name_len)
def is_end_of_file(self):
return self.file_handle.tell() >= self.get_file_size()
- def is_valid(self):
+ def is_valid(self, is_empty):
if not RecordHeader.is_header_valid(self, self):
return False
if self.file_handle is None or self.file_header_size_sblks == 0 or self.partition_num == 0 or \
- self.efp_data_size_kb == 0 or self.first_record_offset == 0 or self.timestamp_sec == 0 or \
- self.timestamp_ns == 0 or self.file_num == 0:
+ self.efp_data_size_kb == 0:
return False
- if self.queue_name_len == 0:
- return False
- if self.queue_name is None:
- return False
- if len(self.queue_name) != self.queue_name_len:
- return False
+ if is_empty:
+ if self.first_record_offset != 0 or self.timestamp_sec != 0 or self.timestamp_ns != 0 or \
+ self.file_num != 0 or self.queue_name_len != 0:
+ return False
+ else:
+ if self.first_record_offset == 0 or self.timestamp_sec == 0 or self.timestamp_ns == 0 or \
+ self.file_num == 0 or self.queue_name_len == 0:
+ return False
+ if self.queue_name is None:
+ return False
+ if len(self.queue_name) != self.queue_name_len:
+ return False
return True
def timestamp_str(self):
"""Get the timestamp of this record in string format"""
diff --git a/qpid/tools/src/py/qpid-config b/qpid/tools/src/py/qpid-config
index ac93954..8d38b1a 100755
--- a/qpid/tools/src/py/qpid-config
+++ b/qpid/tools/src/py/qpid-config
@@ -105,6 +105,8 @@
self._if_unused = True
self._fileCount = None
self._fileSize = None
+ self._efp_partition_num = None
+ self._efp_pool_file_size = None
self._maxQueueSize = None
self._maxQueueCount = None
self._limitPolicy = None
@@ -137,6 +139,8 @@
FILECOUNT = "qpid.file_count"
FILESIZE = "qpid.file_size"
+EFP_PARTITION_NUM = "qpid.efp_partition_num"
+EFP_POOL_FILE_SIZE = "qpid.efp_pool_file_size"
MAX_QUEUE_SIZE = "qpid.max_size"
MAX_QUEUE_COUNT = "qpid.max_count"
POLICY_TYPE = "qpid.policy_type"
@@ -158,7 +162,8 @@
#i.e. the arguments for which there is special processing on add and
#list
SPECIAL_ARGS=[
- FILECOUNT,FILESIZE,MAX_QUEUE_SIZE,MAX_QUEUE_COUNT,POLICY_TYPE,
+ FILECOUNT,FILESIZE,EFP_PARTITION_NUM,EFP_POOL_FILE_SIZE,
+ MAX_QUEUE_SIZE,MAX_QUEUE_COUNT,POLICY_TYPE,
LVQ_KEY,MSG_SEQUENCE,IVE,QUEUE_EVENT_GENERATION,
FLOW_STOP_COUNT,FLOW_RESUME_COUNT,FLOW_STOP_SIZE,FLOW_RESUME_SIZE,
MSG_GROUP_HDR_KEY,SHARED_MSG_GROUP,REPLICATE]
@@ -213,8 +218,10 @@
parser.add_option_group(group2)
group3 = OptionGroup(parser, "Options for Adding Queues")
- group3.add_option("--file-count", action="store", type="int", metavar="<n>", help="Number of files in queue's persistence journal")
- group3.add_option("--file-size", action="store", type="int", metavar="<n>", help="File size in pages (64KiB/page)")
+ group3.add_option("--file-count", action="store", type="int", metavar="<n>", help="[legacystore] Number of files in queue's persistence journal")
+ group3.add_option("--file-size", action="store", type="int", metavar="<n>", help="[legactystore] File size in pages (64KiB/page)")
+ group3.add_option("--efp-partition-num", action="store", type="int", metavar="<n>", help="[linearstore] EFP partition number")
+ group3.add_option("--efp-pool-file-size", action="store", type="int", metavar="<n>", help="[linearstore] EFP file size (KiB)")
group3.add_option("--max-queue-size", action="store", type="int", metavar="<n>", help="Maximum in-memory queue size as bytes")
group3.add_option("--max-queue-count", action="store", type="int", metavar="<n>", help="Maximum in-memory queue size as a number of messages")
group3.add_option("--limit-policy", action="store", choices=["none", "reject", "ring", "ring-strict"], metavar="<policy>", help="Action to take when queue limit is reached")
@@ -294,6 +301,10 @@
config._fileCount = opts.file_count
if opts.file_size is not None:
config._fileSize = opts.file_size
+ if opts.efp_partition_num is not None:
+ config._efp_partition_num = opts.efp_partition_num
+ if opts.efp_pool_file_size is not None:
+ config._efp_pool_file_size = opts.efp_pool_file_size
if opts.max_queue_size is not None:
config._maxQueueSize = opts.max_queue_size
if opts.max_queue_count is not None:
@@ -524,6 +535,8 @@
if q.exclusive: print "excl",
if FILESIZE in args: print "--file-size=%s" % args[FILESIZE],
if FILECOUNT in args: print "--file-count=%s" % args[FILECOUNT],
+ if EFP_PARTITION_NUM in args: print "--efp-partition-num=%s" % args[EFP_PARTITION_NUM],
+ if EFP_POOL_FILE_SIZE in args: print "--efp-pool-file-size=%s" % args[EFP_POOL_FILE_SIZE],
if MAX_QUEUE_SIZE in args: print "--max-queue-size=%s" % args[MAX_QUEUE_SIZE],
if MAX_QUEUE_COUNT in args: print "--max-queue-count=%s" % args[MAX_QUEUE_COUNT],
if POLICY_TYPE in args: print "--limit-policy=%s" % args[POLICY_TYPE].replace("_", "-"),
@@ -606,6 +619,10 @@
declArgs[FILECOUNT] = config._fileCount
if config._fileSize:
declArgs[FILESIZE] = config._fileSize
+ if config._efp_partition_num:
+ declArgs[EFP_PARTITION_NUM] = config._efp_partition_num
+ if config._efp_pool_file_size:
+ declArgs[EFP_POOL_FILE_SIZE] = config._efp_pool_file_size
if config._maxQueueSize is not None:
declArgs[MAX_QUEUE_SIZE] = config._maxQueueSize
diff --git a/qpid/tools/src/py/qpid-qls-analyze b/qpid/tools/src/py/qpid-qls-analyze
index 5c7d04b..35b370f 100755
--- a/qpid/tools/src/py/qpid-qls-analyze
+++ b/qpid/tools/src/py/qpid-qls-analyze
@@ -28,11 +28,11 @@
default = os.path.normpath('/usr/share/qpid-tools')
home = os.environ.get('QPID_TOOLS_HOME', default)
-sys.path.append(os.path.join(home,'python'))
+sys.path.append(os.path.join(home, 'python'))
import argparse
import os
-import qlslibs.anal
+import qlslibs.analyze
import qlslibs.efp
class QlsAnalyzerArgParser(argparse.ArgumentParser):
@@ -45,7 +45,9 @@
help='Qpid Linear Store (QLS) directory to be analyzed')
self.add_argument('--efp', action='store_true',
help='Analyze the Emtpy File Pool (EFP) and show stats')
- self.add_argument('--show-recs', action='store_true',
+ self.add_argument('--show-recovered-recs', action='store_true',
+ help='Show only recovered records')
+ self.add_argument('--show-recovery-recs', action='store_true',
help='Show material records found during recovery')
self.add_argument('--show-all-recs', action='store_true',
help='Show all records (including fillers) found during recovery')
@@ -72,13 +74,13 @@
* The Linear Store
* The Transaction Prepared List (TPL)
"""
- QLS_ANALYZE_VERSION = '0.1'
+ QLS_ANALYZE_VERSION = '1.0'
def __init__(self):
self.args = None
self._process_args()
self.qls_dir = os.path.abspath(self.args.qls_dir)
self.efp_manager = qlslibs.efp.EfpManager(self.qls_dir, None)
- self.jrnl_recovery_mgr = qlslibs.anal.JournalRecoveryManager(self.qls_dir, self.args)
+ self.jrnl_recovery_mgr = qlslibs.analyze.JournalRecoveryManager(self.qls_dir, self.args)
def _process_args(self):
""" Create arg parser and process args """
parser = QlsAnalyzerArgParser()
@@ -101,10 +103,6 @@
#==============================================================================
if __name__ == "__main__":
- # TODO: Remove this in due course
- print 'WARNING: This program is still a work in progress and is largely untested.'
- print '* USE AT YOUR OWN RISK *'
- print
M = QqpdLinearStoreAnalyzer()
M.run()
M.report()
diff --git a/qpid/tools/src/py/qpid-route b/qpid/tools/src/py/qpid-route
index 6890f2a..66c0e6d 100755
--- a/qpid/tools/src/py/qpid-route
+++ b/qpid/tools/src/py/qpid-route
@@ -25,6 +25,7 @@
import os
import locale
from qmf.console import Session, BrokerURL
+from time import sleep
usage = """
Usage: qpid-route [OPTIONS] dynamic add <dest-broker> <src-broker> <exchange> [tag] [exclude-list] [mechanism]
@@ -184,6 +185,21 @@
return link
return None
+ def checkLink(self, link):
+ retry = 3
+ while link is None or (link.state in ("Waiting", "Connecting", "Closing") and retry > 0):
+ sleep(1)
+ link = self.getLink()
+ retry -= 1
+
+ if link == None:
+ raise Exception("Link failed to create")
+
+ if link.state == "Failed":
+ raise Exception("Link failed to create %s" % (link.lastError or ""))
+ elif config._verbose:
+ print "Link state is", link.state
+
def addLink(self, remoteBroker, interbroker_mechanism=""):
self.remote = BrokerURL(remoteBroker)
if self.local.match(self.remote.host, self.remote.port):
@@ -196,8 +212,6 @@
res = broker.connect(self.remote.host, self.remote.port, config._durable,
interbroker_mechanism, self.remote.authName or "", self.remote.authPass or "",
config._transport)
- if config._verbose:
- print "Connect method returned:", res.status, res.text
def delLink(self, remoteBroker):
self.remote = BrokerURL(remoteBroker)
@@ -321,8 +335,7 @@
self.addLink(remoteBroker, interbroker_mechanism)
link = self.getLink()
- if link == None:
- raise Exception("Link failed to create")
+ self.checkLink(link)
bridges = self.agent.getObjects(_class="bridge")
for bridge in bridges:
@@ -345,8 +358,7 @@
def addQueueRoute(self, remoteBroker, interbroker_mechanism, exchange, queue ):
self.addLink(remoteBroker, interbroker_mechanism)
link = self.getLink()
- if link == None:
- raise Exception("Link failed to create")
+ self.checkLink(link)
bridges = self.agent.getObjects(_class="bridge")
for bridge in bridges:
@@ -537,6 +549,7 @@
interbroker_mechanism = ""
if nargs > 4: interbroker_mechanism = args[4]
rm.addLink(remoteBroker, interbroker_mechanism)
+ rm.checkLink(rm.getLink())
elif cmd == "del":
if nargs != 4:
Usage()