Package org.springframework.ide.eclipse.beans.core.internal.model.namespaces

Source Code of org.springframework.ide.eclipse.beans.core.internal.model.namespaces.ProjectClasspathNamespaceDefinitionResolverCache$ResolvlerCacheEntry

/*******************************************************************************
* Copyright (c) 2010 Spring IDE Developers
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.beans.core.internal.model.namespaces;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IProject;
import org.eclipse.jdt.core.ElementChangedEvent;
import org.eclipse.jdt.core.IElementChangedListener;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.springframework.ide.eclipse.beans.core.model.INamespaceDefinitionResolver;
import org.springframework.ide.eclipse.core.java.JdtUtils;


/**
* @author Christian Dupuis
*/
public class ProjectClasspathNamespaceDefinitionResolverCache {

  private static final int CACHE_SIZE = 12;

  private static List<ResolvlerCacheEntry> RESOLVER_CACHE = new ArrayList<ResolvlerCacheEntry>(CACHE_SIZE);

  private static INamespaceDefinitionResolver addResolverToCache(IProject project) {
    synchronized (RESOLVER_CACHE) {
      int nEntries = RESOLVER_CACHE.size();
      if (nEntries >= CACHE_SIZE) {
        // find obsolete entries or remove entry that was least recently accessed
        ResolvlerCacheEntry oldest = null;
        List<ResolvlerCacheEntry> obsoleteClassLoaders = new ArrayList<ResolvlerCacheEntry>(CACHE_SIZE);
        for (int i = 0; i < nEntries; i++) {
          ResolvlerCacheEntry entry = RESOLVER_CACHE.get(i);
          IProject curr = entry.getProject();
          if (!curr.exists() || !curr.isAccessible() || !curr.isOpen()) {
            obsoleteClassLoaders.add(entry);
          }
          else {
            if (oldest == null || entry.getLastAccess() < oldest.getLastAccess()) {
              oldest = entry;
            }
          }
        }
        if (!obsoleteClassLoaders.isEmpty()) {
          for (int i = 0; i < obsoleteClassLoaders.size(); i++) {
            removeResolverEntryFromCache(obsoleteClassLoaders.get(i));
          }
        }
        else if (oldest != null) {
          removeResolverEntryFromCache(oldest);
        }
      }
      ResolvlerCacheEntry newEntry = new ResolvlerCacheEntry(project);
      RESOLVER_CACHE.add(newEntry);
      return newEntry.getResolver();
    }
  }

  private static INamespaceDefinitionResolver findResolverInCache(IProject project) {
    synchronized (RESOLVER_CACHE) {
      for (int i = RESOLVER_CACHE.size() - 1; i >= 0; i--) {
        ResolvlerCacheEntry entry = RESOLVER_CACHE.get(i);
        IProject curr = entry.getProject();
        if (!curr.exists() || !curr.isAccessible() || !curr.isOpen()) {
          removeResolverEntryFromCache(entry);
        }
        else {
          if (entry.matches(project)) {
            entry.markAsAccessed();
            return entry.getResolver();
          }
        }
      }
    }
    return null;
  }

  private static void removeResolverEntryFromCache(ResolvlerCacheEntry entry) {
    synchronized (RESOLVER_CACHE) {
      entry.dispose();
      RESOLVER_CACHE.remove(entry);
    }
  }

  public synchronized static INamespaceDefinitionResolver getResolver(IProject project) {
    INamespaceDefinitionResolver resolver = findResolverInCache(project);
    if (resolver == null) {
      resolver = addResolverToCache(project);
    }
    return resolver;
  }

  /**
   * Internal cache entry
   */
  private static class ResolvlerCacheEntry implements IElementChangedListener {

    private long lastAccess;

    private IProject project;
   
    private ProjectClasspathNamespaceDefinitionResolver resolver;

    public ResolvlerCacheEntry(IProject project) {
      this.project = project;
      this.resolver = new ProjectClasspathNamespaceDefinitionResolver(project);
      markAsAccessed();
      JavaCore.addElementChangedListener(this, ElementChangedEvent.POST_CHANGE);
    }

    public void dispose() {
      JavaCore.removeElementChangedListener(this);
      resolver.dispose();
      resolver = null;
    }

    public void elementChanged(ElementChangedEvent event) {
      IJavaProject javaProject = JdtUtils.getJavaProject(project);
      if (javaProject != null) {
        for (IJavaElementDelta delta : event.getDelta().getAffectedChildren()) {
          if ((delta.getFlags() & IJavaElementDelta.F_RESOLVED_CLASSPATH_CHANGED) != 0
              || (delta.getFlags() & IJavaElementDelta.F_CLASSPATH_CHANGED) != 0) {
            if (javaProject.equals(delta.getElement()) || javaProject.isOnClasspath(delta.getElement())) {
              removeResolverEntryFromCache(this);
            }
          }
        }
      }
    }
   
    public INamespaceDefinitionResolver getResolver() {
      return resolver;
    }
   
    public long getLastAccess() {
      return lastAccess;
    }

    public IProject getProject() {
      return this.project;
    }

    public void markAsAccessed() {
      lastAccess = System.currentTimeMillis();
    }

    public boolean matches(IProject project) {
      return this.project.equals(project);
    }

  }

}
TOP

Related Classes of org.springframework.ide.eclipse.beans.core.internal.model.namespaces.ProjectClasspathNamespaceDefinitionResolverCache$ResolvlerCacheEntry

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.