⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multirepository.java

📁 一个完整的XACML工程,学习XACML技术的好例子!
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
   *    of elements, as DN; each DN must have a non-null repository corresponding
   * @param AttributeNames The array of LDAP names for the attributes; can be
   *    null, if all available attributes and their values are to be retrieved
   *
   * @return the requested attributes; the Repository status reflects the status
   *    of retrieval, the diagnosis contains exceptions the underlying objects
   *    threw, if they failed
   *
   * @throws RepositoryException, if all of the repositories failed, in which case the
   *    embedded exception will be the Throwable returned by <code>getDiagnosis</code>
   *    method; FAILURE_STATUS will also be set
   *
   * @see MultiThreadSearch#getAttributes
   */
  protected Attributes getAttributes(java.security.Principal[] DN, AttributeRepository [] repositories, String [] AttributeNames) throws RepositoryException{
    MultiThreadSearch ms = new MultiThreadSearch();
    try{
      return ms.getAttributes(DN, repositories, AttributeNames);
    }finally{
      mts=ms;
    }
  }

  /**
   * This method returns the status of the repository. It is set when returning
   * attributes.
   *
   * @return the integer value corresponding to the status
   *
   * @see getAttributes(java.security.Principal,String[])
   */
  public int getStatus(){
    return mts.status;
  }

  /**
   * This method returns the Throwable, representing the error, or null, if no
   * error has been encountered (only if the repository is in SUCCESS_STATUS).
   * The Throwable contains an error message and the stack trace of the error.
   *
   * @return Throwable object, representing the error, or null, if no error occured
   */
  public Throwable getDiagnosis(){
    return mts.diagnosis;
  }

  /**
   * This method returns the array of repositories used by the MultiRepository
   * by default (when TokenLocators do not refer to a specific repository).
   *
   * @return the array of AttributeRespositories used by MultiRepository by
   *   default; is never null, does not contain null entries, but may be empty
   *   (zero length)
   */
  public AttributeRepository [] getRepositories() {
    return initialRepositories;
  }
}

/**
 * This is a utility class that does the actual search in multiple repositories
 * using multiple threads. The logic of invocation must guarantee that it is
 * used from a single Thread.
 */
class MultiThreadSearch implements Runnable {
  protected int status;                           // status of the Repository
  protected Throwable diagnosis;                  // the ultimate status: the stack frame in it, the error message to deliver, etc

  private AttributeRepository [] reps;
  private Throwable [] statuses;      // the latest Exceptions thrown by run() methods; null for OK
  private Attributes [] results;      // the latest results returned by run() methods

  /**
   * Variables used by run() method
   */
  private java.security.Principal searchDN[];     // this is the DN that the run() method uses
  private String [] attrIDs;                    // this is the IDs of attributes the run() method uses
  private int launched=0;                       // counter of launched threads
  private int [] finished={0};                  // counter of terminated threads
                                                // it is an array, because I want it to be secure when calling getAttributes twice in a row for any unobvious reason - I can do wait() on arrays
  protected MultiThreadSearch(){}

  /**
   * This method sets up a number of threads, each retrieving the whole set of
   * attributes from one repository using the corresponding entry name. The
   * list of entry names must be synchronous with the list of repositories.
   *
   * <p>As the result of calling this method, the diagnosis and status will be
   * set.
   *
   * @param DN - the entry names; one for each repository
   * @param repositories - the repositories; one for each entry in the DN array
   * @param AttributeNames - the names of the attributes to be retrieved from
   *   all repositories; if null, all available attributes will be retrieved
   *
   * @return the requested Attributes
   */
  protected Attributes getAttributes(java.security.Principal[] DN, AttributeRepository [] repositories, String [] AttributeNames) throws RepositoryException{
    status = AttributeRepository.SUCCESS_STATUS;
    diagnosis = null;       // nothing has been thrown so far
    launched=0;
    finished=new int[]{0};  // thus, stray threads will use their own copy
    searchDN=DN;
    reps=repositories;
    attrIDs = AttributeNames;
    statuses = new Throwable[reps.length];
    results = new Attributes[reps.length];

    try{
      try{
        while (launched<reps.length){   // launched is updated by run() method, called by Thread().start()
          synchronized(this){
            new Thread(this).start(); // searches in different LDAPs will be mainly independent, and lots of waiting; so let them be different threads
            this.wait();        // wait till the run() passes by updating the launched counter
          }
        }
        synchronized(this.finished){
          if (finished[0]<reps.length){ // yet not everyone has finished.
            this.finished.wait();       // so hold me, until it sleeps.. ;-)
                                        // until it wakes, actually :-)))))
          }
        }

        // now we are alright; collect the wrecks :-)
        // or whatever the world has brought to us

        // we are synchronized, and noone else is supposed to replace statuses and results array values
        Exception pe = null;

        for (int i=0; i<statuses.length; i++){
          if (statuses[i]!=null){
            // something has happened in thread i while accessing reps[i]

            // at this point we should verify how crucial the error was
            pe = new issrg.utils.ExceptionPairException(pe, statuses[i]);   // now we can output the thing
          }
          if (statuses[i]==null || results[i]!=null) status = AttributeRepository.PARTIAL_SUCCESS_STATUS;
        }

        if (pe!=null && status==AttributeRepository.SUCCESS_STATUS){
          // this means that the branch status=PARTIAL_SUCCESS_STATUS has never been
          // executed; meaning that all of the statuses were not null; meaning
          // it is a complete failure.
          throw new RepositoryException(null, pe);
        }

        if (pe==null){
	  // this means that all the iterations of the loop went through 
	  // status=PARTIAL_SUCCESS_STATUS branch, so in fact it is a complete success
          status=AttributeRepository.SUCCESS_STATUS;
        }

        diagnosis = pe;

        // here it is safe to collect results
        // do not amend the status variable

        Attributes result = new javax.naming.directory.BasicAttributes();

        for (int i=0; i<results.length; i++){
          Attributes a = results[i];
          if (a==null) continue;

          for(javax.naming.NamingEnumeration ne = a.getIDs(); ne.hasMoreElements();){
            String id = (String)ne.nextElement();
            javax.naming.directory.Attribute attr = a.get(id), collection_attr=result.get(id);
            if (attr!=null){
              if (collection_attr==null){
                result.put(attr);
              }else{
                for(javax.naming.NamingEnumeration ne1 = attr.getAll(); ne1.hasMoreElements(); ){
                  collection_attr.add(ne1.nextElement()); // do I check for the return value?..
                }

              // since we have updated the object by reference, this should be sufficient
              // unless they return us a clone...
              }
            }
          }
        }

        // now result contains all Attributes and all values for each of them

        return result;
      }catch (InterruptedException ie){
        // this and the following catches are put here for the reason
        // we might want to change the error code or the exception thrown
        // (e.g. throw a descendant of the PbaException, not the PbaException itself)
        throw new RepositoryException("The thread was interrupted while waiting", ie);
      }catch (javax.naming.NamingException ne){
        throw new RepositoryException("Naming violation", ne);
      }catch(Throwable th){
        throw new RepositoryException("Unknown error", th);
      }
    }catch(RepositoryException pe){  // really, this try{}catch block is needed purely to set this status
                              // note, that nothing else is thrown withing that block(!)
                              // so the method is error-free; i mean, all the reports can be
                              // reported to the caller in a valid manner
      status = AttributeRepository.FAILURE_STATUS;
      diagnosis=pe;
      throw pe;
    }

  }

  /**
   * This method is needed for efficient Attribute retrieval. You should not
   * call it directly, as this is part of Runnable interface.
   */
  public void run(){
    int idx;
      // lets have a local copy of everything, so if the getAttribtues screws up,
      // we won't screw up a consequent call.
      AttributeRepository rep;
      int [] fin;
      int when_notify;
      Attributes [] ress;
      Throwable [] stats;

      java.security.Principal searchDN;
      String [] attrIDs = this.attrIDs;


    synchronized(this){
      when_notify = reps.length;
      idx=launched;
      ress=results;
      stats=statuses;
      searchDN = this.searchDN[idx];
      fin = finished;   // save the pointer, so even if anything happens to the caller thread, we won't spoil the subsequent calls to the run()
      results[idx]=null;
      rep=reps[idx];

      // unlock the waiter - let us launch search in another repository
      launched++;
      this.notifyAll();
    }

    // now i believe all entries about the idx index are locked for my sole use

    Attributes result=null;
    Throwable status=null;
    try{
      // do some real retrieval here :-)

	// calling the implementation's method - it will go look for the attributes
      result = rep.getAttributes(searchDN, attrIDs);
      status = rep.getDiagnosis(); // this is not thread-safe; If multiple threads use the same repository it may happen some diagnosis is lost, but the advantage is that multiple threads may invoke search on the same repository
    }catch(Throwable th){
      status=th;
    }finally{
      ress[idx]=result;
      stats[idx]=status;

      synchronized(fin){
        fin[0]++;
        if (when_notify<=fin[0]){    // release the wait of the getAttributes()
          fin.notifyAll();
        }
      }
    }
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -