Package org.eclipse.jst.pagedesigner.editors.palette.impl

Source Code of org.eclipse.jst.pagedesigner.editors.palette.impl.PaletteItemManager

/*******************************************************************************
* Copyright (c) 2006 Sybase, Inc. 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:
*     Sybase, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.pagedesigner.editors.palette.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.eclipse.gef.palette.PaletteDrawer;
import org.eclipse.gef.palette.PaletteEntry;
import org.eclipse.jst.jsf.common.internal.JSPUtil;
import org.eclipse.jst.jsf.common.runtime.internal.view.model.common.Namespace;
import org.eclipse.jst.jsf.core.internal.CompositeTagRegistryFactory;
import org.eclipse.jst.jsf.core.internal.CompositeTagRegistryFactory.TagRegistryIdentifier;
import org.eclipse.jst.jsf.designtime.internal.view.model.ITagRegistry;
import org.eclipse.jst.jsf.designtime.internal.view.model.ITagRegistry.ITagRegistryListener;
import org.eclipse.jst.jsf.designtime.internal.view.model.ITagRegistry.TagRegistryChangeEvent;
import org.eclipse.jst.jsf.designtime.internal.view.model.ITagRegistry.TagRegistryChangeEvent.EventType;
import org.eclipse.jst.pagedesigner.PDPlugin;
import org.eclipse.jst.pagedesigner.editors.palette.DesignerPaletteCustomizationsHelper;
import org.eclipse.jst.pagedesigner.editors.palette.IEntryChangeListener;
import org.eclipse.jst.pagedesigner.editors.palette.IPaletteConstants;
import org.eclipse.jst.pagedesigner.editors.palette.IPaletteContext;
import org.eclipse.jst.pagedesigner.editors.palette.IPaletteItemManager;
import org.eclipse.wst.html.core.internal.contentmodel.HTMLCMDocumentFactory;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocType;

/**
*  Manages tag library palette by palette context.   Capable of handling JSP and XHTML content types.
*  Callers must use getInstance(IPaletteContext), and when done, call release(IFile).  
* @author mengbo and others
*/
public class PaletteItemManager implements IPaletteItemManager,
    IPaletteConstants, ITagRegistryListener {
 
  private static final boolean DEBUG = false;

 
  private static Map<TagRegistryIdentifier, PaletteItemManager> _managers = new HashMap<TagRegistryIdentifier, PaletteItemManager>();
  private static ReentrantLock MANAGER_LOCK = new ReentrantLock();
  private static long MANAGER_LOCK_TIMEOUT = 120;
 
  private Set<IFile> _files = new HashSet<IFile>();
  private TagRegistryIdentifier _tagRegId;
  private List<PaletteDrawer> _paletteCategories = new ArrayList<PaletteDrawer>();
  private CopyOnWriteArrayList<IEntryChangeListener> _listeners = new CopyOnWriteArrayList<IEntryChangeListener>();
  private AtomicBoolean IS_DISPOSED = new AtomicBoolean();

  private PaletteHelper _paletteHelper;

  private ITagRegistry _tagRegistry;


  /**
   * Return singleton paletteItemManager for a given project.  Will only work for JSPs.
   * @param project
   * @return PaletteItemManager
   * @deprecated - use getInstance(paletteContext)
   */
  public static PaletteItemManager getInstance(final IProject project) {
    if (project == null) {
      // sometimes when the editor is editing a file in jar file, may not
      // be able to
      // get the project.
      return getInstance(createPaletteContext(null));
    }   
    //relies on JSP file extension for content type
    return getInstance(createPaletteContext(project.getFile("dummy.jsp")))//$NON-NLS-1$
  }
 
  /**
   * @param paletteContext
   * @return PaletteItemManager instance shared with all files with same palette context in a project
   *         May return null if locking issue
   */
  public static PaletteItemManager getInstance(final IPaletteContext paletteContext) { 
    boolean hasLock = false;
    try {
      if (MANAGER_LOCK.tryLock(MANAGER_LOCK_TIMEOUT, TimeUnit.SECONDS)){
        hasLock = true;
        final TagRegistryIdentifier regId = getTagRegistryIdentifier(paletteContext);
        if (regId == null) {
          PDPlugin.log(new Status(IStatus.ERROR, PDPlugin.getPluginId(), "Unable to display palette for "+paletteContext.getFile().getName()+".  Unknown content type for file."))//$NON-NLS-1$//$NON-NLS-2$
          return null;
        }
        PaletteItemManager manager = _managers.get(regId);
        if (manager == null) {
           manager = new PaletteItemManager(regId);
          _managers.put(regId, manager);
          manager.init();
        }
        manager.addFile(paletteContext.getFile());
        return manager;
       
      }
      //if we get here then the lock has timed out
      PDPlugin.log(new Status(Status.ERROR, PDPlugin.getPluginId(), "(getInstance()) Failed to get managers lock for" + paletteContext.getFile().toString())); //$NON-NLS-1$
     
    } catch (InterruptedException e) {
      PDPlugin.log("Failed in PaletteItemManager.getInstance(PaletteContext", e); //$NON-NLS-1$
    } finally {
      if (hasLock)
        MANAGER_LOCK.unlock();
    }
    return null;
  }
 
  private static TagRegistryIdentifier getTagRegistryIdentifier(
      final IPaletteContext paletteContext) {

    final IFile file = paletteContext.getFile();
    if (file != null) {
          final IContentTypeManager typeManager = Platform.getContentTypeManager();
          final IContentType contentType =
              typeManager.findContentTypeFor(file.getName());
         
          if (contentType != null)
          {
              return new TagRegistryIdentifier(file.getProject(), contentType);
          }
          return null;
    }
    //to support legacy null projects.   Allows HTML and JSP tag libs to be displayed.
      return new TagRegistryIdentifier(null, org.eclipse.jst.pagedesigner.utils.JSPUtil.JSP_CONTENTTYPE);

  }

  /**
   * @param file
   * @return IPaletteContext
   */
  public static IPaletteContext createPaletteContext(final IFile file) {
    return new IPaletteContext() {
      public IFile getFile() {
        return file;
      }

      public Object getAdapter(Class adapter) {       
        return null;
      }
    };
  }
  private void addFile(final IFile file) {
    synchronized (_files) {
      _files.add(file);
    }
   
  }
 
  /**
   * Indicates that the file no longer needs the paletteItemManager, freeing the manager to be released after last reference
   * @param paletteContext
   */
  public void release(final IPaletteContext paletteContext) {
    final IFile file = paletteContext.getFile();
    boolean isEmpty = false;
    synchronized (_files) {
      if (_files.contains(file)) {
        _files.remove(file);
        if (_files.isEmpty())
          isEmpty = true;
      }
    }

    if (isEmpty && IS_DISPOSED.compareAndSet(false, true)) {
      removeTagRegistryListeners(this);
      boolean hasLock = false;
      try {
        if (MANAGER_LOCK.tryLock(MANAGER_LOCK_TIMEOUT, TimeUnit.SECONDS)) {
          hasLock = true;
          _managers.remove(_tagRegId);
        }
        else {
          PDPlugin.log(new Status(Status.ERROR, PDPlugin.getPluginId(), "(Release) Failed to get managers lock for" + paletteContext.getFile().toString())); //$NON-NLS-1$
        }
      } catch (InterruptedException e) {
        PDPlugin.log("Failed to release paletteItemManager for" + paletteContext.getFile().toString(), e); //$NON-NLS-1$
      } finally {
        if (hasLock)
          MANAGER_LOCK.unlock();
      }
    }
  }

  private static void removeTagRegistryListeners(final PaletteItemManager manager) {
    if (manager.getTagRegistry() != null)
      manager.getTagRegistry().removeListener(manager);
  }

  private ITagRegistry getTagRegistry() {   
    return _tagRegistry;
  }

  /**
   * For JUnit testing purposes only
   */
  public static void clearPaletteItemManager() {
   
    boolean hasLock = false;
    try {
      if (MANAGER_LOCK.tryLock(MANAGER_LOCK_TIMEOUT, TimeUnit.SECONDS)){
        hasLock = true;
        if (_managers == null)
          return;

        for (final PaletteItemManager manager : _managers.values()) {
          PaletteItemManager.removeTagRegistryListeners(manager);   
          manager._files.clear();
        }             
        _managers.clear();
      } else {
        //if we get here then the lock has timed out
        PDPlugin.log(new Status(Status.ERROR, PDPlugin.getPluginId(), "(clear) Failed to get managers lock")); //$NON-NLS-1$
      }
     
    } catch (InterruptedException e) {
      PDPlugin.log("Failed in clearPaletteItemManager", e); //$NON-NLS-1$
    } finally {
      if (hasLock)
        MANAGER_LOCK.unlock();
    }

  }
 
  private PaletteItemManager(final TagRegistryIdentifier regId) {
    _paletteHelper = new PaletteHelper(this);
    if (regId != null) {
      _tagRegId = regId;
//      init();
    }   
  }
 

  public List getAllCategories() { 
    synchronized (_paletteCategories) {
      final List<PaletteDrawer> readOnlyCategories = new ArrayList<PaletteDrawer>(_paletteCategories);     
      return Collections.unmodifiableList(readOnlyCategories);
    }   
  }

  /**
   * Initializes the palette items for the current project
   */
  protected synchronized void init() {
    synchronized (_paletteCategories) {
      _paletteCategories.clear();
    }
   
    initTagRegistry();

    DesignerPaletteCustomizationsHelper.loadUserCustomizations(this);
   
    sortCategories();
  }

  /**
   * Sort palette categories
   */
  protected void sortCategories() {
    //note that once we store ordering customizations, we will need to do something different
    synchronized(_paletteCategories) {
      Collections.sort(_paletteCategories, new Comparator(){
 
        public int compare(Object o1, Object o2) {
          String label1 = ((PaletteEntry)o1).getLabel();
          String label2 = ((PaletteEntry)o2).getLabel();
         
          return label1.compareTo(label2);
        }
       
      });
    }
  }

  /**
   * Reinitializes the palatteItemManager and informs all palette roots that use the manager to refresh
   */
  public void reset() {
    init();
    fireModelChanged(null, null);
  }
 
  private void initTagRegistry() {
    registerHTMLCategory();
    if (isJSP(_tagRegId)){
      registerJSPCategory();
      registerTapestryCategory()
    }
    registerTagsFromTagRegistry()
  }

  private boolean isJSP(final TagRegistryIdentifier tagRegistryId) {
    final IContentType ct = tagRegistryId.getContentType();
    if (JSPUtil.isJSPContentType(ct.getId()))
      return true;
    return false;
  }

  private void registerTagsFromTagRegistry() {
    _tagRegistry = getTagRegistry(_tagRegId);
    if (_tagRegistry != null) {
      for (final Namespace ns : _tagRegistry.getAllTagLibraries()) {             
        _paletteHelper.configPaletteItemsByNamespace(this, ns);     
      }
    }
  }

  private ITagRegistry getTagRegistry(final TagRegistryIdentifier regId) {
    ITagRegistry reg = null;
    if (regId.getProject() != null) {
      reg = CompositeTagRegistryFactory.getInstance().getRegistry(regId);
      if (reg != null) {
        reg.addListener(this);
      }
    }
    return reg;
  }

  private void registerHTMLCategory() {
    final CMDocument doc = HTMLCMDocumentFactory.getCMDocument(CMDocType.HTML_DOC_TYPE);
    _paletteHelper.getOrCreateTaglibPaletteDrawer(this, doc, CMDocType.HTML_DOC_TYPE);
  }

  private void registerJSPCategory() {
    final CMDocument doc = HTMLCMDocumentFactory.getCMDocument(CMDocType.JSP11_DOC_TYPE);
    _paletteHelper.getOrCreateTaglibPaletteDrawer(this, doc, CMDocType.JSP11_DOC_TYPE);
  }
 
  private void registerTapestryCategory(){
    final CMDocument doc = HTMLCMDocumentFactory.getCMDocument(CMDocType.TAPESTRY5_DOC_TYPE);
    _paletteHelper.getOrCreateTaglibPaletteDrawer(this, doc, CMDocType.TAPESTRY5_DOC_TYPE);
  }

//  /**
//   * Search Classpath entry list to find if the entry is jar library and the
//   * library have the tld descriptor, if have ,build a palette category mapping
//   * the tld descriptor.
//   *
//   * @param project
//   */
//  private void registerTldFromClasspath(final IProject project) {
//    if (project != null) {
//      ITaglibRecord[] tldrecs = TaglibIndex.getAvailableTaglibRecords(project.getFullPath());
//      for (int i=0;i<tldrecs.length;i++){       
//        _paletteHelper.configPaletteItemsByTLD(this, getCurProject(), tldrecs[i]);     
//      }
//    }     
//  }

  /**
   * @param id (most likely the uri)
   * @param label
   * @return TaglibPaletteDrawer
   */
  public TaglibPaletteDrawer findOrCreateCategory(final String id, final String label) {
    TaglibPaletteDrawer category = getTaglibPalletteDrawer(id);
    if (category == null)
      category = createTaglibPaletteDrawer(id, label);
    return category;
  }

  /**
   * @param uri
   * @return TaglibPaletteDrawer
   */
  public TaglibPaletteDrawer findCategoryByURI(final String uri) {
    TaglibPaletteDrawer category;
    for (final Iterator iter = getAllCategories().iterator(); iter.hasNext();) {
      category = (TaglibPaletteDrawer) iter.next();
      if (uri.equals(category.getURI())) {
        return category;
      }
    }
    return null;
  }

  public TaglibPaletteDrawer createTaglibPaletteDrawer(final String uri, final String label) {
    final TaglibPaletteDrawer r = new TaglibPaletteDrawer(uri, label);
    synchronized(_paletteCategories) {
      _paletteCategories.add(r);
    }
    return r;
  }

  public TaglibPaletteDrawer getTaglibPalletteDrawer(final String uri) {
    for (final Iterator iter = getAllCategories().iterator(); iter.hasNext();) {
      final TaglibPaletteDrawer cat = (TaglibPaletteDrawer) iter.next();
      if (uri.equalsIgnoreCase(cat.getId())) {
        return cat;
      }
    }
    return null;
  }

  /*
   * (non-Javadoc)
   *
   * @see com.sybase.stf.jmt.pagedesigner.editors.palette.IPaletteItemManager#addEntryChangeListener(com.sybase.stf.jmt.pagedesigner.editors.palette.IEntryChangeListener)
   */
  public void addEntryChangeListener(final IEntryChangeListener listener) {
    _listeners.addIfAbsent(listener);
  }

  /*
   * (non-Javadoc)
   *
   * @see com.sybase.stf.jmt.pagedesigner.editors.palette.IPaletteItemManager#removeEntryChangeListener(com.sybase.stf.jmt.pagedesigner.editors.palette.IEntryChangeListener)
   */
  public void removeEntryChangeListener(final IEntryChangeListener listener) {   
    _listeners.remove(listener);
  }

  /**
   * Notify model change event
   *
   * @param oldDefinitions
   * @param newDefinitions
   */
  private void fireModelChanged(final List oldDefinitions, final List newDefinitions) {
    if (_listeners == null) {
      return;
    }
    for (final Iterator<IEntryChangeListener> it= _listeners.iterator();it.hasNext();){
      final IEntryChangeListener listener = it.next();
      listener.modelChanged(oldDefinitions, newDefinitions);
   
  }
 
  /**
   * Informs all paletteItemManagers, except the notifying paletteManager, of updates to the customizations
   * All palette viewer roots will be notifed of possible updates
   * @param notifyingManager
   */
  public static void notifyPaletteItemManagersOfCustomizationsUpdate(final IPaletteItemManager notifyingManager){
    boolean hasLock = false;
    try {
      if (MANAGER_LOCK.tryLock(MANAGER_LOCK_TIMEOUT, TimeUnit.SECONDS)){
        hasLock = true;
        for (Iterator it=_managers.values().iterator();it.hasNext();){
          final PaletteItemManager mgr = (PaletteItemManager)it.next();
          if (mgr != null && notifyingManager != mgr)
            mgr.reset();
        }
      }
      else {
        //if we get here then the lock has timed out
        PDPlugin.log(new Status(Status.ERROR, PDPlugin.getPluginId(), "Failed to get managers lock in notifyPaletteItemManagersOfCustomizationsUpdate")); //$NON-NLS-1$
      }
     
    } catch (InterruptedException e) {
      PDPlugin.log("Failed in notifyPaletteItemManagersOfCustomizationsUpdate", e); //$NON-NLS-1$
    } finally {
      if (hasLock)
        MANAGER_LOCK.unlock();
    }

  }

  public void registryChanged(final TagRegistryChangeEvent event) {
    final EventType eventType = event.getType();
    switch (eventType) {
      case ADDED_NAMESPACE:
        addNamespaces(event.getAffectedObjects());
        break;
      case REMOVED_NAMESPACE:
        removeNamespaces(event.getAffectedObjects());
        break;
      case CHANGED_NAMESPACE:
        changeNamespaces(event.getAffectedObjects());
        break;
      case REGISTRY_DISPOSED:
        break;
 
      default:
        break;
    }
   
    DesignerPaletteCustomizationsHelper.loadUserCustomizations(this);
    sortCategories();
   
    fireModelChanged(null, null);
  }


  private void addNamespaces(final List<? extends Namespace> affectedObjects) {
    synchronized (_paletteCategories) {
      for (final Namespace ns : affectedObjects) {
        if (DEBUG)
          System.out.println("Add NS: "+ns.getNSUri()+"["+System.currentTimeMillis()+"]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        _paletteHelper.configPaletteItemsByNamespace(this, ns);
      }
    }
  }
 
  private void removeNamespaces(final List<? extends Namespace> affectedObjects) {
    final List<Integer> drawersToRemove = new ArrayList<Integer>();
    synchronized (_paletteCategories) {
      for (final Namespace ns : affectedObjects) {
        for (int i=_paletteCategories.size() - 1; i >= 0; i--) {//gather in reverse order
          final PaletteDrawer drawer = _paletteCategories.get(i);
          if (drawer.getId().equals(ns.getNSUri())) {
            if (DEBUG)
              System.out.println("Remove NS: "+drawer.getId() +"["+System.currentTimeMillis()+"]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
            drawersToRemove.add(new Integer(i))
          }
        }
      } 
      if (! drawersToRemove.isEmpty()) {
        Collections.sort(drawersToRemove, new Comparator<Integer>() {//reverse order sort

          public int compare(Integer o1, Integer o2) {
            if (o1.intValue() > o2.intValue())
              return -1;
            else if (o1.intValue() < o2.intValue())
              return 1;
             
            return 0;
          }
        });
        for (Integer index : drawersToRemove) {
          _paletteCategories.remove(index.intValue());       
        }
      }
    }
  }

  private void changeNamespaces(final List<? extends Namespace> affectedObjects) {
    //for now, remove then add
    removeNamespaces(affectedObjects);
    addNamespaces(affectedObjects);   
  }

  public TagRegistryIdentifier getTagRegistryIdentifier() {   
    return _tagRegId;
  }

  /**
   * @return helper
   */
  public PaletteHelper getPaletteHelper() {
    return _paletteHelper;
  }

}
TOP

Related Classes of org.eclipse.jst.pagedesigner.editors.palette.impl.PaletteItemManager

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.