Package org.eclipse.core.internal.expressions

Source Code of org.eclipse.core.internal.expressions.TypeExtensionManager

/*******************************************************************************
* Copyright (c) 2000, 2006 IBM Corporation and others.
* 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:
*     IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.core.internal.expressions;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionDelta;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IRegistryChangeEvent;
import org.eclipse.core.runtime.IRegistryChangeListener;
import org.eclipse.core.runtime.Platform;

import org.eclipse.core.expressions.IPropertyTester;

public class TypeExtensionManager implements IRegistryChangeListener {
 
  private String fExtensionPoint;
 
  private static final String TYPE= "type"; //$NON-NLS-1$
 
  private static final IPropertyTester[] EMPTY_PROPERTY_TESTER_ARRAY= new IPropertyTester[0];
 
  private static final IPropertyTester NULL_PROPERTY_TESTER= new IPropertyTester() {
    public boolean handles(String namespace, String property) {
      return false;
    }
    public boolean isInstantiated() {
      return true;
    }
    public boolean isDeclaringPluginActive() {
      return true;
    }
    public IPropertyTester instantiate() throws CoreException {
      return this;
    }
    public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
      return false;
    }
  };
 
  /*
   * Map containing all already created type extension object.
   */
  private Map/*<Class, TypeExtension>*/ fTypeExtensionMap;
 
  /*
   * Table containing mapping of class name to configuration element
   */
  private Map/*<String, List<IConfigurationElement>>*/ fConfigurationElementMap;
 
  /*
   * A cache to give fast access to the last 1000 method invocations.
   */
  private PropertyCache fPropertyCache;
 
 
  public TypeExtensionManager(String extensionPoint) {
    Assert.isNotNull(extensionPoint);
    fExtensionPoint= extensionPoint;
    Platform.getExtensionRegistry().addRegistryChangeListener(this);
    initializeCaches();
  }

  public Property getProperty(Object receiver, String namespace, String method) throws CoreException  {
    return getProperty(receiver, namespace, method, false);
  }
 
  public synchronized Property getProperty(Object receiver, String namespace, String method, boolean forcePluginActivation) throws CoreException  {
    long start= 0;
    if (Expressions.TRACING)
      start= System.currentTimeMillis();
   
    // if we call a static method than the receiver is the class object
    Class clazz= receiver instanceof Class ? (Class)receiver : receiver.getClass();
    Property result= new Property(clazz, namespace, method);
    Property cached= fPropertyCache.get(result);
    if (cached != null) {
      if (cached.isValidCacheEntry(forcePluginActivation)) {
        if (Expressions.TRACING) {
          System.out.println("[Type Extension] - method " + //$NON-NLS-1$
            clazz.getName() + "#" + method + //$NON-NLS-1$
            " found in cache: " //$NON-NLS-1$
            (System.currentTimeMillis() - start) + " ms."); //$NON-NLS-1$
        }
        return cached;
      }
      // The type extender isn't loaded in the cached method but can be loaded
      // now. So remove method from cache and do the normal look up so that the
      // implementation class gets loaded.
      fPropertyCache.remove(cached);
    }
    TypeExtension extension= get(clazz);
    IPropertyTester extender= extension.findTypeExtender(this, namespace, method, receiver instanceof Class, forcePluginActivation);
    if (extender == TypeExtension.CONTINUE || extender == null) {
      throw new CoreException(new ExpressionStatus(
        ExpressionStatus.TYPE_EXTENDER_UNKOWN_METHOD,
        Messages.format(
          ExpressionMessages.TypeExtender_unknownMethod, 
          new Object[] {method, clazz.toString()})));
    }
    result.setPropertyTester(extender);
    fPropertyCache.put(result);
    if (Expressions.TRACING) {
      System.out.println("[Type Extension] - method " + //$NON-NLS-1$
        clazz.getName() + "#" + method + //$NON-NLS-1$
        " not found in cache: " //$NON-NLS-1$
        (System.currentTimeMillis() - start) + " ms."); //$NON-NLS-1$
    }
    return result;
  }
 
  /*
   * This method doesn't need to be synchronized since it is called
   * from withing the getProperty method which is synchronized
   */
  /* package */ TypeExtension get(Class clazz) {
    TypeExtension result= (TypeExtension)fTypeExtensionMap.get(clazz);
    if (result == null) {
      result= new TypeExtension(clazz);
      fTypeExtensionMap.put(clazz, result);
    }
    return result;
  }
 
  /*
   * This method doesn't need to be synchronized since it is called
   * from withing the getProperty method which is synchronized
   */
  /* package */ IPropertyTester[] loadTesters(Class type) {
    if (fConfigurationElementMap == null) {
      fConfigurationElementMap= new HashMap();
      IExtensionRegistry registry= Platform.getExtensionRegistry();
      IConfigurationElement[] ces= registry.getConfigurationElementsFor(
        ExpressionPlugin.getPluginId(),
        fExtensionPoint);
      for (int i= 0; i < ces.length; i++) {
        IConfigurationElement config= ces[i];
        String typeAttr= config.getAttribute(TYPE);
        List typeConfigs= (List)fConfigurationElementMap.get(typeAttr);
        if (typeConfigs == null) {
          typeConfigs= new ArrayList();
          fConfigurationElementMap.put(typeAttr, typeConfigs);
        }
        typeConfigs.add(config);
      }
    }
    String typeName= type.getName();
    List typeConfigs= (List)fConfigurationElementMap.get(typeName);
    if (typeConfigs == null)
      return EMPTY_PROPERTY_TESTER_ARRAY;
    else {
      IPropertyTester[] result= new IPropertyTester[typeConfigs.size()];
      for (int i= 0; i < result.length; i++) {
        IConfigurationElement config= (IConfigurationElement)typeConfigs.get(i);
        try {
          result[i]= new PropertyTesterDescriptor(config);
        } catch (CoreException e) {
          ExpressionPlugin.getDefault().getLog().log(e.getStatus());
          result[i]= NULL_PROPERTY_TESTER;
        }
      }
      fConfigurationElementMap.remove(typeName);
      return result;
    }
  }
 
  public void registryChanged(IRegistryChangeEvent event) {
    IExtensionDelta[] deltas= event.getExtensionDeltas(ExpressionPlugin.getPluginId(), fExtensionPoint);
    if (deltas.length > 0) {
      initializeCaches();
    }
  }
 
  private synchronized void initializeCaches() {
    fTypeExtensionMap= new HashMap();
    fConfigurationElementMap= null;
    fPropertyCache= new PropertyCache(1000);
  }
}
TOP

Related Classes of org.eclipse.core.internal.expressions.TypeExtensionManager

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.