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

org.apache.geode.cache.client.internal.ProxyCache Maven / Gradle / Ivy

/*
 * 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.geode.cache.client.internal;

import java.util.ArrayList;
import org.apache.geode.CancelCriterion;
import org.apache.geode.cache.CacheClosedException;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionService;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.query.QueryService;
import org.apache.geode.cache.query.internal.ProxyQueryService;
import org.apache.geode.distributed.internal.ServerLocation;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.internal.cache.LocalRegion;
import org.apache.geode.pdx.PdxInstance;
import org.apache.geode.pdx.PdxInstanceFactory;
import org.apache.geode.pdx.internal.PdxInstanceFactoryImpl;

import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;

/**
 * A wrapper class over an actual Cache instance. This is used when the multiuser-authentication
 * attribute is set to true. Application must use its {@link #getRegion(String)} API instead that of
 * actual Cache instance for getting a reference to Region instances, to perform operations on
 * server.
 * 
 * TODO Avoid creating multiple instances of ProxyCache for a single user.
 * 
 * @see ClientCache#createAuthenticatedView(Properties)
 * @see ProxyQueryService
 * @see ProxyRegion
 * @since GemFire 6.5
 */
public class ProxyCache implements RegionService {

  private final GemFireCacheImpl cache;
  private UserAttributes userAttributes;
  private ProxyQueryService proxyQueryService;
  private boolean isClosed = false;
  private final Stopper stopper = new Stopper();

  public ProxyCache(Properties properties, GemFireCacheImpl cache, PoolImpl pool) {
    this.userAttributes = new UserAttributes(properties, pool);
    this.cache = cache;
  }

  public void close() {
    close(false);
  }

  public void close(boolean keepAlive) {
    if (this.isClosed) {
      return;
    }
    // It should go to all the servers it has authenticated itself on and ask
    // them to clean-up its entry from their auth-data structures.
    try {
      if (this.proxyQueryService != null) {
        this.proxyQueryService.closeCqs(keepAlive);
      }
      UserAttributes.userAttributes.set(this.userAttributes);
      Iterator iter = this.userAttributes.getServerToId().keySet().iterator();
      while (iter.hasNext()) {
        ProxyCacheCloseOp.executeOn(iter.next(), (PoolImpl) this.userAttributes.getPool(),
            this.userAttributes.getCredentials(), keepAlive);
      }
      ArrayList proxyCache =
          ((PoolImpl) this.userAttributes.getPool()).getProxyCacheList();
      synchronized (proxyCache) {
        proxyCache.remove(this);
      }
    } finally {
      // @todo I think some NPE will be caused by this code.
      // It would be safer to not null things out.
      // It is really bad that we null out and then set isClosed true.
      this.isClosed = true;
      this.proxyQueryService = null;
      this.userAttributes.setCredentials(null);
      this.userAttributes = null;
      UserAttributes.userAttributes.set(null);
    }
  }

  // TODO remove this method
  public String getName() {
    return this.cache.getName();
  }

  public QueryService getQueryService() {
    preOp();
    if (this.proxyQueryService == null) {
      this.proxyQueryService =
          new ProxyQueryService(this, userAttributes.getPool().getQueryService());
    }
    return this.proxyQueryService;
  }

  public  Region getRegion(String path) {
    preOp();
    // TODO Auto-generated method stub
    // ProxyRegion region = this.proxyRegionList.get(path);
    // if (region != null) {
    // return region;
    // }
    // else {
    if (this.cache.getRegion(path) == null) {
      return null;
    } else {
      if (!this.cache.getRegion(path).getAttributes().getDataPolicy().isEmpty()) {
        throw new IllegalStateException(
            "Region's data-policy must be EMPTY when multiuser-authentication is true");
      }
      return new ProxyRegion(this, this.cache.getRegion(path));
    }
    // }
  }

  public boolean isClosed() {
    return this.isClosed;
  }

  public void setProperties(Properties properties) {
    preOp();
    this.userAttributes.setCredentials(properties);
  }

  public Properties getProperties() {
    preOp();
    return this.userAttributes.getCredentials();
  }

  public void setUserAttributes(UserAttributes userAttributes) {
    preOp();
    this.userAttributes = userAttributes;
  }

  public UserAttributes getUserAttributes() {
    preOp();
    return this.userAttributes;
  }

  public Object getUserId(Object key) {
    preOp();
    if (!(key instanceof ServerLocation)) {
      throw new IllegalArgumentException(
          "Key must be of type ServerLocation, but is " + key.getClass());
    }
    return this.userAttributes.getServerToId().get(key);
  }

  private void preOp() {
    this.stopper.checkCancelInProgress(null);
  }

  protected class Stopper extends CancelCriterion {
    /*
     * (non-Javadoc)
     * 
     * @see org.apache.geode.CancelCriterion#cancelInProgress()
     */
    @Override
    public String cancelInProgress() {
      String reason = cache.getCancelCriterion().cancelInProgress();
      if (reason != null) {
        return reason;
      }
      if (isClosed()) {
        return "Authenticated cache view is closed for this user.";
      }
      return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.geode.CancelCriterion#generateCancelledException(java.lang.Throwable)
     */
    @Override
    public RuntimeException generateCancelledException(Throwable e) {
      String reason = cancelInProgress();
      if (reason == null) {
        return null;
      }
      RuntimeException result = cache.getCancelCriterion().generateCancelledException(e);
      if (result != null) {
        return result;
      }
      if (e == null) {
        // Caller did not specify any root cause, so just use our own.
        return new CacheClosedException(reason);
      }

      try {
        return new CacheClosedException(reason, e);
      } catch (IllegalStateException e2) {
        // Bug 39496 (Jrockit related) Give up. The following
        // error is not entirely sane but gives the correct general picture.
        return new CacheClosedException(reason);
      }
    }
  }

  public CancelCriterion getCancelCriterion() {
    return this.stopper;
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.apache.geode.cache.RegionService#rootRegions()
   */
  public Set> rootRegions() {
    preOp();
    Set> rRegions = new HashSet>();
    Iterator it = this.cache.rootRegions().iterator();
    while (it.hasNext()) {
      LocalRegion lr = it.next();
      if (!lr.getAttributes().getDataPolicy().withStorage()) {
        rRegions.add(new ProxyRegion(this, lr));
      }
    }
    return Collections.unmodifiableSet(rRegions);
  }

  public PdxInstanceFactory createPdxInstanceFactory(String className) {
    return PdxInstanceFactoryImpl.newCreator(className, true);
  }

  public PdxInstanceFactory createPdxInstanceFactory(String className, boolean b) {
    return PdxInstanceFactoryImpl.newCreator(className, b);
  }

  public PdxInstance createPdxEnum(String className, String enumName, int enumOrdinal) {
    return PdxInstanceFactoryImpl.createPdxEnum(className, enumName, enumOrdinal, this.cache);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy