/*
* 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.synapse.commons.executors.config;
import org.apache.synapse.commons.executors.*;
import org.apache.synapse.commons.executors.queues.FixedSizeQueue;
import org.apache.synapse.commons.executors.queues.UnboundedQueue;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMAttribute;
import org.apache.axis2.AxisFault;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;
import javax.xml.namespace.QName;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Properties;
public class PriorityExecutorFactory {
private static Log log = LogFactory.getLog(PriorityExecutorFactory.class);
public static final QName NAME_ATT = new QName(ExecutorConstants.NAME);
public static final QName SIZE_ATT = new QName(ExecutorConstants.SIZE);
public static final QName PRIORITY_ATT = new QName(ExecutorConstants.PRIORITY);
public static final QName IS_FIXED_ATT = new QName(ExecutorConstants.IS_FIXED_SIZE);
public static final QName BEFORE_EXECUTE_HANDLER =
new QName(ExecutorConstants.BEFORE_EXECUTE_HANDLER);
public static final QName NEXT_QUEUE_ATT = new QName(ExecutorConstants.NEXT_QUEUE);
public static final QName MAX_ATT = new QName(ExecutorConstants.MAX);
public static final QName CORE_ATT = new QName(ExecutorConstants.CORE);
public static final QName KEEP_ALIVE_ATT = new QName(ExecutorConstants.KEEP_ALIVE);
@SuppressWarnings({"UnusedDeclaration"})
public static PriorityExecutor createExecutor(String namespace, OMElement e,
boolean requireName,
Properties properties) throws AxisFault {
QName queuesQName = createQname(namespace, ExecutorConstants.QUEUES);
QName queueQName = createQname(namespace, ExecutorConstants.QUEUE);
QName threadsQName = createQname(namespace, ExecutorConstants.THREADS);
PriorityExecutor executor = new PriorityExecutor();
OMAttribute nameAtt = e.getAttribute(NAME_ATT);
if (nameAtt != null && !"".equals(nameAtt.getAttributeValue())) {
executor.setName(nameAtt.getAttributeValue());
} else if (requireName){
handlerException(ExecutorConstants.NAME +
" is required for a " + ExecutorConstants.PRIORITY_EXECUTOR);
}
// set the handler for calling before the message is put in to the queue
OMAttribute handlerAtt = e.getAttribute(BEFORE_EXECUTE_HANDLER);
if (handlerAtt != null) {
BeforeExecuteHandler beh =
createExecuteBeforeHandler(handlerAtt.getAttributeValue());
executor.setBeforeExecuteHandler(beh);
}
// create the queue configuration
OMElement queuesEle = e.getFirstChildWithName(queuesQName);
if (queuesEle != null) {
OMAttribute nextQueueAtt = queuesEle.getAttribute(NEXT_QUEUE_ATT);
NextQueueAlgorithm<Runnable> nqa = null;
if (nextQueueAtt != null) {
nqa = createNextQueueAlgo(nextQueueAtt.getAttributeValue());
}
boolean isFixedSize = true;
OMAttribute fixedSizeAtt = queuesEle.getAttribute(IS_FIXED_ATT);
if (fixedSizeAtt != null) {
isFixedSize = Boolean.parseBoolean(fixedSizeAtt.getAttributeValue());
}
// create the queue configuration
List<InternalQueue<Runnable>> intQueues
= createQueues(queueQName, queuesEle, isFixedSize);
MultiPriorityBlockingQueue<Runnable> queue =
new MultiPriorityBlockingQueue<Runnable>(intQueues, isFixedSize, nqa);
executor.setQueue(queue);
} else {
handlerException("Queues configuration is mandatory");
}
OMElement threadsEle = e.getFirstChildWithName(threadsQName);
if (threadsEle != null) {
OMAttribute maxAttr = threadsEle.getAttribute(MAX_ATT);
if (maxAttr != null) {
executor.setMax(Integer.parseInt(maxAttr.getAttributeValue()));
}
OMAttribute coreAttr = threadsEle.getAttribute(CORE_ATT);
if (coreAttr != null) {
executor.setCore(Integer.parseInt(coreAttr.getAttributeValue()));
}
OMAttribute keepAliveAttr = threadsEle.getAttribute(KEEP_ALIVE_ATT);
if (keepAliveAttr != null) {
executor.setKeepAlive(Integer.parseInt(keepAliveAttr.getAttributeValue()));
}
}
return executor;
}
private static List<InternalQueue<Runnable>> createQueues(
QName qQName, OMElement queuesEle, boolean isFixedSize) throws AxisFault {
List<InternalQueue<Runnable>> internalQueues =
new ArrayList<InternalQueue<Runnable>>();
Iterator it = queuesEle.getChildrenWithName(qQName);
while (it.hasNext()) {
OMElement qElement = (OMElement) it.next();
String size = qElement.getAttributeValue(SIZE_ATT);
String priority = qElement.getAttributeValue(PRIORITY_ATT);
int s = 0;
int p = 0;
if (priority != null) {
p = Integer.parseInt(priority);
} else {
handlerException("Priority must be specified");
}
if (size != null) {
s = Integer.parseInt(size);
isFixedSize = true;
} else if (isFixedSize) {
handlerException("Queues should have a " + ExecutorConstants.SIZE);
}
InternalQueue<Runnable> queue;
if (isFixedSize) {
queue = new FixedSizeQueue<Runnable>(p, s);
} else {
queue = new UnboundedQueue<Runnable>(p);
}
internalQueues.add(queue);
}
return internalQueues;
}
private static BeforeExecuteHandler createExecuteBeforeHandler(
String className) throws AxisFault {
try {
Class c = Class.forName(className);
Object o = c.newInstance();
if (o instanceof BeforeExecuteHandler) {
return (BeforeExecuteHandler) o;
} else {
handlerException("Before execute handler class, " +
className +
" is not type of BeforeExecuteHandler");
}
} catch (ClassNotFoundException e1) {
handlerException("Before execute handler class, " +
className +
" is not found");
} catch (IllegalAccessException e1) {
handlerException("Before execute handler class, " +
className +
" cannot be accessed");
} catch (InstantiationException e1) {
handlerException("Before execute handler class, " +
className +
" cannot be instantiated");
}
return null;
}
private static NextQueueAlgorithm<Runnable> createNextQueueAlgo(
String className) throws AxisFault {
try {
Class c = Class.forName(className);
Object o = c.newInstance();
if (o instanceof NextQueueAlgorithm) {
return (NextQueueAlgorithm<Runnable>) o;
} else {
handlerException("NextQueue algorithm class, " +
className +
" is not type of BeforeExecuteHandler");
}
} catch (ClassNotFoundException e1) {
handlerException("NextQueue algorithm class, " +
className + " is not found");
} catch (IllegalAccessException e1) {
handlerException("NextQueue algorithm class, " +
className + " cannot be accessed");
} catch (InstantiationException e1) {
handlerException("NextQueue algorithm class, " +
className + " cannot be instantiated");
}
return null;
}
private static QName createQname(String namespace, String name) {
if (namespace == null) {
return new QName(name);
}
return new QName(namespace, name);
}
private static void handlerException(String message) throws AxisFault {
log.error(message);
throw new AxisFault(message);
}
}