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

Source Code of org.eclipse.wst.html.core.internal.htmlcss.URLModelProvider

/*******************************************************************************
* Copyright (c) 2004, 2007 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.htmlcss;



import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.UnsupportedCharsetException;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeConstants;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.encoding.EncodingRule;
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceAlreadyExists;
import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceInUse;
import org.eclipse.wst.sse.core.internal.util.PathHelper;
import org.eclipse.wst.sse.core.internal.util.ProjectResolver;
import org.eclipse.wst.sse.core.internal.util.URIResolver;
import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapter;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

// TODO when this class is removed from .core, PathHelper and URLHelper class
// also can be removed.

/**
*/
public class URLModelProvider {

  private static final int GET_MODEL_FOR_READ = 1;
  //  private static final int GET_NEW_MODEL_FOR_READ = 2;
  private static final int GET_MODEL_FOR_EDIT = 3;
  //  private static final int GET_NEW_MODEL_FOR_EDIT = 4;
  //  private static final int READ_BUFFER_SIZE = 4096;
  // IModelManager
  private IModelManager modelManager = null;

  /**
   */
  public URLModelProvider() {
    super();

    // obtain model manager
    modelManager = StructuredModelManager.getModelManager();
  }

  /**
   * Calculate ID from a filename. This must be same as
   * FileModelProvider.calculateId(IFile)
   */
  private static String calculateId(IPath fullIPath) {
    return fullIPath.toString();
  }

  /**
   * <code>baseModel</code>: the model containing the link
   * <code>ref</code>: the link URL string
   */
  private IStructuredModel getCommonModelFor(final IStructuredModel baseModel, final String ref, final int which) throws IOException {
    // first, create absolute url
    String absURL = resolveURI(baseModel, ref, true);
    if ((absURL == null) || (absURL.length() == 0)) {
      return null;
    }

    // need to remove file:// scheme if necessary
    try {
      final java.net.URL aURL = new java.net.URL(absURL);
      // An actual URL was given, only file:/// is supported
      // resolve it by finding the file it points to
      if (!aURL.getProtocol().equals("platform")) { //$NON-NLS-1$
        if (aURL.getProtocol().equals("file") && (aURL.getHost().equals("localhost") || aURL.getHost().length() == 0)) {//$NON-NLS-2$//$NON-NLS-1$
          absURL = aURL.getFile();
          final IPath ipath = new Path(absURL);
          //  if path has a device, and if it begins with
          // IPath.SEPARATOR, remove it
          final String device = ipath.getDevice();
          if ((device != null) && (device.length() > 0)) {
            if (device.charAt(0) == IPath.SEPARATOR) {
              final String newDevice = device.substring(1);
              absURL = ipath.setDevice(newDevice).toString();
            }
          }

        }
      }
    }
    catch (java.net.MalformedURLException mfuExc) {
    }


    // next, decide project
    IProject project = null;
    final IPath fullIPath = new Path(absURL);
    IWorkspaceRoot workspace = ResourcesPlugin.getWorkspace().getRoot();
    IContainer container = workspace.getContainerForLocation(fullIPath);
    if (container != null) {
      // fullIPath doesn't exist in workspace
      project = container.getProject();
    }

    // If HTML document has a link to an extern CSS which is not in
    // IProject
    // workspace.getContainerForLoation() may return null. We need to take
    // care
    // of this case

    // now, get absURL's IFile
    if ((project != null) && (project.getLocation().isPrefixOf(fullIPath) == false)) {
      // it's at outside of Project
      return null;
    }

    IStructuredModel model = null;
    if (project != null) {
      IPath filePath = fullIPath.removeFirstSegments(project.getLocation().segmentCount());
      IFile file = (filePath != null && !filePath.isEmpty()) ? project.getFile(filePath) : null;
      if (file == null) {
        return null;
      }

      // obtain model
      if (which == GET_MODEL_FOR_EDIT) {
        model = getModelForEdit(file);
      }
      else if (which == GET_MODEL_FOR_READ) {
        model = getModelForRead(file);
      }

      // setting synchronization stamp is IModelManager's client's
      // responsibility
      if (model != null && model.getSynchronizationStamp() == IResource.NULL_STAMP)
        model.resetSynchronizationStamp(file);
    }
    else {
      String id = null;
      InputStream inStream = null;
      // obtain resolver
      URIResolver resolver = (project != null) ? (URIResolver) project.getAdapter(URIResolver.class) : null;
      if (resolver == null) {
        // ProjectResolver can take care of the case if project is
        // null.
        resolver = new ProjectResolver(project);
      }
      if (resolver == null) {
        return null;
      }

      // there is no project. we can't expect IProject help to create
      // id/inputStream
      java.io.File file = fullIPath.toFile();

      // obatin id
      id = calculateId(fullIPath);

      // obtain InputStream
      try {
        inStream = new FileInputStream(file);
      }
      catch (FileNotFoundException fnfe) {
        // the file does not exist, or we don't have read permission
        return null;
      }

      // obtain model
      try {
        if (which == GET_MODEL_FOR_EDIT) {
          model = getModelManager().getModelForEdit(id, inStream, resolver);
        }
        else if (which == GET_MODEL_FOR_READ) {
          model = getModelManager().getModelForRead(id, inStream, resolver);
        }
      }
      catch (UnsupportedEncodingException ue) {
      }
      catch (IOException ioe) {
      }
      finally {
        // close now !
        if (inStream != null) {
          inStream.close();
        }
      }
    }


    // set locationid
    if (model != null && model.getBaseLocation() == null) {
      model.setBaseLocation(fullIPath.toString());
    }

    return model;
  }

  /**
   * <code>baseModel</code>: the model containing the link
   * <code>ref</code>: the link URL string
   */
  public IStructuredModel getModelForEdit(IStructuredModel baseModel, String ref) throws IOException {
    return getCommonModelFor(baseModel, ref, GET_MODEL_FOR_EDIT);
  }

  /**
   */
  private IStructuredModel getModelForEdit(IFile file) throws IOException {
    if (file == null)
      return null;
    IModelManager manager = getModelManager();

    // create a fake InputStream
    IStructuredModel model = null;
    try {
      model = manager.getModelForEdit(file);
    }
    catch (UnsupportedCharsetException ex) {
      try {
        model = manager.getModelForEdit(file, EncodingRule.FORCE_DEFAULT);
      }
      catch (IOException ioe) {
      }
      catch (CoreException ce) {
      }
    }
    catch (CoreException ce) {
    }
    return model;
  }

  /**
   * <code>baseModel</code>: the model containing the link
   * <code>ref</code>: the link URL string
   */
  public IStructuredModel getModelForRead(IStructuredModel baseModel, String ref) throws UnsupportedEncodingException, IOException {
    return getCommonModelFor(baseModel, ref, GET_MODEL_FOR_READ);
  }

  /**
   */
  private IStructuredModel getModelForRead(IFile file) throws IOException {
    if (file == null)
      return null;
    IModelManager manager = getModelManager();

    // create a fake InputStream
    IStructuredModel model = null;
    try {
      model = manager.getModelForRead(file);
    }
    catch (UnsupportedCharsetException ex) {
      try {
        model = manager.getModelForRead(file, EncodingRule.FORCE_DEFAULT);
      }
      catch (IOException ioe) {
      }
      catch (CoreException ce) {
      }
    }
    catch (CoreException ce) {
    }
    return model;
  }

  /**
   */
  private IModelManager getModelManager() {
    return modelManager;
  }

  public IStructuredModel getNewModelForEdit(IFile iFile) {
    if (iFile == null)
      return null;
    IModelManager manager = getModelManager();
    if (manager == null)
      return null;

    IStructuredModel model = null;
    try {
      model = manager.getNewModelForEdit(iFile, false);
    }
    catch (IOException ex) {
    }
    catch (ResourceInUse riu) {
    }
    catch (ResourceAlreadyExists rae) {
    }
    catch (CoreException ce) {
    }
    return model;
  }

  public IStructuredModel getNewModelForRead(IFile iFile) {
    if (iFile == null)
      return null;
    IModelManager manager = getModelManager();
    if (manager == null)
      return null;

    IStructuredModel model = null;
    try {
      model = manager.getNewModelForEdit(iFile, false);
    }
    catch (IOException ex) {
    }
    catch (ResourceInUse riu) {
    }
    catch (ResourceAlreadyExists rae) {
    }
    catch (CoreException ce) {
    }
    return model;
  }

  /**
   * Utility to check the model is HTML family or not
   */
  static private boolean isHTMLFamily(IStructuredModel model) {
    if (model instanceof IDOMModel) {
      IDOMDocument document = ((IDOMModel) model).getDocument();
      DocumentTypeAdapter adapter = (DocumentTypeAdapter) document.getAdapterFor(DocumentTypeAdapter.class);
      if (adapter != null)
        return adapter.hasFeature(HTMLDocumentTypeConstants.HTML);
    }
    return false;
  }

  /**
   * <code>baseModel</code>: the model containing the link
   * <code>ref</code>: the link URL string
   * <code>resolveCrossProjectLinks</code>: If resolveCrossProjectLinks
   * is set to true, then this method will properly resolve the URI if it is
   * a valid URI pointing to another (appropriate) project.
   */
  public static String resolveURI(IStructuredModel baseModel, String ref, boolean resolveCrossProjectLinks) {
    if (baseModel == null)
      return null;
    // for HTML, 'href' attribute value of BASE element
    // should be used, if exists any
    String baseHref = null;
    // dmw_TODO needs to be changed to handle a content model
    // of HTML or XHTML
    if (isHTMLFamily(baseModel)) {
      final IDOMModel xmlmodel = (IDOMModel) baseModel;
      final IDOMDocument doc = xmlmodel.getDocument();
      // look for <BASE> w/ href
      final NodeList nl = doc.getElementsByTagName("BASE");//$NON-NLS-1$
      if ((nl != null) && (nl.getLength() > 0)) {
        // per each <BASE>
        for (int i = 0; i < nl.getLength(); i++) {
          final Node baseNode = nl.item(i);
          if (baseNode != null) {
            // get all attrs
            final NamedNodeMap attrNodes = baseNode.getAttributes();
            if (attrNodes != null) {
              final Node attrNode = attrNodes.getNamedItem("HREF");//$NON-NLS-1$
              if (attrNode != null) {
                // found href=""
                final String attrValue = attrNode.getNodeValue();
                if (attrValue != null) {
                  baseHref = attrValue.trim();
                }
              }
            }
          }
          // what if there are multiple <BASE> tags ??
          if (baseHref != null) {
            break;
          }
        }
      }
    }

    // get resolver in Model
    final URIResolver resolver = baseModel.getResolver();

    // resolve to absolute url
    final String absurl = (resolver != null) ? ((baseHref != null) ? resolver.getLocationByURI(ref, baseHref, resolveCrossProjectLinks) : resolver.getLocationByURI(ref, resolveCrossProjectLinks)) : null;
    if ((resolver != null) && (absurl == null) && (ref != null) && (ref.trim().length() > 0) && (ref.trim().charAt(0) == '/')) {
      // to reach here means :
      //    ref is a Docroot relative
      //    resolver can't resolve ref
      // so that href is a broken and should not create model
      return null;
    }
    if ((absurl != null) && (absurl.length() > 0)) {
      return absurl;
    }

    // maybe ref is at outside of the Project
    // obtain docroot;
    final IContainer container = (resolver != null) ? resolver.getRootLocation() : null;
    String docroot = null;
    if (container != null) {
      IPath containerLocation = container.getLocation();
      if (containerLocation != null) {
        docroot = containerLocation.toString();
      }
      else if (container.getLocationURI() != null) {
        docroot = container.getLocationURI().toString();
      }
    }
    if (docroot == null) {
      docroot = baseModel.getBaseLocation();
    }
    if (docroot == null) {
      // should not be
      return null;
    }

    // obtain document url
    String modelBaseLocation = baseModel.getBaseLocation();
    if ((modelBaseLocation == null) || (modelBaseLocation.length() == 0)) {
      // fallback...
      modelBaseLocation = baseModel.getId();
    }
    if ((modelBaseLocation == null) || (modelBaseLocation.length() == 0)) {
      // i can't resolve uri !
      return null;
    }

    // resolve url
    URLHelper helper = new URLHelper(PathHelper.getContainingFolderPath(modelBaseLocation), PathHelper.getContainingFolderPath(PathHelper.appendTrailingURLSlash(docroot)));
    return helper.toAbsolute(ref);
  }

}
TOP

Related Classes of org.eclipse.wst.html.core.internal.htmlcss.URLModelProvider

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.