/*
* JBoss, Home of Professional Open Source
* Copyright 2009 Red Hat Inc. and/or its affiliates and other
* contributors as indicated by the @author tags. All rights reserved.
* See the copyright.txt in the distribution for a full listing of
* individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.infinispan.config;
import org.infinispan.interceptors.base.CommandInterceptor;
import org.infinispan.util.TypedProperties;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import java.util.Locale;
import java.util.Properties;
/**
* Holds information about the custom interceptors defined in the configuration file.
*
*
* @author Mircea.Markus@jboss.com
* @author Vladimir Blagojevic
* @since 4.0
*/
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(name="interceptor")
@ConfigurationDoc(name="interceptor")
public class CustomInterceptorConfig extends AbstractNamedCacheConfigurationBean {
/** The serialVersionUID */
private static final long serialVersionUID = 6206233611032238190L;
@XmlTransient
protected CommandInterceptor interceptor;
@ConfigurationDocRef(name="class", bean=CustomInterceptorConfig.class,targetElement="setIndex")
protected Integer index = -1;
@ConfigurationDocRef(name="class", bean=CustomInterceptorConfig.class,targetElement="setAfterInterceptor")
protected String after;
@ConfigurationDocRef(name="class", bean=CustomInterceptorConfig.class,targetElement="setBeforeInterceptor")
protected String before;
@ConfigurationDocRef(name="class", bean=CustomInterceptorConfig.class,targetElement="setPosition")
protected Position position = Position.OTHER_THAN_FIRST_OR_LAST;
@ConfigurationDocRef(name="class", bean=CustomInterceptorConfig.class,targetElement="setClassName")
protected String className;
@XmlElement
private TypedProperties properties = new TypedProperties();
public CustomInterceptorConfig() {
super();
overriddenConfigurationElements.add("isFirst");
}
/**
* Builds a custom interceptor configuration.
*
* @param interceptor interceptor instance, already initialized with all attributes specified in the configuration
* @param first true if you wan this to be the first interceptor in the chain
* @param last true if you wan this to be the last interceptor in the chain
* @param index an absolute position within the interceptor chain
* @param after if you want this interceptor immediately after the specified class in the chain
* @param before immediately before the specified class in the chain
*/
public CustomInterceptorConfig(CommandInterceptor interceptor, boolean first, boolean last, int index,
String after, String before) {
this.interceptor = interceptor;
this.index = index;
this.after = after;
this.before = before;
if (interceptor != null) overriddenConfigurationElements.add("interceptor");
if (first && last)
throw new IllegalArgumentException("Interceptor " + interceptor
+ " can not be both first and last!");
if (first) {
position = Position.FIRST;
}
if (last) {
position = Position.LAST;
}
// No way to tell here, unfortunately...
overriddenConfigurationElements.add("isFirst");
overriddenConfigurationElements.add("isLast");
if (index > -1) overriddenConfigurationElements.add("index");
if (after != null && after.length() > 0) overriddenConfigurationElements.add("after");
if (before != null && before.length() > 0) overriddenConfigurationElements.add("before");
}
/**
* Constructs an interceptor config based on the supplied interceptor instance.
*
* @param interceptor
*/
public CustomInterceptorConfig(CommandInterceptor interceptor) {
this();
this.interceptor = interceptor;
overriddenConfigurationElements.add("interceptor");
}
public Properties getProperties() {
return properties;
}
@XmlTransient
public void setProperties(Properties properties) {
this.properties = toTypedProperties(properties);
testImmutability("properties");
}
public Position getPosition() {
return position;
}
public String getPositionAsString() {
return position.toString();
}
/**
* A position at which to place this interceptor in the chain. FIRST is the first interceptor
* encountered when an invocation is made on the cache, LAST is the last interceptor before the
* call is passed on to the data structure. Note that this attribute is mutually exclusive with
* 'before', 'after' and 'index'.
*
* @param position
*/
@XmlTransient
public void setPosition(Position position) {
this.position = position;
testImmutability("position");
}
public String getClassName() {
return className;
}
/**
* Fully qualified interceptor class name which must extend org.infinispan.interceptors.base.CommandInterceptor.
* @param className
*/
@XmlAttribute(name="class")
public void setClassName(String className) {
this.className = className;
testImmutability("className");
}
/**
* Shall this interceptor be the first one in the chain?
*/
@XmlTransient
public void setFirst(boolean first) {
testImmutability("first");
setPosition(Position.FIRST);
}
/**
* Shall this interceptor be the last one in the chain?
*/
@XmlTransient
public void setLast(boolean last) {
testImmutability("last");
setPosition(Position.LAST);
}
/**
* A position at which to place this interceptor in the chain. FIRST is the first interceptor
* encountered when an invocation is made on the cache, LAST is the last interceptor before the
* call is passed on to the data structure. Note that this attribute is mutually exclusive with
* 'before', 'after' and 'index'.
*
* @param pos
*/
@XmlAttribute(name="position")
public void setPositionAsString(String pos) {
setPosition(Position.valueOf(uc(pos)));
}
/**
* A position at which to place this interceptor in the chain, with 0 being the first position.
* Note that this attribute is mutually exclusive with 'position', 'before' and 'after'."
*
* @param index
*/
@XmlAttribute(name="index")
public void setIndex(Integer index) {
testImmutability("index");
this.index = index;
}
/**
* Places the new interceptor directly after the instance of the named interceptor which is
* specified via its fully qualified class name. Note that this attribute is mutually exclusive
* with 'position', 'before' and 'index'.
*
* @param afterClass
*/
@XmlAttribute(name="after")
public void setAfterInterceptor(String afterClass) {
testImmutability("after");
this.after = afterClass;
}
/**
* Places the new interceptor directly after the instance of the named interceptor which is
* specified via its fully qualified class name. Note that this attribute is mutually exclusive
* with 'position', 'before' and 'index'.
*
* @param interceptorClass
*/
@XmlTransient
public void setAfterInterceptor(Class<? extends CommandInterceptor> interceptorClass) {
setAfterInterceptor(interceptorClass.getName());
}
/**
* Places the new interceptor directly before the instance of the named interceptor which is
* specified via its fully qualified class name.. Note that this attribute is mutually exclusive
* with 'position', 'after' and 'index'."
*
* @param beforeClass
*/
@XmlAttribute(name="before")
public void setBeforeInterceptor(String beforeClass) {
testImmutability("before");
this.before = beforeClass;
}
/**
* Places the new interceptor directly before the instance of the named interceptor which is
* specified via its fully qualified class name.. Note that this attribute is mutually exclusive
* with 'position', 'after' and 'index'."
*
* @param interceptorClass
*/
@XmlTransient
public void setBeforeInterceptor(Class<? extends CommandInterceptor> interceptorClass) {
setBeforeInterceptor(interceptorClass.getName());
}
/**
* Returns a the interceptor that we want to add to the chain.
*/
public CommandInterceptor getInterceptor() {
return interceptor;
}
/**
* Returns a the interceptor that we want to add to the chain.
*/
@XmlTransient
public void setInterceptor(CommandInterceptor interceptor) {
testImmutability("interceptor");
this.interceptor = interceptor;
}
/**
* @see #setFirst(boolean)
*/
public boolean isFirst() {
return getPosition() == Position.FIRST;
}
/**
* @see #setLast(boolean)
*/
public boolean isLast() {
return getPosition() == Position.LAST;
}
/**
* @see #getIndex()
*/
public Integer getIndex() {
return index;
}
/**
* @see #getAfter()
*/
public String getAfter() {
return after;
}
/**
* @see #getAfter()
*/
public String getAfterInterceptor() {
//DO NOT remove this method as it is needed for proper marshalling
return getAfter();
}
/**
* @see #getBefore()
*/
public String getBefore() {
return before;
}
public String getBeforeInterceptor() {
//DO NOT remove this method as it is needed for proper marshalling
return getBefore();
}
public String toString() {
return "CustomInterceptorConfig{" +
"interceptor='" + interceptor + '\'' +
", isFirst=" + isFirst() +
", isLast=" + isLast() +
", index=" + index +
", after='" + after + '\'' +
", before='" + before + '\'' +
", position='" + position + '\'' +
", class='" + className + '\'' +
'}';
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CustomInterceptorConfig)) return false;
CustomInterceptorConfig that = (CustomInterceptorConfig) o;
if (index != null && !index.equals(that.index)) return false;
if (after != null ? !after.equals(that.after) : that.after != null) return false;
if (before != null ? !before.equals(that.before) : that.before != null) return false;
if (position != null ? !position.equals(that.position) : that.position != null) return false;
if (interceptor != null ? !interceptor.equals(that.interceptor) : that.interceptor != null)
return false;
return true;
}
public int hashCode() {
int result;
result = (interceptor != null ? interceptor.hashCode() : 0);
result = 31 * result + index;
result = 31 * result + (after != null ? after.hashCode() : 0);
result = 31 * result + (before != null ? before.hashCode() : 0);
result = 31 * result + (position != null ? position.hashCode() : 0);
return result;
}
@Override
public CustomInterceptorConfig clone() throws CloneNotSupportedException {
CustomInterceptorConfig dolly = (CustomInterceptorConfig) super.clone();
if (properties != null) dolly.properties = (TypedProperties) properties.clone();
return dolly;
}
@Override
protected String uc(String s) {
return s == null ? null : s.toUpperCase(Locale.ENGLISH);
}
enum Position {
FIRST,LAST, OTHER_THAN_FIRST_OR_LAST
}
public void accept(ConfigurationBeanVisitor v) {
v.visitCustomInterceptorConfig(this);
}
}