All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alachisoft.ncache.client.internal.caching.ClientCache Maven / Gradle / Ivy

package com.alachisoft.ncache.client.internal.caching;

import Alachisoft.NCache.Common.BitSet;
import Alachisoft.NCache.Common.EncryptionUtil;
import Alachisoft.NCache.Common.Enum.SerializationFormat;
import Alachisoft.NCache.Common.Enum.UserObjectType;
import Alachisoft.NCache.Common.ErrorHandling.ErrorCodes;
import Alachisoft.NCache.Common.Locking.LockAccessType;
import com.alachisoft.ncache.client.ClientInfo;
import com.alachisoft.ncache.client.*;
import com.alachisoft.ncache.client.datastructures.DataStructureManager;
import com.alachisoft.ncache.client.internal.util.ConversionUtil;
import com.alachisoft.ncache.client.services.MessagingService;
import com.alachisoft.ncache.client.services.NotificationService;
import com.alachisoft.ncache.client.services.SearchService;
import com.alachisoft.ncache.common.caching.EntryType;
import com.alachisoft.ncache.runtime.CacheItemPriority;
import com.alachisoft.ncache.runtime.caching.*;
import com.alachisoft.ncache.runtime.caching.datasource.ResyncOptions;
import com.alachisoft.ncache.runtime.caching.expiration.Expiration;
import com.alachisoft.ncache.runtime.caching.expiration.ExpirationType;
import com.alachisoft.ncache.runtime.dependencies.CacheDependency;
import com.alachisoft.ncache.runtime.errorhandling.ErrorMessages;
import com.alachisoft.ncache.runtime.events.EventDataFilter;
import com.alachisoft.ncache.runtime.events.EventType;
import com.alachisoft.ncache.runtime.events.ListenerType;
import com.alachisoft.ncache.runtime.exceptions.SecurityException;
import com.alachisoft.ncache.runtime.exceptions.*;
import com.alachisoft.ncache.runtime.util.NCDateTime;
import com.alachisoft.ncache.runtime.util.TimeSpan;
import com.alachisoft.ncache.security.encryption.EncryptionMgr;
import com.alachisoft.ncache.serialization.standard.CompactBinaryFormatter;
import com.google.common.collect.Iterables;
import com.alachisoft.ncache.runtime.util.TimeSpan;
import tangible.RefObject;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.FutureTask;

public class ClientCache extends CacheImpl {
    private CacheImpl _nearCache;
    private CacheImpl _farCache;
    private boolean _isPessimistic = false;
    private SearchService _searchService;
    private boolean _sldDefaultEnabled;
    private boolean _sldLongerEnabled;
    private boolean _absDefaultEnabled;
    private boolean _absLongerEnabled;
    private long _sldDefault;
    private long _sldLonger;
    private long _absDefault;
    private long _absLonger;
    private String _userId;
    private byte[] _password;

    public ClientCache(CacheImpl l2, CacheImpl nearCache, String userid, String password, boolean isPessimistic) throws Exception {
        if (nearCache == null)
            throw new OperationFailedException(ErrorCodes.CacheInit.L1_CACHE_NOT_INIT, ErrorMessages.getErrorMessage(ErrorCodes.CacheInit.L1_CACHE_NOT_INIT));
        if (l2 == null)
            throw new OperationFailedException(ErrorCodes.CacheInit.L2_CACHE_NOT_INIT, ErrorMessages.getErrorMessage(ErrorCodes.CacheInit.L2_CACHE_NOT_INIT));

        _nearCache = nearCache;
        _farCache = l2;

        InitializeEncryption();
        getClientExpiration();

        _nearCache.setQueryTypeInfoMap(_farCache.getQueryTypeMap());

        _isPessimistic = isPessimistic;

        _nearCache.setSerializationContext(_farCache.getSerializationContext());
        _nearCache.setSerializationFormat(_farCache.getSerializationFormat());

        _searchService = new ClientCacheSearchService(_farCache, _nearCache);

        if (userid != null)
            _userId = userid;

        if (password != null)
            _password = EncryptionUtil.Encrypt(password);
    }

    final void getClientExpiration() {
        HashMap expirationInfo = ((RemoteCache) _farCache.getCacheImpl()).GetExpirationInfo();
        if (expirationInfo != null) {
            _absDefault = (long) (expirationInfo.get("absDefault"));
            _absLonger = (long) (expirationInfo.get("absLonger"));
            _sldDefault = (long) (expirationInfo.get("sldDefault"));
            _sldLonger = (long) (expirationInfo.get("sldLonger"));
            _absDefaultEnabled = (boolean) (expirationInfo.get("absDefaultEnabled"));
            _absLongerEnabled = (boolean) (expirationInfo.get("absLongerEnabled"));
            _sldDefaultEnabled = (boolean) (expirationInfo.get("sldDefaultEnabled"));
            _sldLongerEnabled = (boolean) (expirationInfo.get("sldLongerEnabled"));
        }
    }

    final java.util.Map insertBulkOperation(java.util.Map items, WriteMode writeMode, String provider, DataSourceModifiedListener dataSourceModifiedListener, EventTypeInternal eventType, String clientId, short updateCallbackId, short removeCallbackId, short dataSourceUpdatedCallbackId) throws CacheException {

        if (items == null)
            throw new IllegalArgumentException("items");
        if (items.isEmpty())
            throw new IllegalArgumentException("Adding empty dictionary into cache.");

        java.util.HashMap itemsToUpdate = new java.util.HashMap();
        long[] sizes = new long[items.size()];
        long[] updateSize = null;
        Map insertResult = null;
        try {
            _nearCache.removeBulk(items.keySet(), null, Object.class); // 28/05:Ref:mail 27/05 item#9


            RefObject tempRef_sizes = new tangible.RefObject(sizes);
            tangible.RefObject tempRef_itemVersions = new tangible.RefObject(null);
            insertResult = _farCache.InsertBulkInternal(items, writeMode, dataSourceModifiedListener, eventType, provider, tempRef_sizes, true, null, (short) -1, (short) -1, (short) -1, EventDataFilter.None, EventDataFilter.None, false, tempRef_itemVersions);

            if (insertResult == null || insertResult.isEmpty()) {
                for (Map.Entry item : items.entrySet()) {
                    if (!itemsToUpdate.containsKey(item.getKey()))
                        itemsToUpdate.put(item.getKey(), getCompatibleItem(item.getValue()));
                }
                updateSize = sizes;
            } else if (insertResult.size() < items.size()) {
                updateSize = new long[items.size() - insertResult.size()];

                for (Map.Entry item : items.entrySet()) {
                    if (!insertResult.containsKey(item.getKey())) {
                        CacheItem l2item = item.getValue();
                        CacheItem newItem = new CacheItem(l2item.getValue(Object.class));
                        Expiration tempVar2 = new Expiration(ExpirationType.Absolute);
                        tempVar2.setExpireAfter(TimeSpan.subtract(new Date(), getServerExpiration(ConversionUtil.getAbsoluteExpiration(newItem.getExpiration()), ConversionUtil.getSlidingExpiration(newItem.getExpiration()))));
                        newItem.setExpiration(tempVar2);
                        newItem.setResyncOptions(l2item.getResyncOptions());
                        newItem.setCacheItemPriority(l2item.getCacheItemPriority());
                        newItem.setSyncDependency(new CacheSyncDependency(_farCache._cacheId, item.getKey(), _userId, _password));

                        if (!itemsToUpdate.containsKey(item.getKey()))
                            itemsToUpdate.put(item.getKey(), newItem);
                    }
                }
            }

            if (itemsToUpdate.size() > 0) {
                RefObject tempRef_updateSize = new tangible.RefObject(updateSize);
                tempRef_itemVersions = new tangible.RefObject(null);
                _nearCache.InsertBulkInternal(itemsToUpdate, WriteMode.None, null, EventTypeInternal.None, null, tempRef_updateSize, true, null, (short) -1, (short) -1, (short) -1, EventDataFilter.None, EventDataFilter.None, false, tempRef_itemVersions);
            }

        } catch (CacheException e) {
            if (_nearCache.getExceptionEnabled())
                throw e;
        }

        return insertResult;
    }

    @Override
    public Map addBulk(Map items, WriteThruOptions writeThruOptions) throws StreamNotFoundException, StreamException, ConfigurationException, CommandException, AggregateException, GeneralFailureException, OperationNotSupportedException, OperationFailedException, StreamAlreadyLockedException, LicensingException, SecurityException {
        long[] sizes = new long[items.size()];
        java.util.Map failedkeys;
        try {
            String providerName = null;
            java.util.Map itemVersions = null;
            WriteMode mode = WriteMode.None;
            DataSourceModifiedListener dataSourceModifiedCallback = null;
            EnumSet eventTypes = EnumSet.of(EventTypeInternal.None);

            tangible.RefObject tempRef_mode = new tangible.RefObject(mode);
            tangible.RefObject tempRef_providerName = new tangible.RefObject(providerName);
            tangible.RefObject tempRef_dataSourceModifiedCallback = new tangible.RefObject(dataSourceModifiedCallback);
            RefObject> tempRef_eventTypes = new RefObject(eventTypes);
            ConversionUtil.GetWriteOptions(writeThruOptions, tempRef_mode, tempRef_providerName, tempRef_dataSourceModifiedCallback,tempRef_eventTypes);
            mode = tempRef_mode.argvalue;
            providerName = tempRef_providerName.argvalue;
            dataSourceModifiedCallback = tempRef_dataSourceModifiedCallback.argvalue;
            eventTypes = tempRef_eventTypes.argvalue;
            //Consider only first element from enumset. For now multiple events are not supported.
            EventTypeInternal eventTypeInternal = (EventTypeInternal) eventTypes.toArray()[0];

            failedkeys = _farCache.AddBulkInternal(items, mode, dataSourceModifiedCallback, eventTypeInternal, providerName, true, null, (short) -1, (short) -1, (short) -1, EventDataFilter.None, EventDataFilter.None, false);
        } finally {
            TargetMethodAttribute.setMethodOverload(0);
        }

        if (failedkeys == null)
            return null;
        if (failedkeys.size() == items.size())
            return failedkeys;

        java.util.HashMap successfullItems = new java.util.HashMap();

        for (Map.Entry item : items.entrySet()) {
            if (!failedkeys.containsKey(item.getKey())) {
                CacheItem l2item = item.getValue();
                CacheItem newItem = new CacheItem(l2item.getValue(Object.class));
                newItem.setCacheItemPriority(l2item.getCacheItemPriority());

                Expiration tempVar2 = new Expiration(ExpirationType.Absolute);
                tempVar2.setExpireAfter(TimeSpan.subtract(new java.util.Date(), getServerExpiration(ConversionUtil.getAbsoluteExpiration(l2item.getExpiration()), ConversionUtil.getSlidingExpiration(l2item.getExpiration()))));
                newItem.setExpiration(tempVar2);
                newItem.setResyncOptions(l2item.getResyncOptions());
                newItem.setSyncDependency(new CacheSyncDependency(_farCache._cacheId, item.getKey(), _userId, _password));
                ;

                if (!successfullItems.containsKey(item.getKey()))
                    successfullItems.put(item.getKey(), item.getValue());
            }
        }

        try {
            java.util.Map itemVersions = null;

            _nearCache.AddBulkInternal(successfullItems, WriteMode.None, null, EventTypeInternal.None, null, true, null, (short) -1, (short) -1, (short) -1, EventDataFilter.None, EventDataFilter.None, false);
        } catch (java.lang.Exception e) {
            if (_nearCache.getExceptionEnabled())
                throw e;
        }
        return failedkeys;
    }

    @Override
    protected CacheItemVersion addOperation(String key, Object value, CacheDependency dependency, CacheSyncDependency syncDependency, Date absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority,
                                            WriteMode writeMode, DataSourceModifiedListener onDataSourceModified,EventTypeInternal eventTypeInternal,
                                            boolean isResyncExpiredItems, String group, Tag[] tags, String providerName, String resyncProviderName, NamedTagsDictionary namedTags,
                                            CacheDataModificationListener cacheItemUpdatedListener, CacheDataModificationListener cacheItemRemovedListener, EventDataFilter itemUpdateDataFilter, EventDataFilter itemRemovedDataFilter, tangible.RefObject size, boolean allowQueryTags, String clientId,
                                            short updateCallbackId, short removeCallbackId, short dsItemAddedCallbackId) throws CacheException {
        CacheItemVersion result = _farCache.addOperation(key, value, dependency, syncDependency, absoluteExpiration, slidingExpiration, priority, writeMode, onDataSourceModified,eventTypeInternal, isResyncExpiredItems, group, tags, providerName, resyncProviderName, namedTags, cacheItemUpdatedListener, cacheItemRemovedListener, itemUpdateDataFilter, itemRemovedDataFilter, size, allowQueryTags, clientId, updateCallbackId, removeCallbackId, dsItemAddedCallbackId);

        if (result == null)
            return null;

        try {
            _nearCache.insertOperation(key, value, dependency, new CacheSyncDependency(_farCache._cacheId, key, _userId, _password),
                    getServerExpiration(absoluteExpiration, NoSlidingExpiration), slidingExpiration,
                    priority, WriteMode.None, null, null, isResyncExpiredItems,
                    group, null, new CacheItemVersion(result.getVersion()), LockAccessType.DEFAULT, tags,
                    providerName, resyncProviderName, namedTags, null, null, EventDataFilter.None,
                    EventDataFilter.None, true, null, (short) -1, (short) -1, (short) -1);
        } catch (CacheException e) {
            if (_nearCache.getExceptionEnabled())
                throw e;
        }
        return result;
    }

    @Override
    public void clear() throws CacheException {
        _farCache.clear();
    }

    @Override
    public FutureTask clearAsync() {
        _farCache.clearAsync();
        return _nearCache.clearAsync();
    }

    @Override
    public void clearClientCache() throws CacheException {
        _nearCache.clear();
        try {
            Thread.sleep(1000);
        }
        catch (InterruptedException ex)
        {
            throw new CacheException(ex);
        }
        _nearCache.clear();
    }

    @Override
    public FutureTask clearClientCacheAsync() {
        return _nearCache.clearAsync();
    }

    @Override
    public boolean contains(String key) throws CacheException {
        return _farCache.contains(key);
    }

    @Override
    public java.util.Map containsBulk(Iterable keys) throws CacheException {
        return _farCache.containsBulk(keys);
    }

    public final long getAbsDefault() {
        return _absDefault;
    }

    public final void setAbsDefault(long value) {
        _absDefault = value;
    }

    public final boolean getAbsDefaultEnabled() {
        return _absDefaultEnabled;
    }

    public final void setAbsDefaultEnabled(boolean value) {
        _absDefaultEnabled = value;
    }

    public final long getAbsLonger() {
        return _absLonger;
    }

    public final void setAbsLonger(long value) {
        _absLonger = value;
    }

    public final boolean getAbsLongerEnabled() {
        return _absLongerEnabled;
    }

    public final void setAbsLongerEnabled(boolean value) {
        _absLongerEnabled = value;
    }

    public CacheImpl getCacheInstanceInternal() {
        return _farCache;
    }

    @Override
    public ClientInfo getClientInfo() throws CacheException {
        return _farCache.getClientInfo();
    }

    final CacheItem getCompatibleItem(CacheItem l2CacheItem) throws OperationFailedException {
        if (l2CacheItem == null)
            return null;

        CacheItem l1CacheItem = new CacheItem(l2CacheItem.getValue(Object.class));

        l1CacheItem.setCacheItemPriority(l2CacheItem.getCacheItemPriority());
        Expiration tempVar = new Expiration(ExpirationType.Absolute);
        Date expiration=getServerExpiration(ConversionUtil.getAbsoluteExpiration(l2CacheItem.getExpiration()), ConversionUtil.getSlidingExpiration(l2CacheItem.getExpiration()));
        if(expiration!=NoAbsoluteExpiration) {
            tempVar.setExpireAfter(TimeSpan.subtract(new Date(), expiration));
            l1CacheItem.setExpiration(tempVar);
        }
        l1CacheItem.setCacheItemVersion(l2CacheItem.getCacheItemVersion());
        l1CacheItem.setGroup(l2CacheItem.getGroup());
        l1CacheItem.setTags(l2CacheItem.getTags());
        l1CacheItem.setNamedTags(l2CacheItem.getNamedTags());
        l1CacheItem.setResyncOptions(l2CacheItem.getResyncOptions() == null ? new ResyncOptions(false, null) : l2CacheItem.getResyncOptions());

        return l1CacheItem;
    }

    @Override
    public java.util.List getConnectedClientList() throws CacheException {
        return _farCache.getConnectedClientList();
    }

    @Override
    public long getCount() throws CacheException {
        return _farCache.getCount();
    }

    @Override
    public DataStructureManager getDataStructuresManager()  {
        return _farCache.getDataStructuresManager();
    }

    @Override
    public boolean getExceptionEnabled() {
        return _farCache.getExceptionEnabled();
    }

    @Override
    public MessagingService getMessagingService() throws CacheException {
        return _farCache.getMessagingService();
    }

    @Override
    public NotificationService getNotificationService() throws CacheException {
        return _farCache.getNotificationService();
    }

    public final byte[] getPassword() {
        return _password;
    }

    public final void setPassword(byte[] value) {
        _password = value;
    }

    @Override
    public SearchService getSearchService() {
        return _searchService;
    }

    @Override
    public void setSearchService(SearchService value) {
        _searchService = value;
    }

    @Override
    public SerializationFormat getSerializationFormat() {
        return _farCache.getSerializationFormat();
    }

    @Override
    public void setSerializationFormat(SerializationFormat value) {
        super.setSerializationFormat(value);
    }

    private Date getServerExpiration(Expiration expiration) {
        return getServerExpiration(ConversionUtil.getAbsoluteExpiration(expiration), ConversionUtil.getSlidingExpiration(expiration));
    }

    private Date getServerExpiration(Date absoluteExpiration, TimeSpan slidingExpiration) {
        Calendar c = Calendar.getInstance();

        if (absoluteExpiration == defaultAbsolute && _absDefaultEnabled) {
            NCDateTime dateTime= new NCDateTime(new Date());
            dateTime.addTicks(TimeSpan.TimeToTicks(0,0,(int)getAbsDefault()));
            return dateTime.getDate();
        }
        if (absoluteExpiration == defaultAbsoluteLonger && _absLongerEnabled) {
            NCDateTime dateTime= new NCDateTime(new Date());
            dateTime.addTicks(TimeSpan.TimeToTicks(0,0,(int)getAbsDefault()));
            return dateTime.getDate();
        }
        if (slidingExpiration == DefaultSliding && _sldDefaultEnabled) {
            NCDateTime dateTime= new NCDateTime(new Date());
            dateTime.addTicks(TimeSpan.TimeToTicks(0,0,(int)getSldDefault()));
            return dateTime.getDate();
        }
        if (slidingExpiration == DefaultSlidingLonger && _sldLongerEnabled) {
            NCDateTime dateTime= new NCDateTime(new Date());
            dateTime.addTicks(TimeSpan.TimeToTicks(0,0,(int)getSldLonger()));
            return dateTime.getDate();
        }
        //incase if default expirations are not available then set NoAbsoluteExpiration for Client cache
        if(absoluteExpiration == defaultAbsolute||absoluteExpiration == defaultAbsoluteLonger ||slidingExpiration == DefaultSliding||slidingExpiration == DefaultSlidingLonger)
        {
            return NoAbsoluteExpiration;
        }
        if (!(absoluteExpiration == NoAbsoluteExpiration))
            return absoluteExpiration;
        if (slidingExpiration == NoSlidingExpiration)
            return NoAbsoluteExpiration;

        NCDateTime date=new NCDateTime(new Date());
        date.addTicks(slidingExpiration._ticks);

        return date.getDate();//new NCDateTime(new TimeSpan(new NCDateTime(new Date()).getTicks()).Add(slidingExpiration).getTotalTicks()).getDate();
    }

    public final long getSldDefault() {
        return _sldDefault;
    }

    public final void setSldDefault(long value) {
        _sldDefault = value;
    }

    public final boolean getSldDefaultEnabled() {
        return _sldDefaultEnabled;
    }

    public final void setSldDefaultEnabled(boolean value) {
        _sldDefaultEnabled = value;
    }

    public final long getSldLonger() {
        return _sldLonger;
    }

    public final void setSldLonger(long value) {
        _sldLonger = value;
    }

    public final boolean getSldLongerEnabled() {
        return _sldLongerEnabled;
    }

    public final void setSldLongerEnabled(boolean value) {
        _sldLongerEnabled = value;
    }

    public final String getUserId() {
        return _userId;
    }

    public final void setUserId(String value) {
        _userId = value;
    }

    @Override
    public Map insertBulk(Map items, WriteThruOptions writeThruOptions) throws CacheException {

        String providerName = null;
        WriteMode mode = WriteMode.None;
        DataSourceModifiedListener dataSourceModifiedListener = null;
        EnumSet eventTypes = EnumSet.of(EventTypeInternal.None);

        tangible.RefObject tempRef_mode = new tangible.RefObject(mode);
        tangible.RefObject tempRef_providerName = new tangible.RefObject(providerName);
        tangible.RefObject tempRef_dataSourceModifiedCallback = new tangible.RefObject(dataSourceModifiedListener);
        RefObject> tempRef_eventTypes = new RefObject(eventTypes);
        ConversionUtil.GetWriteOptions(writeThruOptions, tempRef_mode, tempRef_providerName, tempRef_dataSourceModifiedCallback,tempRef_eventTypes);
        mode = tempRef_mode.argvalue;
        providerName = tempRef_providerName.argvalue;
        dataSourceModifiedListener = tempRef_dataSourceModifiedCallback.argvalue;
        eventTypes = tempRef_eventTypes.argvalue;
        //Consider only first element from enumset. For now multiple events are not supported.
        EventTypeInternal eventTypeInternal = (EventTypeInternal) eventTypes.toArray()[0];
        return insertBulkOperation(items, mode, providerName, dataSourceModifiedListener, eventTypeInternal, null, (short) -1, (short) -1, (short) -1);
    }

    @Override
    protected CacheItemVersion insertOperation(String key, Object value, CacheDependency dependency, CacheSyncDependency syncDependency, Date absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, WriteMode writeMode, DataSourceModifiedListener onDataSourceModified, EventTypeInternal eventType, boolean isResyncExpiredItems, String group, LockHandle lockHandle, CacheItemVersion version, LockAccessType accessType, Tag[] tags, String providerName, String resyncProviderName, NamedTagsDictionary namedTags, CacheDataModificationListener cacheItemUpdated, CacheDataModificationListener cacheItemRemoved, EventDataFilter itemUpdateDataFilter, EventDataFilter itemRemovedDataFilter, boolean allowQueryTags, String clientId, short updateCallbackId, short removeCallbackId, short dsItemAddedCallbackId) throws CacheException, IllegalArgumentException {
        CacheItemVersion newVersion = null;
        boolean contained = false;

        int prevMethodOcverload = TargetMethodAttribute.getMethodOverload();
        Object lockId = (lockHandle == null) ? null : lockHandle.getLockId();

        try {
            contained = _nearCache.contains(key);
        } catch (CacheException e) {
            if (_nearCache.getExceptionEnabled())
                throw e;
        }

        if (!contained) {
            try {
                TargetMethodAttribute.setMethodOverload(prevMethodOcverload);

                newVersion = _farCache.insertOperation(key, value, dependency, syncDependency, getServerExpiration(absoluteExpiration, NoSlidingExpiration), slidingExpiration, priority, writeMode, onDataSourceModified, eventType, isResyncExpiredItems, group, lockHandle, version, accessType, tags, providerName, resyncProviderName, namedTags, cacheItemUpdated, cacheItemRemoved, itemUpdateDataFilter, itemRemovedDataFilter, true, null, (short) -1, (short) -1, (short) -1);
            } finally {
                TargetMethodAttribute.setMethodOverload(0);
            }
            if (newVersion == null)
                return null;
            try {
                _nearCache.insertOperation(key, value, dependency, new CacheSyncDependency(_farCache._cacheId, key, _userId, _password), getServerExpiration(absoluteExpiration, NoSlidingExpiration), slidingExpiration, priority, WriteMode.None, null, EventTypeInternal.None, isResyncExpiredItems, group, null, newVersion, LockAccessType.PRESERVE_VERSION, tags, providerName, resyncProviderName, namedTags, null, null, EventDataFilter.None, EventDataFilter.None, true, null, (short) -1, (short) -1, (short) -1);
            } catch (CacheException e2) {
                if (_nearCache.getExceptionEnabled())
                    throw e2;
            }
        } else {
            try {
                _nearCache.delete(key);

                //Date absoluteExpirationClone=new Date(absoluteExpiration.getTime()); //it gets changed inside this
                // method so we need a separate for far cache, Convertion to UTC
                try {
                    TargetMethodAttribute.setMethodOverload(prevMethodOcverload);

                    newVersion = _farCache.insertOperation(key, value, dependency, syncDependency, getServerExpiration(absoluteExpiration, NoSlidingExpiration), slidingExpiration, priority, writeMode, onDataSourceModified, eventType, isResyncExpiredItems, group, lockHandle, version, accessType, tags, providerName, resyncProviderName, namedTags, cacheItemUpdated, cacheItemRemoved, itemUpdateDataFilter, itemRemovedDataFilter, true, null, (short) -1, (short) -1, (short) -1);
                } finally {
                    TargetMethodAttribute.setMethodOverload(0);
                }

                _nearCache.insertOperation(key, value, dependency, new CacheSyncDependency(_farCache._cacheId, key, _userId, _password), getServerExpiration(absoluteExpiration, NoSlidingExpiration), slidingExpiration, priority, WriteMode.None, null, EventTypeInternal.None, isResyncExpiredItems, group, null, newVersion, LockAccessType.PRESERVE_VERSION, tags, providerName, resyncProviderName, namedTags, null, null, EventDataFilter.None, EventDataFilter.None, true, null, (short) -1, (short) -1, (short) -1);

            } catch (CacheException e3) {
                if (_nearCache.getExceptionEnabled())
                    throw e3;
            }
        }
        return newVersion;
    }

    @Override
    public boolean updateAttributes(String key, CacheItemAttributes attributes) throws CacheException {
        boolean success = false;

        if (key == null)
            throw new IllegalArgumentException();

        if (attributes == null)
            throw new IllegalArgumentException();

        if (_farCache == null)
            throw new OperationFailedException(ErrorCodes.CacheInit.L2_CACHE_NOT_INIT, ErrorMessages.getErrorMessage(ErrorCodes.CacheInit.L2_CACHE_NOT_INIT));

        try
        {
            success = _farCache.updateAttributes(key, attributes);

            if (success)
            {
                success = _nearCache.updateAttributes(key, attributes);
            }
        }
        catch (CacheException e)
        {
            if (getExceptionEnabled())
                throw e;
        }

        return success;
    }

    @Override
    public  T remove(String key, LockHandle lockHandle, CacheItemVersion version, WriteThruOptions writeThruOptions, Class cls) throws CacheException {
        _nearCache.remove(key, cls);
        return _farCache.remove(key, lockHandle, version, writeThruOptions, cls);
    }

    @Override
    public  Map removeBulk(Iterable keys, WriteThruOptions writeThruOptions, Class cls) throws CacheException, IllegalArgumentException, ClassCastException {
        _nearCache.removeBulk(keys, cls);
        return _farCache.removeBulk(keys, writeThruOptions, cls);
    }

    @Override
    public void delete(String key, LockHandle lockHandle, CacheItemVersion version, WriteThruOptions writeThruOptions) throws CacheException {
        _nearCache.delete(key);
        _farCache.delete(key, lockHandle, version, writeThruOptions);
    }

    @Override
    public void deleteBulk(Iterable keys, WriteThruOptions writeThruOptions) throws CacheException {
        _nearCache.deleteBulk(keys);
        _farCache.deleteBulk(keys, writeThruOptions);
    }

    @Override
    public  T get(String key, ReadThruOptions readThruOptions, Class cls) throws CacheException, IllegalArgumentException, ClassCastException {
        T result = null;
        CacheItem cacheItem = null;

        if(readThruOptions == null)
            readThruOptions = new ReadThruOptions(ReadMode.None);

        if (_isPessimistic)
        {
            CacheItemVersion version = new CacheItemVersion();
            T localItem =null;
            if(readThruOptions.getReadMode()!=ReadMode.ReadThruForced)
                localItem=_nearCache.get(key, version, null, cls);
            try
            {
                if (localItem != null)
                {
                    result = _farCache.getIfNewer(key, version, cls);
                    //if l2 does not return the item because item there is not
                    //newer then return the local item. otherwise return null because
                    //item is removed from l2.
                    if (result == null)
                    {
                        if (version == null||version.getVersion()==0)
                            return localItem;
                        else
                            return null;
                    }
                }
                else
                {
                    cacheItem = _farCache.getCacheItem(key, version, readThruOptions);
                    if (cacheItem != null)
                        version = cacheItem.getCacheItemVersion();
                }

                if (cacheItem != null)
                {
                    result = cacheItem.getValue(cls);
                    try
                    {
                        cacheItem = getCompatibleItem(cacheItem);

                        _nearCache.insertOperation(key, result, cacheItem.getDependency(), new CacheSyncDependency(_farCache._cacheId, key, _userId, _password), getServerExpiration(ConversionUtil.getAbsoluteExpiration(cacheItem.getExpiration()), NoSlidingExpiration), ConversionUtil.getSlidingExpiration(cacheItem.getExpiration()), cacheItem.getCacheItemPriority(), WriteMode.None, null, EventTypeInternal.None, cacheItem.getResyncOptions().getResyncOnExpiration(), cacheItem.getGroup(), null, version, LockAccessType.PRESERVE_VERSION, ConversionUtil.toArray(cacheItem.getTags()), null, cacheItem.getResyncOptions().getProviderName(), cacheItem.getNamedTags(), null, null, EventDataFilter.None, EventDataFilter.None, true, null, (short) -1, (short) -1, (short) -1);

                    }
                    catch (CacheException e)
                    {
                        if (_nearCache.getExceptionEnabled())
                            throw e;
                    }
                }
            }
            catch (CacheException e2)
            {
                if (_nearCache.getExceptionEnabled())
                    throw e2;
            }
        }
        else
        {
            try
            {
                if(readThruOptions.getReadMode()!=ReadMode.ReadThruForced)
                    result = _nearCache.get(key, null, cls);
            }
            catch (CacheException e3)
            {
                if (_nearCache.getExceptionEnabled())
                    throw e3;
            }

            if (result != null)
                return result;

            CacheItemVersion version = new CacheItemVersion();

            cacheItem = _farCache.getCacheItem(key, version, readThruOptions);

            if (cacheItem != null)
            {
                result = cacheItem.getValue(cls);
                try
                {
                    if(CacheItemWrapperInternal.GetCacheItemEntryType(cacheItem)!=null && CacheItemWrapperInternal.GetCacheItemEntryType(cacheItem)== EntryType.CacheItem) {
                        cacheItem = getCompatibleItem(cacheItem);
                        _nearCache.insertOperation(key, cacheItem.getValue(cls), cacheItem.getDependency(), new CacheSyncDependency(_farCache._cacheId, key, _userId, _password), getServerExpiration(ConversionUtil.getAbsoluteExpiration(cacheItem.getExpiration()), NoSlidingExpiration), ConversionUtil.getSlidingExpiration(cacheItem.getExpiration()), cacheItem.getCacheItemPriority(), WriteMode.None, null, EventTypeInternal.None, cacheItem.getResyncOptions().getResyncOnExpiration(), cacheItem.getGroup(), null, version, LockAccessType.PRESERVE_VERSION, ConversionUtil.toArray(cacheItem.getTags()), null, cacheItem.getResyncOptions().getProviderName(), cacheItem.getNamedTags(), null, null, EventDataFilter.None, EventDataFilter.None, true, null, (short) -1, (short) -1, (short) -1);
                    }
                }
                catch (CacheException e4)
                {
                    if (_nearCache.getExceptionEnabled())
                        throw e4;
                }
            }
        }
        return result;

    }

    @Override
    public  T get(String key, boolean acquireLock, TimeSpan lockTimeout, LockHandle lockHandle, Class cls) throws CacheException, IllegalArgumentException, ClassCastException {
        T result = null;
        CacheItem cacheItem = null;
        try
        {
            result = _nearCache.get(key, null, cls);
        }
        catch ( CacheException e)
        {
            if (_nearCache.getExceptionEnabled())
                throw e;
        }

        if (result != null)
        {
            if (acquireLock)
            {
                if (!lock(key, lockTimeout, lockHandle))
                    return null;
            }
            else
            {
                if (isLocked(key, lockHandle))
                    return null;
            }
        }
        else
        {
            cacheItem = _farCache.getCacheItem(key, acquireLock, lockTimeout, lockHandle);

            if (cacheItem != null)
            {
                result = cacheItem.getValue(cls);
                BitSet flagmap = CacheItemWrapperInternal.getFlagValue(cacheItem);
                long size = 0;
                _farCache.safeSerialize(result, _farCache._cacheId, flagmap, size, UserObjectType.CacheItem);

                try
                {
                    cacheItem = getCompatibleItem(cacheItem);

                    _nearCache.insertOperation(key, cacheItem.getValue(cls), cacheItem.getDependency(), new CacheSyncDependency(_farCache._cacheId, key, _userId, _password), getServerExpiration(ConversionUtil.getAbsoluteExpiration(cacheItem.getExpiration()), NoSlidingExpiration), ConversionUtil.getSlidingExpiration(cacheItem.getExpiration()), cacheItem.getCacheItemPriority(), WriteMode.None, null, EventTypeInternal.None, cacheItem.getResyncOptions().getResyncOnExpiration(), cacheItem.getGroup(), null, null, LockAccessType.IGNORE_LOCK,  ConversionUtil.toArray(cacheItem.getTags()), null, cacheItem.getResyncOptions().getProviderName(), cacheItem.getNamedTags(), null, null, EventDataFilter.None, EventDataFilter.None, true, null, (short) -1, (short) -1, (short) -1);

                }
                catch (CacheException e2)
                {
                    if (_nearCache.getExceptionEnabled())
                        throw e2;
                }
            }
        }
        return result;
    }

    @Override
    public  T get(String key, CacheItemVersion version, ReadThruOptions readThruOptions, Class cls) throws CacheException, IllegalArgumentException, ClassCastException {
        CacheItem cacheItem = _farCache.getCacheItem(key, version, readThruOptions);
        if (cacheItem != null)
        {

            if (version != null && cacheItem.getCacheItemVersion().getVersion() != version.getVersion()
            && version.getVersion()!=0)
            {
                version.setVersion(cacheItem.getCacheItemVersion().getVersion());
                if(readThruOptions==null || readThruOptions.getReadMode()==ReadMode.None)
                    return null;

            }
            else
                version.setVersion(cacheItem.getCacheItemVersion().getVersion());

            try
            {
                if (!_nearCache.contains(key))
                {
                    Object seralized = null;
                    try {
                        seralized = CompactBinaryFormatter.toByteBuffer(cacheItem.getValue(cls), _farCache._cacheId);
                    } catch (IOException e) {
                        throw new OperationFailedException(e);
                    }
                    long size = seralized instanceof byte[] ? ((byte[])seralized).length : 0;

                    cacheItem = getCompatibleItem(cacheItem);

                    _nearCache.insertOperation(key, cacheItem.getValue(cls), cacheItem.getDependency(), new CacheSyncDependency(_farCache._cacheId, key, _userId, _password), getServerExpiration(ConversionUtil.getAbsoluteExpiration(cacheItem.getExpiration()), NoSlidingExpiration), ConversionUtil.getSlidingExpiration(cacheItem.getExpiration()), cacheItem.getCacheItemPriority(), WriteMode.None, null, EventTypeInternal.None, cacheItem.getResyncOptions().getResyncOnExpiration(), cacheItem.getGroup(), null, version, LockAccessType.PRESERVE_VERSION, ConversionUtil.toArray(cacheItem.getTags()), null, cacheItem.getResyncOptions().getProviderName(), cacheItem.getNamedTags(), null, null, EventDataFilter.None, EventDataFilter.None, true, null, (short) -1, (short) -1, (short) -1);
                }
            }
            catch (CacheException e)
            {
                if (_nearCache.getExceptionEnabled())
                    throw e;
            }
        }
        return cacheItem != null ? cacheItem.getValue(cls) : null;
    }

    @Override
    public  T getInternal(String key, CacheItemVersion version, LockAccessType accessType, TimeSpan lockTimeout, LockHandle lockHandle, ReadThruOptions readOptions, Class cls) throws CacheException {
        T result = null;
        CacheItem cacheItem = null;

        if (_isPessimistic)
        {
            try
            {
                CacheItem cItem = _nearCache.getCacheItem(key, readOptions);
                T localItem = null;

                if (cItem != null)
                {
                    localItem = cItem.getValue(cls);
                    version = cItem.getCacheItemVersion();
                }

                if (localItem != null)
                {
                    result = _farCache.getIfNewer(key, version, cls);
                    //if l2 does not return the item because item there is not
                    //newer then return the local item. otherwise return null because
                    //item is removed from l2.
                    if (result == null)
                    {
                        if (version == null)
                            return localItem;
                        else
                            return null;
                    }
                }
                else
                    cacheItem = _farCache.getCacheItemInternal(key, version, accessType, lockTimeout, lockHandle, readOptions);

                if (cacheItem != null)
                {
                    result = cacheItem.getValue(cls);
                    long size = ((byte[])(Object)result).length;
                    try
                    {
                        cacheItem = getCompatibleItem(cacheItem);

                        _nearCache.insertOperation(key, result, cacheItem.getDependency(), new CacheSyncDependency(_farCache._cacheId, key, _userId, _password), getServerExpiration(ConversionUtil.getAbsoluteExpiration(cacheItem.getExpiration()), NoSlidingExpiration), ConversionUtil.getSlidingExpiration(cacheItem.getExpiration()), cacheItem.getCacheItemPriority(), WriteMode.None, null, EventTypeInternal.None, cacheItem.getResyncOptions().getResyncOnExpiration(), cacheItem.getGroup(), null, version, LockAccessType.PRESERVE_VERSION, ConversionUtil.toArray(cacheItem.getTags()), null, cacheItem.getResyncOptions().getProviderName(), cacheItem.getNamedTags(), null, null, EventDataFilter.None, EventDataFilter.None, true, null, (short) -1, (short) -1, (short) -1);

                    }
                    catch (CacheException e)
                    {
                        if (_nearCache.getExceptionEnabled())
                            throw e;
                    }
                }
            }
            catch (CacheException e2)
            {
                if (_nearCache.getExceptionEnabled())
                    throw e2;
            }
        }
        else
        {
            try
            {
                result = _nearCache.get(key, readOptions, cls);
            }
            catch (CacheException e3)
            {
                if (_nearCache.getExceptionEnabled())
                    throw e3;
            }

            if (result != null)
                return result;

            cacheItem = _farCache.getCacheItem(key, readOptions);

            if (cacheItem != null)
            {
                result = cacheItem.getValue(cls);
                long size = 0;
                try
                {
                    cacheItem = getCompatibleItem(cacheItem);

                    tangible.RefObject tempRef_size2 = new tangible.RefObject(size);
                    _nearCache.insertOperation(key, result, cacheItem.getDependency(), new CacheSyncDependency(_farCache._cacheId, key, _userId, _password), getServerExpiration(ConversionUtil.getAbsoluteExpiration(cacheItem.getExpiration()), NoSlidingExpiration), ConversionUtil.getSlidingExpiration(cacheItem.getExpiration()), cacheItem.getCacheItemPriority(), WriteMode.None, null, EventTypeInternal.None, cacheItem.getResyncOptions().getResyncOnExpiration(), cacheItem.getGroup(), null, version, LockAccessType.PRESERVE_VERSION, ConversionUtil.toArray(cacheItem.getTags()), null, cacheItem.getResyncOptions().getProviderName(), cacheItem.getNamedTags(), null, null, EventDataFilter.None, EventDataFilter.None, true, null, (short) -1, (short) -1, (short) -1);
                    size = tempRef_size2.argvalue;

                }
                catch (CacheException e4)
                {
                    if (_nearCache.getExceptionEnabled())
                        throw e4;
                }
            }
        }

        return result;
    }

    @Override
    public  java.util.Map getBulk(Iterable keys, ReadThruOptions readThruOptions, Class cls) throws CacheException, IllegalArgumentException, ClassCastException {
        java.util.Map clientResult = null;

        try
        {
            clientResult = _nearCache.getBulk(keys, null, cls);
        }
        catch (CacheException e)
        {
            if (_nearCache.getExceptionEnabled())
                throw e;
        }

        String[] keyList = Iterables.toArray(keys, String.class);

        if (clientResult != null && clientResult.size() == keyList.length)
            return clientResult;

        String[] remainingKeys = keyList;

        if (clientResult != null && clientResult.size() > 0)
        {
            remainingKeys = new String[keyList.length - clientResult.size()];
            for (int i = 0, j = 0; i < keyList.length; i++)
            {
                if (!clientResult.containsKey(keyList[i]))
                    remainingKeys[j++] = keyList[i];
            }
        }

        java.util.Map remoteResult = _farCache.getBulk(Arrays.asList(remainingKeys), readThruOptions, cls);

        if (remoteResult != null && remoteResult.size() > 0)
        {
            java.util.Map itemsdic = new java.util.HashMap();

            java.util.Hashtable type2ExpirationMap = new java.util.Hashtable();
            for (java.util.Map.Entry entry : remoteResult.entrySet())
            {
                String key = entry.getKey();
                CacheItem item = new CacheItem(entry.getValue());
                item.setSyncDependency(new CacheSyncDependency(_farCache._cacheId, key, _userId, _password));

                /* We don't have any overload for getting GetCachItem in bulk. Therefore to determine cache expirations
                 * of L2 cache item, we fetch a single cachetiem for a given object type and assign it to all the object of a same type.
                 * For e.g. if Customer type object returned by GetBulk has absolute expiration 't' then we will assign the same
                 * expiration to all other objects of the type Customer. [Approved by Iqbal Khan]
                 */
                java.lang.Class objectType = item.getValue(cls).getClass();

                if (!type2ExpirationMap.containsKey(objectType))
                {
                    CacheItem cacheItem = _farCache.getCacheItem(key, null);
                    type2ExpirationMap.put(objectType, cacheItem);
                }

                CacheItem l2CacheItem = (CacheItem)((type2ExpirationMap.get(objectType) instanceof CacheItem) ? type2ExpirationMap.get(objectType) : null);

                if (l2CacheItem != null)
                {
                    Expiration tempVar =l2CacheItem.getExpiration();
                    item.setExpiration(tempVar);

                    item.setCacheItemPriority(l2CacheItem.getCacheItemPriority());
                    item.setGroup(l2CacheItem.getGroup());
                    item.setTags(l2CacheItem.getTags());
                    item.setNamedTags(l2CacheItem.getNamedTags());
                    item.setResyncOptions(l2CacheItem.getResyncOptions() == null ? new ResyncOptions(false, null) : l2CacheItem.getResyncOptions());

                }
                itemsdic.put((String)((entry.getKey() instanceof String) ? entry.getKey() : null), item);
            }

            try
            {
                _nearCache.insertBulk(itemsdic, null);
            }
            catch (CacheException e2)
            {
                if (_nearCache.getExceptionEnabled())
                    throw e2;
            }
        }

        if (clientResult != null)
        {
            if (remoteResult == null)
                remoteResult = new java.util.HashMap(clientResult);
            else
            {
                for (java.util.Map.Entry entry : clientResult.entrySet())
                    remoteResult.put(entry.getKey(), entry.getValue());
            }
        }

        return remoteResult;
    }

    @Override
    public CacheItem getCacheItem(String key, ReadThruOptions readThruOptions) throws CacheException, IllegalArgumentException {
        try
        {

            CacheItem cacheItem = null;
            long size = 0;
            if(readThruOptions == null)
                readThruOptions = new ReadThruOptions(ReadMode.None);
            if (_isPessimistic)
            {
                try
                {
                    CacheItemVersion version = new CacheItemVersion();
                    if(readThruOptions.getReadMode() != ReadMode.ReadThruForced)
                        cacheItem = _nearCache.getCacheItem(key, version, null);
                    Object result = null;
                    if (cacheItem != null)
                    {
                        result = _farCache.getIfNewer(key, version, Object.class);
                        //if l2 does not return the item because item there is not
                        //newer then return the local item. otherwise return null because
                        //item is removed from l2.
                        if (result == null)
                        {
                            if (version == null||version.getVersion()==0)
                                return cacheItem;
                            else
                                return null;
                        }
                    }
                    if(cacheItem == null || result != null)
                    {
                        cacheItem = _farCache.getCacheItem(key, version, readThruOptions);
                        if (cacheItem != null)
                            version = cacheItem.getCacheItemVersion();
                    }

                    if (cacheItem != null)
                    {
                        try {
                            if (CacheItemWrapperInternal.GetCacheItemEntryType(cacheItem) != null && CacheItemWrapperInternal.GetCacheItemEntryType(cacheItem) == EntryType.CacheItem) {
                                cacheItem = getCompatibleItem(cacheItem);
                                _nearCache.insertOperation(key, cacheItem.getValue(Object.class), null, new CacheSyncDependency(_farCache._cacheId, key), getServerExpiration(ConversionUtil.getAbsoluteExpiration(cacheItem.getExpiration()), NoSlidingExpiration), ConversionUtil.getSlidingExpiration(cacheItem.getExpiration()), cacheItem.getCacheItemPriority(), WriteMode.None, null, EventTypeInternal.None, cacheItem.getResyncOptions().getResyncOnExpiration(), cacheItem.getGroup(), null, version, LockAccessType.PRESERVE_VERSION, ConversionUtil.toArray(cacheItem.getTags()), null, cacheItem.getResyncOptions().getProviderName(), cacheItem.getNamedTags(), null, null, EventDataFilter.None, EventDataFilter.None, true, null, (short) -1, (short) -1, (short) -1);
                            }
                        }
                        catch (CacheException e)
                        {
                            if (_nearCache.getExceptionEnabled())
                                throw e;
                        }
                    }
                }
                catch ( CacheException e2)
                {
                    if (_nearCache.getExceptionEnabled())
                        throw e2;
                }
            }
            else
            {

                try
                {
                    if(readThruOptions.getReadMode() != ReadMode.ReadThruForced)
                        cacheItem = _nearCache.getCacheItem(key);
                }
                catch (CacheException e3)
                {
                    if (_nearCache.getExceptionEnabled())
                        throw e3;
                }

                if (cacheItem != null)
                    return cacheItem;

                CacheItemVersion version = new CacheItemVersion();

                cacheItem = _farCache.getCacheItem(key, version, readThruOptions);

                if (cacheItem != null)
                {
                    try
                    {
                        if(CacheItemWrapperInternal.GetCacheItemEntryType(cacheItem)!=null && CacheItemWrapperInternal.GetCacheItemEntryType(cacheItem)== EntryType.CacheItem) {
                            CacheItemVersion tempVersion=cacheItem.getCacheItemVersion();
                            cacheItem = getCompatibleItem(cacheItem);
                            if(version.getVersion()==0)cacheItem.setCacheItemVersion(tempVersion);
                            _nearCache.insertOperation(key, cacheItem.getValue(Object.class), cacheItem.getDependency(), new CacheSyncDependency(_farCache._cacheId, key), getServerExpiration(ConversionUtil.getAbsoluteExpiration(cacheItem.getExpiration()), NoSlidingExpiration), ConversionUtil.getSlidingExpiration(cacheItem.getExpiration()), cacheItem.getCacheItemPriority(), WriteMode.None, null, EventTypeInternal.None, cacheItem.getResyncOptions().getResyncOnExpiration(), cacheItem.getGroup(), null, version, LockAccessType.PRESERVE_VERSION, ConversionUtil.toArray(cacheItem.getTags()), null, cacheItem.getResyncOptions().getProviderName(), cacheItem.getNamedTags(), null, null, EventDataFilter.None, EventDataFilter.None, true, null, (short) -1, (short) -1, (short) -1);
                        }

                    }
                    catch (CacheException e4)
                    {
                        if (_nearCache.getExceptionEnabled())
                            throw e4;
                    }
                }
            }

            return cacheItem;
        }
        finally
        {
            TargetMethodAttribute.setMethodOverload(0);
        }
    }

    @Override
    public CacheItem getCacheItem(String key, boolean acquireLock, TimeSpan lockTimeout, LockHandle lockHandle) throws CacheException {
        return _farCache.getCacheItem(key, acquireLock, lockTimeout, lockHandle);
    }

    @Override
    public java.util.Map getCacheItemBulk(Iterable keys, ReadThruOptions readThruOptions) throws CacheException {
        java.util.Map clientResult = null;
        java.util.Map  remoteResult = null;

        try
        {
            clientResult = _nearCache.getCacheItemBulk(keys, null);
        }
        catch ( CacheException e)
        {
            if (_nearCache.getExceptionEnabled())
                throw e;
        }

        String[] keyList = Iterables.toArray(keys, String.class);
        java.util.ArrayList remainingKeys = new java.util.ArrayList();

        if (clientResult != null)
        {
            if (clientResult.size() == keyList.length)
                return clientResult;

            for (int i = 0, j = 0; i < keyList.length; i++)
            {
                if (!clientResult.containsKey(keyList[i]))
                    remainingKeys.add(j++, keyList[i]);
            }

            if (remainingKeys.isEmpty())
                return clientResult;

            remoteResult = _farCache.getCacheItemBulk(remainingKeys, readThruOptions);

            if (remoteResult != null && remoteResult.size() > 0)
            {
                try
                {
                    _nearCache.insertBulk(remoteResult, null);
                }
                catch (CacheException e2)
                {
                    if (_nearCache.getExceptionEnabled())
                        throw e2;
                }
            }

            if (remoteResult == null)
                remoteResult = new java.util.HashMap(clientResult);
            else
            {
                for (java.util.Map.Entry entry : clientResult.entrySet())
                    remoteResult.put(entry.getKey(), entry.getValue());
            }
        }

        return remoteResult;
    }

    @Override
    public CacheItem getCacheItemInternal(String key, CacheItemVersion version, LockAccessType accessType, TimeSpan lockTimeout, LockHandle lockHandle, ReadThruOptions readOptions) throws CacheException {
        return _farCache.getCacheItemInternal(key, version, accessType, lockTimeout, lockHandle, readOptions);
    }

    @Override
    public boolean lock(String key, TimeSpan lockTimeout, LockHandle lockHandle) throws CacheException {
        return _farCache.lock(key, lockTimeout, lockHandle);
    }

    @Override
    public void unlock(String key) throws CacheException {
        _farCache.unlock(key);
    }

    @Override
    public void unlock(String key, LockHandle lockHandle) throws CacheException {
        _farCache.unlock(key, lockHandle);
    }

    @Override
    public  T getIfNewer(String key, CacheItemVersion version, Class cls) throws CacheException {
        T result = null;
        CacheItem cacheItem = null;

        if (version == null)
            throw new IllegalArgumentException("Value cannot be null."+System.lineSeparator()+"Parameter name: version");

        try
        {
            if (TargetMethodAttribute.getMethodOverload() == 0)
                TargetMethodAttribute.setMethodOverload(2);
            cacheItem = _farCache.getCacheItem(key);
        } catch (CacheException e) {
            e.printStackTrace();
        } finally
        {
            TargetMethodAttribute.setMethodOverload(0);
        }


        if (cacheItem != null)
        {
            // Bug Fix "5514"
            Object seralized = null;
            try {
                seralized = CompactBinaryFormatter.toByteBuffer(cacheItem.getValue(cls), _farCache._cacheId);
            } catch (IOException e) {
                throw new OperationFailedException(e);
            }
            long size = seralized instanceof byte[] ? ((byte[])seralized).length : 0;
            //
            result = cacheItem.getValue(cls);
            if (cacheItem.getCacheItemVersion() != null && cacheItem.getCacheItemVersion().getVersion() > version.getVersion())
                version.setVersion(cacheItem.getCacheItemVersion().getVersion());
            else
            {
                version.setVersion(0);
                return null;
            }
            try
            {
                if (!_nearCache.contains(key))
                {
                    if (cacheItem != null)
                        cacheItem = getCompatibleItem(cacheItem);

                    _nearCache.insertOperation(key, result, cacheItem.getDependency(), new CacheSyncDependency(_farCache._cacheId, key, _userId, _password), getServerExpiration(ConversionUtil.getAbsoluteExpiration(cacheItem.getExpiration()), NoSlidingExpiration), ConversionUtil.getSlidingExpiration(cacheItem.getExpiration()), cacheItem.getCacheItemPriority(), WriteMode.None, null, EventTypeInternal.None, cacheItem.getResyncOptions().getResyncOnExpiration(), cacheItem.getGroup(), null, version, LockAccessType.PRESERVE_VERSION, ConversionUtil.toArray(cacheItem.getTags()), null, cacheItem.getResyncOptions().getProviderName(), cacheItem.getNamedTags(), null, null, EventDataFilter.None, EventDataFilter.None, true, null, (short) -1, (short) -1, (short) -1);
                }
            }
            catch (CacheException e)
            {
                if (_nearCache.getExceptionEnabled())
                    throw e;
            }
        }
        return result;
    }

    @Override
    public boolean isLocked(String key, LockHandle lockHandle) throws CacheException {
        return _farCache.isLocked(key, lockHandle);
    }

    @Override
    public CacheStream getCacheStream(String key, CacheStreamAttributes cacheStreamAttributes) throws CacheException {
        return _farCache.getCacheStream(key, cacheStreamAttributes);
    }

    @Override
    public void addCacheNotification(String key, CacheDataModificationListener cacheDataModificationListener, EnumSet eventType, EventDataFilter datafilter, ListenerType listenerType) throws CacheException {
        super.addCacheNotification(key, cacheDataModificationListener, eventType, datafilter, listenerType);
    }

    //C# TO JAVA CONVERTER TODO TASK: There is no preprocessor in Java:
    ///#endregion

//C# TO JAVA CONVERTER TODO TASK: There is no preprocessor in Java:
    ///#region Register Notification Methods

//C# TO JAVA CONVERTER TODO TASK: There is no preprocessor in Java:
    ///#endregion


//C# TO JAVA CONVERTER TODO TASK: There is no preprocessor in Java:
    ///#region ToString Implementation

    @Override
    public String toString()
    {
        return "L1 cache=" + _nearCache.toString() + ", L2 cache=" + _farCache.toString();
    }

//C# TO JAVA CONVERTER TODO TASK: There is no preprocessor in Java:
    ///#endregion

//C# TO JAVA CONVERTER TODO TASK: There is no preprocessor in Java:
    ///#region  IDisposable Implementation
    @Override
    public void close(){
        _farCache.close();
        _nearCache.close();
    }

    @Override
    public void raiseCustomEvent(Object notifId, Object data) throws CacheException {
        _farCache.raiseCustomEvent(notifId, data);
    }
    @Override
    public void touch(java.util.ArrayList keys) throws OperationNotSupportedException, CommandException, GeneralFailureException, StreamNotFoundException, ConfigurationException, StreamException, AggregateException, OperationFailedException, StreamAlreadyLockedException, LicensingException, SecurityException {
        _farCache.touch(keys);
    }

    //C# TO JAVA CONVERTER TODO TASK: There is no preprocessor in Java:
//#if ENTERPRISE
    @Override
    public String getTargetCacheUniqueID()
    {
        return _farCache.getTargetCacheUniqueID();
    }

    @Override
    public void makeTargetCacheActivePassive(boolean makeActive) throws Exception {
        try
        {
            _farCache.makeTargetCacheActivePassive(makeActive);
        }
        catch (CacheException e)
        {
            if (_exceptionEnabled)
                throw e;
        }
    }

//#endif

    @Override
    public void InitializeEncryption() throws Exception {
        java.util.HashMap encryptionInfo = ((RemoteCache)_farCache.getCacheImpl()).getEncryptionInfo();
        if (encryptionInfo != null && encryptionInfo.size() > 0)
        {
            boolean enableEncryption = Boolean.parseBoolean((String)encryptionInfo.get("enabled"));
            _nearCache._exceptionEnabled = enableEncryption;
            EncryptionMgr.InitializeEncryption(enableEncryption, (String)encryptionInfo.get("key"), _nearCache.getCacheImpl().getName(), (String)encryptionInfo.get("provider"));
        }
    }

    public final java.util.Date GetCompatibleExpiration(java.util.Date absoluteExpiration, TimeSpan slidingExpiration)
    {
        if (!absoluteExpiration.equals(NoAbsoluteExpiration))
            return absoluteExpiration;

        if (slidingExpiration == NoSlidingExpiration)
            return NoAbsoluteExpiration;

        return new java.util.Date(slidingExpiration.getTotalTicks());
    }

    @Override
    public CacheReader executeReaderCQ(ContinuousQuery query, boolean getData, int chunkSize) throws CacheException {
        return _farCache.executeReaderCQ(query, getData, chunkSize);
    }

    @Override
    public void setExceptionsEnabled(boolean value) {
        _farCache.setExceptionsEnabled(value);
    }


}