/**
* 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 io.hawtjms.provider.stomp.adapters;
import static io.hawtjms.provider.stomp.StompConstants.CONTENT_LENGTH;
import static io.hawtjms.provider.stomp.StompConstants.CONTENT_TYPE;
import static io.hawtjms.provider.stomp.StompConstants.ID;
import static io.hawtjms.provider.stomp.StompConstants.TRANSFORMATION;
import static io.hawtjms.provider.stomp.StompConstants.UNSUBSCRIBE;
import io.hawtjms.jms.JmsDestination;
import io.hawtjms.jms.JmsQueue;
import io.hawtjms.jms.JmsTopic;
import io.hawtjms.jms.message.JmsMessage;
import io.hawtjms.jms.meta.JmsConsumerInfo;
import io.hawtjms.provider.stomp.StompConnection;
import io.hawtjms.provider.stomp.StompFrame;
import io.hawtjms.provider.stomp.message.StompJmsBytesMessage;
import io.hawtjms.provider.stomp.message.StompJmsMessageFacade;
import io.hawtjms.provider.stomp.message.StompJmsMessageFactory;
import io.hawtjms.provider.stomp.message.StompJmsTextMessage;
import javax.jms.JMSException;
/**
* Base adapter class for supporting STOMP servers that offer extended features
* beyond the defined STOMP specification.
*/
public class GenericStompServerAdaptor implements StompServerAdapter {
private final String version;
private final StompConnection connection;
public GenericStompServerAdaptor(StompConnection connection) {
this.version = "Unknown";
this.connection = connection;
}
public GenericStompServerAdaptor(StompConnection connection, String version) {
this.version = version;
this.connection = connection;
}
@Override
public StompConnection getStompConnection() {
return this.connection;
}
@Override
public String getQueuePrefix() {
return connection.getQueuePrefix();
}
@Override
public String getTopicPrefix() {
return connection.getTopicPrefix();
}
@Override
public String getTempQueuePrefix() {
return connection.getTempQueuePrefix();
}
@Override
public String getTempTopicPrefix() {
return connection.getTempTopicPrefix();
}
@Override
public String toStompDestination(JmsDestination destination) {
String result = null;
if (destination.isTopic()) {
if (destination.isTemporary()) {
result = getTempTopicPrefix() + destination.getName();
} else {
result = getTopicPrefix() + destination.getName();
}
} else {
if (destination.isTemporary()) {
result = getTempQueuePrefix() + destination.getName();
} else {
result = getQueuePrefix() + destination.getName();
}
}
return result;
}
@Override
public JmsDestination toJmsDestination(String destinationName) throws JMSException {
JmsDestination result = null;
if (destinationName == null) {
return null;
}
if (destinationName.startsWith(getTopicPrefix())) {
result = new JmsTopic(destinationName.substring(getTopicPrefix().length()));
} else if (destinationName.startsWith(getQueuePrefix())) {
result = new JmsQueue(destinationName.substring(getQueuePrefix().length()));
} else if (destinationName.startsWith(getTempTopicPrefix())) {
result = new JmsQueue(destinationName.substring(getTempTopicPrefix().length()));
} else if (destinationName.startsWith(getTempQueuePrefix())) {
result = new JmsQueue(destinationName.substring(getTempQueuePrefix().length()));
} else {
throw new JMSException("Cannot transform unknown destination type: " + destinationName);
}
return result;
}
@Override
public StompFrame createCreditFrame(StompFrame messageFrame) {
return null;
}
@Override
public void addSubscribeHeaders(StompFrame frame, JmsConsumerInfo consumerInfo) throws JMSException {
if (consumerInfo.isBrowser()) {
throw new JMSException("Server does not support browsing over STOMP");
}
if (consumerInfo.isNoLocal()) {
throw new JMSException("Server does not support 'no local' semantics over STOMP");
}
if (consumerInfo.isDurable()) {
throw new JMSException("Server does not durable subscriptions over STOMP");
}
}
@Override
public boolean isEndOfBrowse(StompFrame message) {
return false;
}
@Override
public StompFrame createUnsubscribeFrame(JmsConsumerInfo consumerInfo) throws JMSException {
if (consumerInfo.isDurable()) {
throw new JMSException("Server does not support un-subscribing durable subscriptions over STOMP");
}
StompFrame frame = new StompFrame();
frame.setCommand(UNSUBSCRIBE);
frame.getProperties().put(ID, consumerInfo.getConsumerId().toString());
return frame;
}
@Override
public JmsMessage convertToJmsMessage(StompFrame frame) throws JMSException {
StompJmsMessageFactory messageFactory = connection.getMessageFactory();
String transformation = frame.getProperty(TRANSFORMATION);
if (transformation != null) {
switch (StompJmsMessageFactory.JmsMsgType.valueOf(transformation)) {
case BYTES:
return messageFactory.wrapBytesMessage(frame);
case TEXT:
return messageFactory.wrapTextMessage(frame);
case TEXT_NULL:
return messageFactory.wrapTextMessage(frame);
case MAP:
return messageFactory.wrapMapMessage(frame);
case OBJECT:
return messageFactory.wrapObjectMessage(frame);
case STREAM:
return messageFactory.wrapStreamMessage(frame);
case MESSAGE:
return messageFactory.wrapMessage(frame);
default:
}
}
transformation = frame.getProperty(CONTENT_TYPE);
if (transformation != null ) {
if( transformation.startsWith("text") ||
transformation.endsWith("json") ||
transformation.endsWith("xml")) {
return messageFactory.wrapTextMessage(frame);
}
}
// Standard STOMP contract is that if there is no content-length then the
// message is a text message.
transformation = frame.getProperty(CONTENT_LENGTH);
if (transformation == null) {
return messageFactory.wrapTextMessage(frame);
}
return messageFactory.wrapBytesMessage(frame);
}
@Override
public String getServerVersion() {
return this.version;
}
@Override
public String getServerName() {
return "Generic";
}
/**
* Creates a new JmsMessage that wraps the incoming MESSAGE frame.
*/
public JmsMessage wrapMessage(StompFrame message) {
return new JmsMessage(new StompJmsMessageFacade(message, connection));
}
/**
* Creates a new JmsTextMessage that wraps the incoming MESSAGE frame.
*/
public StompJmsTextMessage wrapTextMessage(StompFrame message) {
return new StompJmsTextMessage(new StompJmsMessageFacade(message, connection));
}
/**
* Creates a new JmsBytesMessage that wraps the incoming MESSAGE frame.
*/
public StompJmsBytesMessage wrapBytesMessage(StompFrame message) {
return new StompJmsBytesMessage(new StompJmsMessageFacade(message, connection));
}
}