Package org.eclipse.wst.html.core.internal.modelquery

Source Code of org.eclipse.wst.html.core.internal.modelquery.XHTMLAssociationProvider

/*******************************************************************************
* Copyright (c) 2004, 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.wst.html.core.internal.modelquery;


import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.Platform;
import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager;
import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.XMLAssociationProvider;
import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
import org.w3c.dom.Document;

/**
* A Class to provide an association between XHTML documents and DTDs for
* XHTML. This class is intended to be used only in HTMLModelQueryCMProvider.
*/
/*
* This class closely resemble XMLModelQueryAssociationProvider.
*/
class XHTMLAssociationProvider extends XMLAssociationProvider {
 
  /**
   * set CACHE_FIXED_DOCUMENTS to false to test effects of not caching certain catalog-contributed schemas.
   */
  private static final boolean CACHE_FIXED_DOCUMENTS = true;
  private static final String[] STANDARD_SCHEMA_BUNDLES = new String[] {"org.eclipse.wst.standard.schemas","org.eclipse.jst.standard.schemas"};
  private static final String XML_CATALOG_EXT_POINT = "org.eclipse.wst.xml.core.catalogContributions";
  private static Collection fFixedPublicIDs = null;
  private static Map fFixedCMDocuments = new HashMap();

  /**
   * set USE_QUICK_CACHE to false to test effects of not caching at all.
   */
  private static final boolean USE_QUICK_CACHE = true;
  protected URIResolver idResolver;
  private String fCachedGrammerURI;
  private String fCachedPublicID;
  private String fCachedSystemID;
  private boolean cached;

  public XHTMLAssociationProvider(CMDocumentCache cache, URIResolver idResolver) {
    super(cache);
    this.idResolver = idResolver;
      
    // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=136399. If the CM document URI
    // is resolved and cached at this level instruct the CM model manager to avoid
    // re-resolving the URI.

    if (USE_QUICK_CACHE) {
      documentManager.setPropertyEnabled(CMDocumentManager.PROPERTY_PERFORM_URI_RESOLUTION, false);
    }
  }

  /**
   *
   * @param publicId
   * @param systemId
   * @return
   */
  public CMDocument getXHTMLCMDocument(String publicId, String systemId) {
    if (idResolver == null)
      return null;
   
    String grammerURI = null;
    if (USE_QUICK_CACHE) {
      /*
       * In parsing a document, we get many identical requests to this
       * method, so instead of looking up (resolving) grammerURI each
       * time, we'll just return previously cached one. Probably not
       * worth have a more complex cache than that.
       */
      if (cached && sameAs(fCachedPublicID, publicId) && sameAs(fCachedSystemID, systemId)) {
        grammerURI = fCachedGrammerURI;
      }
      else {
        grammerURI = idResolver.resolve(null, publicId, systemId);
        fCachedGrammerURI = grammerURI;
        fCachedPublicID = publicId;
        fCachedSystemID = systemId;
        cached = true;
      }
    }
    else {
      grammerURI = idResolver.resolve(null, publicId, systemId);
    }

    if (grammerURI == null)
      return null;
   
    CMDocument cmDocument = null;
    if (CACHE_FIXED_DOCUMENTS) {
      Reference ref = (Reference) fFixedCMDocuments.get(publicId);
      if (ref != null) {
        cmDocument = (CMDocument) ref.get();
        if (cmDocument != null) {
          return cmDocument;
        }
      }
    }
   
    /*
     * https://bugs.eclipse.org/bugs/show_bug.cgi?id=88896
     *
     * We once called the deprecated 2 argument form of getCMDocument.
     *
     * CMDocument cmDocument = documentManager.getCMDocument(publicId,
     * grammerURI);
     *
     * which eventually resulted in empty string for type, which I don't
     * think the infrastructure handles any longer. So, I deleted
     * deprecated methods, and switched to null for type argument.
     *
     * 'null' means to "create based on uri".
     *
     * FYI, 'dtd' would mean load only those registered as dtd's
     *
     * CMDocument cmDocument = documentManager.getCMDocument(publicId,
     * grammerURI); CMDocument cmDocument =
     * documentManager.getCMDocument(publicId, grammerURI, "dtd");
     */
    synchronized (grammerURI) {
      cmDocument = documentManager.getCMDocument(publicId, grammerURI, null);
    }
   
    if (CACHE_FIXED_DOCUMENTS && getFixedPublicIDs().contains(publicId)) {
      fFixedCMDocuments.put(publicId, new SoftReference(cmDocument));
    }
   
    return cmDocument;
  }

  /**
   */
  protected String resolveGrammarURI(Document document, String publicId, String systemId) {
    return idResolver.resolve(null, publicId, systemId);
  }

  private boolean sameAs(String a, String b) {
    boolean result = false;
    if (a == null) {
      result = b == null;
    }
    else {
      result = a.equals(b);
    }
    return result;
  }

  /**
   * This added and/or made public specifically for experimentation. It
   * will change as this functionality becomes API. See
   * https://bugs.eclipse.org/bugs/show_bug.cgi?id=119084
   */
  public String getCachedGrammerURI() {
    return fCachedGrammerURI;
  }

  /**
   * @return the fFixedPublicIDs, a collection of contributed Public
   *         Identifiers from the known schema plug-ins.
   */
  private static Collection getFixedPublicIDs() {
    /**
     * public:publicId
     * TODO: system:systemId and uri:name in their own methods and maps?
     */
    synchronized (STANDARD_SCHEMA_BUNDLES) {
      if (fFixedPublicIDs == null) {
        fFixedPublicIDs = new HashSet();
        for (int i = 0; i < STANDARD_SCHEMA_BUNDLES.length; i++) {
          IExtension[] extensions = Platform.getExtensionRegistry().getExtensions(STANDARD_SCHEMA_BUNDLES[i]);
          for (int j = 0; j < extensions.length; j++) {
            if (XML_CATALOG_EXT_POINT.equals(extensions[j].getExtensionPointUniqueIdentifier())) {
              IConfigurationElement[] configurationElements = extensions[j].getConfigurationElements();
              for (int k = 0; k < configurationElements.length; k++) {
                IConfigurationElement[] publics = configurationElements[k].getChildren("public");
                for (int l = 0; l < publics.length; l++) {
                  String publicId = publics[l].getAttribute("publicId");
                  if (publicId != null && publicId.length() > 0) {
                    fFixedPublicIDs.add(publicId);
                  }
                }
              }
            }
          }
        }
      }
    }
    return fFixedPublicIDs;
  }
}
TOP

Related Classes of org.eclipse.wst.html.core.internal.modelquery.XHTMLAssociationProvider

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.