Package org.eclipse.wst.xml.core.internal.catalog

Source Code of org.eclipse.wst.xml.core.internal.catalog.Catalog$UserCatalogLS

/*******************************************************************************
* Copyright (c) 2002, 2011 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
*     Jens Lukowski/Innoopract - initial renaming/restructuring
*     Jesper Steen Moeller - Added XML Catalogs 1.1 support
*    
*******************************************************************************/
package org.eclipse.wst.xml.core.internal.catalog;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.Platform;
import org.eclipse.wst.xml.core.internal.Logger;
import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEvent;
import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogListener;
import org.eclipse.wst.xml.core.internal.catalog.provisional.IDelegateCatalog;
import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
import org.eclipse.wst.xml.core.internal.catalog.provisional.IRewriteEntry;
import org.eclipse.wst.xml.core.internal.catalog.provisional.ISuffixEntry;
public class Catalog implements ICatalog
{

  class CatalogLS
  {
    public void load()
    {
    }

    public synchronized void save()
    {
      try
      {
        new CatalogWriter().write(Catalog.this, location);
      } catch (Exception e)
      {
        Logger.logException(e);
      }
    }
  }

  class DefaultCatalogLS extends CatalogLS
  {
    public void load()
    {
      NextCatalog userCatalogReference = new NextCatalog();
      userCatalogReference.setId(XMLCorePlugin.USER_CATALOG_ID);
      userCatalogReference.setCatalogLocation(USER_CATALOG_FILE);
      addCatalogElement(userCatalogReference);

      NextCatalog systemCatalogReference = new NextCatalog();
      systemCatalogReference.setId(XMLCorePlugin.SYSTEM_CATALOG_ID);
      systemCatalogReference.setCatalogLocation(SYSTEM_CATALOG_FILE);
      addCatalogElement(systemCatalogReference);

      /*
       * Here we save the file in order to 'reflect' the catalog that
       * we've created from plug-in extensions to disk. The 'default'
       * catalog is only ever written to disk and never read from disk.
       */
      save();
    }
  }

  private static Comparator LONGEST_REWRITE_FIRST = new Comparator()
  {
    public int compare(Object entry1, Object entry2)
    {
      String start1 = ((IRewriteEntry)entry1).getStartString();
      String start2 = ((IRewriteEntry)entry2).getStartString();
     
      // Bigger is earlier
      return start2.length() - start1.length();
    }
  };

  private static Comparator LONGEST_SUFFIX_FIRST = new Comparator()
  {
    public int compare(Object entry1, Object entry2)
    {
      String suffix1 = ((ISuffixEntry)entry1).getSuffix();
      String suffix2 = ((ISuffixEntry)entry2).getSuffix();
     
      // Bigger is earlier
      return suffix2.length() - suffix1.length();
    }
  };

  private static Comparator LONGEST_DELEGATE_PREFIX_FIRST = new Comparator()
  {
    public int compare(Object entry1, Object entry2)
    {
      String prefix1 = ((IDelegateCatalog)entry1).getStartString();
      String prefix2 = ((IDelegateCatalog)entry2).getStartString();
     
      // Bigger is earlier
      return prefix2.length() - prefix1.length();
    }
  };

  class InternalResolver
  {
    protected Map publicMap = new HashMap();

    protected Map systemMap = new HashMap();

    protected Map uriMap = new HashMap();

    // These are sorted by longest "key" first.
    protected List rewriteSystemList = new LinkedList();
    protected List rewriteUriList = new LinkedList();
    protected List suffixSystemList = new LinkedList();
    protected List suffixUriList = new LinkedList();
    protected List delegatePublicList = new LinkedList();
    protected List delegateSystemList = new LinkedList();
    protected List delegateUriList = new LinkedList();
   
    InternalResolver()
    {
      synchronized (catalogElements) {
        for (Iterator i = catalogElements.iterator(); i.hasNext();)
        {
          ICatalogElement catalogElement = (ICatalogElement) i.next();
          if (catalogElement.getType() == ICatalogElement.TYPE_ENTRY)
          {
            ICatalogEntry entry = (ICatalogEntry) catalogElement;
            Map map = getEntryMap(entry.getEntryType());
            map.put(entry.getKey(), entry);
          }
          else if (catalogElement.getType() == ICatalogElement.TYPE_REWRITE)
          {
            IRewriteEntry entry = (IRewriteEntry) catalogElement;
            if (entry.getEntryType() == IRewriteEntry.REWRITE_TYPE_SYSTEM)
            {
              rewriteSystemList.add(entry);
            }
            else
            {
              rewriteUriList.add(entry);
            }
          }
          else if (catalogElement.getType() == ICatalogElement.TYPE_SUFFIX)
          {
            ISuffixEntry entry = (ISuffixEntry) catalogElement;
            if (entry.getEntryType() == ISuffixEntry.SUFFIX_TYPE_SYSTEM)
            {
              suffixSystemList.add(entry);
            }
            else
            {
              suffixUriList.add(entry);
            }
          }
          else if (catalogElement.getType() == ICatalogElement.TYPE_DELEGATE)
          {
            IDelegateCatalog delegate = (IDelegateCatalog) catalogElement;
            if (delegate.getEntryType() == IDelegateCatalog.DELEGATE_TYPE_PUBLIC)
            {
              delegatePublicList.add(delegate);
            }
            else if (delegate.getEntryType() == IDelegateCatalog.DELEGATE_TYPE_SYSTEM)
            {
              delegateSystemList.add(delegate);
            }
            else
            {
              delegateUriList.add(delegate);
            }
          }
        }
      }
     
      Collections.sort(rewriteSystemList, LONGEST_REWRITE_FIRST);
      Collections.sort(rewriteUriList, LONGEST_REWRITE_FIRST);

      Collections.sort(suffixSystemList, LONGEST_SUFFIX_FIRST);
      Collections.sort(suffixUriList, LONGEST_SUFFIX_FIRST);
   
      Collections.sort(delegatePublicList, LONGEST_DELEGATE_PREFIX_FIRST);
      Collections.sort(delegateSystemList, LONGEST_DELEGATE_PREFIX_FIRST);
      Collections.sort(delegateUriList, LONGEST_DELEGATE_PREFIX_FIRST);
    }

    private Map getEntryMap(int entryType)
    {
      Map map = systemMap;
      switch (entryType)
      {
      case ICatalogEntry.ENTRY_TYPE_PUBLIC:
        map = publicMap;
        break;
      case ICatalogEntry.ENTRY_TYPE_URI:
        map = uriMap;
        break;
      default:
        break;
      }
      return map;
    }

    protected String getMappedURI(Map map, String key)
    {
      CatalogEntry entry = (CatalogEntry) map.get(key);
      if(entry == null) return null;
      String uri = entry.getURI();
      try
      {
                // TODO CS : do we really want to resolve these here?
                // I'm guessing we should return the 'platform:' form of the URI
                // to the caller.
                if (uri.startsWith("platform:")) //$NON-NLS-1$
               
          URL entryURL = new URL(entry.getAbsolutePath(uri));               
          uri = Platform.resolve(entryURL).toString();
                 
                  // we need to ensure URI's are of form "file:///D:/XXX" and NOT 
                  // "file:D:/XXX".  Otherwise the EMF URI class gets confused
                  // (see bug 103607)
                  String FILE_SCHEME = "file:"; //$NON-NLS-1$
                  if (uri.startsWith(FILE_SCHEME) && !uri.startsWith(FILE_SCHEME + "/")) //$NON-NLS-1$
                  {
                    uri = FILE_SCHEME + "///" + uri.substring(FILE_SCHEME.length()); //$NON-NLS-1$
                 
                } 
                return uri;
      } catch (IOException e)
      {
        return null;
      }
    }

    public String resolvePublic(String publicId, String systemId)
        throws MalformedURLException, IOException
    {
      String result = getMappedURI(publicMap, publicId);
      if (result == null)
      {
        result = getMappedURI(systemMap, systemId);
      }
      // our clients used to pass namespace in place of public id, so we need to check uri map for those
      if (result == null)
      {
        result = getMappedURI(uriMap, publicId);
      }
      if (result == null)
      {
        result = resolveDelegateCatalogs(delegatePublicList, publicId, systemId);
      }
      if (result == null)
      {
        result = resolveSubordinateCatalogs(
            ICatalogEntry.ENTRY_TYPE_PUBLIC, publicId, systemId);
      }
      return result;
    }

    public String resolveSystem(String systemId)
        throws MalformedURLException, IOException
    {
      String result = getMappedURI(systemMap, systemId);
      if (result == null)
      {
        result = resolveRewrite(rewriteSystemList, systemId);
      }
      if (result == null)
      {
        result = resolveSuffix(suffixSystemList, systemId);
      }
      if (result == null)
      {
        result = resolveDelegateCatalogs(delegateSystemList, systemId, systemId); // systemId is the key for "startString"
      }
      if (result == null)
      {
        result = resolveSubordinateCatalogs(
            ICatalogEntry.ENTRY_TYPE_SYSTEM, null, systemId);
      }
      return result;
    }

    private String resolveRewrite(List rewriteList, String searchString)
    {
      for (Iterator it = rewriteList.iterator(); it.hasNext();)
      {
        IRewriteEntry entry = (IRewriteEntry) it.next();
        String startString = entry.getStartString();
        if (searchString.startsWith(startString))
        {
          return entry.getRewritePrefix() + searchString.substring(startString.length());
        }
      }
      return null;
    }

    private String resolveSuffix(List suffixList, String searchString) {
      for (Iterator it = suffixList.iterator(); it.hasNext();) {
        ISuffixEntry entry = (ISuffixEntry) it.next();
        if (searchString.endsWith(entry.getSuffix())) {
          return entry.getURI();
        }
      }
      return null;
    }

    protected String resolveDelegateCatalogs(List delegateCatalogs, String key,
        String systemId) throws MalformedURLException, IOException
    {
      String result = null;
      for (Iterator iterator = delegateCatalogs.iterator(); iterator
          .hasNext();) {
        IDelegateCatalog delegate = (IDelegateCatalog) iterator.next();
       
        if (key.startsWith(delegate.getStartString())) {
 
          ICatalog catalog = delegate.getReferencedCatalog();
          if (catalog != null)
          {
            switch (delegate.getEntryType())
            {
            case IDelegateCatalog.DELEGATE_TYPE_PUBLIC:
              result = catalog.resolvePublic(key, systemId);
              break;
            case IDelegateCatalog.DELEGATE_TYPE_SYSTEM:
              result = catalog.resolveSystem(systemId);
              break;
            case IDelegateCatalog.DELEGATE_TYPE_URI:
              result = catalog.resolveURI(systemId);
              break;
            default:
              break;
            }
            if (result != null)
            {
              return result;
            }
          }
        }
      }
      return null;
    }
   
    public String resolveURI(String uri) throws MalformedURLException,
        IOException
    {
      String result = getMappedURI(uriMap, uri);
      if (result == null)
      {
        result = resolveRewrite(rewriteUriList, uri);
      }
      if (result == null)
      {
        result = resolveSuffix(suffixUriList, uri);
      }
      if (result == null)
      {
        result = resolveDelegateCatalogs(delegateUriList, uri, uri); // uri is treated as the systemId
      }
      if (result == null)
      {
        result = resolveSubordinateCatalogs(
            ICatalogEntry.ENTRY_TYPE_URI, null, uri);
      }
      return result;
    }
  }

  class SystemCatalogLS extends CatalogLS
  {
    public void load()
    {
      new CatalogContributorRegistryReader(Catalog.this).readRegistry();

      /*
       * Here we save the file in order to 'reflect' the catalog that
       * we've created from plugin extensions to disk.
       * The 'system' catalog is only ever written to disk and never read from disk.
       */
      save();
    }
  }

  class UserCatalogLS extends CatalogLS
  {
    public void load()
    {
      InputStream inputStream = null;
      try
      {
        if (location != null && location.length() > 0)
        {
          URL url = new URL(location);
          inputStream = url.openStream();
          boolean oldNotificationEnabled = isNotificationEnabled();
          setNotificationEnabled(false);
          clear();
          try
          {
            CatalogReader.read(Catalog.this, inputStream);
          } finally
          {
            setNotificationEnabled(oldNotificationEnabled);
          }
        }
        else
        {
          clear();
        }
        notifyChanged();
      } catch (Exception e)
      {
        // This is OK since the catalog may not exist before we create it
      } finally
      {
        if (inputStream != null)
        {
          try
          {
            inputStream.close();
          } catch (Exception e)
          {
          }
        }
      }
    }
  }

  public static final String DEFAULT_CATALOG_FILE = "default_catalog.xml"; //$NON-NLS-1$

  public static final String SYSTEM_CATALOG_FILE = "system_catalog.xml"; //$NON-NLS-1$

  public static final String USER_CATALOG_FILE = "user_catalog.xml"; //$NON-NLS-1$

  protected String base;

  protected List catalogElements = new ArrayList();

  protected CatalogLS catalogLS;

  protected String id;

  protected InternalResolver internalResolver;

  protected boolean isNotificationEnabled;

  protected List listenerList = new ArrayList();

  protected String location;

  protected CatalogSet resourceSet;

  public Catalog(CatalogSet catalogResourceSet, String id, String location)
  {
    this.resourceSet = catalogResourceSet;
    this.id = id;
    this.location = location;

    if (XMLCorePlugin.DEFAULT_CATALOG_ID.equals(id))
    {
      catalogLS = new DefaultCatalogLS();
    } else if (XMLCorePlugin.SYSTEM_CATALOG_ID.equals(id))
    {
      catalogLS = new SystemCatalogLS();
    } else
    {
      catalogLS = new UserCatalogLS();
    }
  }

  public void addCatalogElement(ICatalogElement element)
  {
    synchronized (catalogElements) {
      catalogElements.add(element);
    }
    element.setOwnerCatalog(this);
    internalResolver = null;
    notifyAddElement(element);
  }

  public void addEntriesFromCatalog(ICatalog catalog)
  {
    try
    {
      setNotificationEnabled(false);
      if (catalog != null)
      {
        ICatalogElement[] entries = ((Catalog)catalog).getCatalogElements();
        for (int i = 0; i < entries.length; i++)
        {
          CatalogElement clone = (CatalogElement)((CatalogElement)entries[i]).clone();
          addCatalogElement(clone);
        }
      } else
      {
        Logger.log(Logger.ERROR, "argument was null in Catalog.addEntriesFromCatalog"); //$NON-NLS-1$
      }
    } finally
    {
      setNotificationEnabled(true);
    }
    internalResolver = null;
    notifyChanged();
  }

  public void addListener(ICatalogListener listener)
  {
    listenerList.add(listener);
  }

  public void clear()
  {
    synchronized (catalogElements) {
      catalogElements.clear();
    }
    internalResolver = null;
    notifyChanged();
  }

  public ICatalogElement createCatalogElement(int type)
  {
    switch (type)
    {
    case ICatalogElement.TYPE_ENTRY:
      return new CatalogEntry(); // TODO: Should be kind of deprecated
    case ICatalogElement.TYPE_NEXT_CATALOG:
      return new NextCatalog();
    case ICatalogEntry.ENTRY_TYPE_PUBLIC:
    case ICatalogEntry.ENTRY_TYPE_SYSTEM:
    case ICatalogEntry.ENTRY_TYPE_URI:
      return new CatalogEntry(type);
    case ICatalogElement.TYPE_REWRITE: 
    case IRewriteEntry.REWRITE_TYPE_SYSTEM:
    case IRewriteEntry.REWRITE_TYPE_URI:
      return new RewriteEntry(type);
    case ICatalogElement.TYPE_SUFFIX: 
    case ISuffixEntry.SUFFIX_TYPE_SYSTEM:
    case ISuffixEntry.SUFFIX_TYPE_URI:
      return new SuffixEntry(type);
    case ICatalogElement.TYPE_DELEGATE: 
    case IDelegateCatalog.DELEGATE_TYPE_PUBLIC:
    case IDelegateCatalog.DELEGATE_TYPE_SYSTEM:
    case IDelegateCatalog.DELEGATE_TYPE_URI:
      return new DelegateCatalog(type);
    default:
      throw new IllegalArgumentException("Unknown element type " + type);//$NON-NLS-1 // Makes no sense at all!
    }
  }

  public String getBase()
  {
    return base;
  }

  private List getCatalogElements(int type)
  {
    List result = new ArrayList();
    ICatalogElement[] elements = (ICatalogElement[]) catalogElements
        .toArray(new ICatalogElement[catalogElements.size()]);
    for (int i = 0; i < elements.length; i++)
    {
      ICatalogElement element = elements[i];
      if (element.getType() == type)
      {
        result.add(element);
      }
    }
    return result;
  }

  public ICatalogEntry[] getCatalogEntries()
  {
    List result = getCatalogElements(ICatalogElement.TYPE_ENTRY);
    return (ICatalogEntry[]) result
        .toArray(new ICatalogEntry[result.size()]);
  }

  public IDelegateCatalog[] getDelegateCatalogs()
  {
    List result = getCatalogElements(ICatalogElement.TYPE_DELEGATE);
    return (IDelegateCatalog[]) result
        .toArray(new IDelegateCatalog[result.size()]);
  }
 
  public IRewriteEntry[] getRewriteEntries()
  {
    List result = getCatalogElements(ICatalogElement.TYPE_REWRITE);
    return (IRewriteEntry[]) result
        .toArray(new IRewriteEntry[result.size()]);
  }
 
  public ISuffixEntry[] getSuffixEntries()
  {
    List result = getCatalogElements(ICatalogElement.TYPE_SUFFIX);
    return (ISuffixEntry[]) result
        .toArray(new ISuffixEntry[result.size()]);
  }
 
  protected CatalogSet getCatalogSet()
  {
    return resourceSet;
  }

  public String getId()
  {
    return id;
  }

  public String getLocation()
  {
    return location;
  }

  public INextCatalog[] getNextCatalogs()
  {
    List result = getCatalogElements(ICatalogElement.TYPE_NEXT_CATALOG);
    return (INextCatalog[]) result.toArray(new INextCatalog[result.size()]);
  }

  protected InternalResolver getOrCreateInternalResolver()
  {
    if (internalResolver == null)
    {
      internalResolver = new InternalResolver();
    }
    return internalResolver;
  }

  protected boolean isNotificationEnabled()
  {
    return isNotificationEnabled;
  }

  public void load() throws IOException
  {
    catalogLS.load();
  }

  protected void notifyAddElement(ICatalogElement entry)
  {
    if (isNotificationEnabled)
    {
      ICatalogEvent event = new CatalogEvent(this, entry,
          ICatalogEvent.ELEMENT_ADDED);
      notifyListeners(event);
    }
  }

  protected void notifyChanged()
  {
    ICatalogEvent event = new CatalogEvent(this, null,
        ICatalogEvent.CHANGED);
    notifyListeners(event);
  }

  protected void notifyListeners(ICatalogEvent event)
  {
    List list = new ArrayList();
    list.addAll(listenerList);
    for (Iterator i = list.iterator(); i.hasNext();)
    {
      ICatalogListener listener = (ICatalogListener) i.next();
      listener.catalogChanged(event);
    }
  }

  protected void notifyRemoveElement(ICatalogElement element)
  {
    if (isNotificationEnabled)
    {
      ICatalogEvent event = new CatalogEvent(this, element,
          ICatalogEvent.ELEMENT_REMOVED);
      notifyListeners(event);
    }
  }

  public void removeCatalogElement(ICatalogElement element)
  {
    synchronized (catalogElements) {
      catalogElements.remove(element);
    }
    internalResolver = null;
    notifyRemoveElement(element);
   
  }

  public void removeListener(ICatalogListener listener)
  {
    listenerList.remove(listener);
  }

  public String resolvePublic(String publicId, String systemId)
      throws MalformedURLException, IOException
  {
    return getOrCreateInternalResolver().resolvePublic(publicId, systemId);
  }

  protected String resolveSubordinateCatalogs(int entryType, String publicId,
      String systemId) throws MalformedURLException, IOException
  {
    String result = null;
    INextCatalog[] nextCatalogs = getNextCatalogs();
    for (int i = 0; i < nextCatalogs.length; i++)
    {
      INextCatalog nextCatalog = nextCatalogs[i];
      ICatalog catalog = nextCatalog.getReferencedCatalog();
      if (catalog != null)
      {
        switch (entryType)
        {
        case ICatalogEntry.ENTRY_TYPE_PUBLIC:
          result = catalog.resolvePublic(publicId, systemId);
          break;
        case ICatalogEntry.ENTRY_TYPE_SYSTEM:
          result = catalog.resolveSystem(systemId);
          break;
        case ICatalogEntry.ENTRY_TYPE_URI:
          result = catalog.resolveURI(systemId);
          break;
        default:
          break;
        }
        if (result != null)
        {
          return result;
        }
      }
    }
    return null;
  }

  public String resolveSystem(String systemId) throws MalformedURLException,
      IOException
  {
    return getOrCreateInternalResolver().resolveSystem(systemId);
  }

  public String resolveURI(String uri) throws MalformedURLException,
      IOException
  {
    return getOrCreateInternalResolver().resolveURI(uri);
  }

  public void save() throws IOException
  {
    catalogLS.save();
  }

  public void setBase(String base)
  {
    this.base = base;
  }

  public void setId(String id)
  {
    this.id = id;
  }

  public void setLocation(String location)
  {
    this.location = location;
  }

  protected void setNotificationEnabled(boolean b)
  {
    isNotificationEnabled = b;
  }

  public ICatalogElement[] getCatalogElements()
  {
    return (ICatalogElement[]) catalogElements.toArray(new ICatalogElement[catalogElements.size()]);
  }
 

 

}
TOP

Related Classes of org.eclipse.wst.xml.core.internal.catalog.Catalog$UserCatalogLS

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.