/**
  * Determines if file is jsp fragment or not (does a deep, indepth check, looking into contents of
  * file)
  *
  * @param file assumes file is not null and exists
  * @return true if file is jsp fragment, false otherwise
  */
 private boolean isFragment(IFile file) {
   // copied from JSPValidator
   boolean isFragment = false;
   InputStream is = null;
   try {
     IContentDescription contentDescription = file.getContentDescription();
     // it can be null
     if (contentDescription == null) {
       is = file.getContents();
       contentDescription =
           Platform.getContentTypeManager()
               .getDescriptionFor(
                   is, file.getName(), new QualifiedName[] {IContentDescription.CHARSET});
     }
     if (contentDescription != null) {
       String fileCtId = contentDescription.getContentType().getId();
       isFragment =
           (fileCtId != null && ContentTypeIdForJSP.ContentTypeID_JSPFRAGMENT.equals(fileCtId));
     }
   } catch (IOException e) {
     // ignore, assume it's invalid JSP
   } catch (CoreException e) {
     // ignore, assume it's invalid JSP
   } finally {
     // must close input stream in case others need it
     if (is != null)
       try {
         is.close();
       } catch (Exception e) {
         // not sure how to recover at this point
       }
   }
   return isFragment;
 }
 @Override
 public void setInitializationData(
     final IConfigurationElement config, final String propertyName, final Object data)
     throws CoreException {
   if (data instanceof Map) {
     try {
       final Map<String, String> parameters = (Map<String, String>) data;
       {
         final String s = parameters.get(ActionUtil.CONTENT_TYPE_PAR_NAME);
         if (s != null) {
           this.util.setContentType(Platform.getContentTypeManager().getContentType(s));
         }
       }
       {
         final String s = parameters.get(ActionUtil.LAUNCH_FLAGS_PAR_NAME);
         if (s != null) {
           this.launchFlags = CollectionUtils.toIdentifierSet(s.split(";")); // $NON-NLS-1$
         }
       }
     } catch (final IllegalArgumentException e) {
       throw new CoreException(
           new Status(
               IStatus.ERROR,
               DocBaseUI.PLUGIN_ID,
               0,
               NLS.bind(
                   "Invalid declaration of contribution by ''{0}''.", //$NON-NLS-1$
                   config.getContributor().getName()),
               e));
     }
   }
 }
  public void testContentTypeLookup() {
    IContentTypeManager global = Platform.getContentTypeManager();
    final SingleNodeScope scope = new SingleNodeScope();
    IContentTypeMatcher local = global.getMatcher(new LocalSelectionPolicy(), scope);
    IContentType textContentType = global.getContentType(Platform.PI_RUNTIME + '.' + "text");
    try {
      // added "<test case name>.global" to the text content type as a global file spec
      textContentType.addFileSpec(getName() + ".global", IContentType.FILE_NAME_SPEC);
    } catch (CoreException e) {
      fail("0.1", e);
    }
    try {
      // added "<test case name>.local" to the text content type as a local (scope-specific) file
      // spec
      textContentType
          .getSettings(scope)
          .addFileSpec(getName() + ".local", IContentType.FILE_NAME_SPEC);
    } catch (CoreException e) {
      fail("0.2", e);
    }
    // make ensure associations are properly recognized when doing content type lookup
    assertEquals("1.0", textContentType, global.findContentTypeFor(getName() + ".global"));
    assertEquals("1.1", null, local.findContentTypeFor(getName() + ".global"));
    assertEquals("2.0", textContentType, local.findContentTypeFor(getName() + ".local"));
    assertEquals("2.1", null, global.findContentTypeFor(getName() + ".local"));

    try {
      textContentType.removeFileSpec(getName() + ".global", IContentType.FILE_NAME_SPEC);
    } catch (CoreException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
 public void testIsAssociatedWith() {
   IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
   final SingleNodeScope scope = new SingleNodeScope();
   IContentType textContentType =
       contentTypeManager.getContentType(Platform.PI_RUNTIME + '.' + "text");
   IContentTypeSettings localSettings = null;
   try {
     localSettings = textContentType.getSettings(scope);
   } catch (CoreException e) {
     fail("0.1", e);
   }
   // haven't added association yet
   assertTrue("1.0", !textContentType.isAssociatedWith("hello.foo", scope));
   assertTrue("1.1", !textContentType.isAssociatedWith("hello.foo"));
   try {
     // associate at the scope level
     localSettings.addFileSpec("foo", IContentType.FILE_EXTENSION_SPEC);
   } catch (CoreException e) {
     fail("1.5", e);
   }
   try {
     localSettings = textContentType.getSettings(scope);
   } catch (CoreException e) {
     fail("2.1", e);
   }
   // scope-specific settings should contain the filespec we just added
   String[] fileSpecs = localSettings.getFileSpecs(IContentType.FILE_EXTENSION_SPEC);
   assertEquals("2.2", 1, fileSpecs.length);
   assertEquals("2.3", "foo", fileSpecs[0]);
   // now it is associated at the scope level...
   assertTrue("2.5", textContentType.isAssociatedWith("hello.foo", scope));
   // ...but not at the global level
   assertTrue("2.6", !textContentType.isAssociatedWith("hello.foo"));
 }
  public IStructuredFormatProcessor getFormatProcessor(String contentTypeId) {
    if (contentTypeId == null) return null;

    IStructuredFormatProcessor formatProcessor = null;
    if (map.containsKey(contentTypeId)) {
      formatProcessor = (IStructuredFormatProcessor) map.get(contentTypeId);
    } else {
      IContentTypeManager manager = Platform.getContentTypeManager();
      IContentType queryContentType = manager.getContentType(contentTypeId);
      boolean found = false;
      for (Iterator iter = map.keySet().iterator(); iter.hasNext(); ) {
        String elementContentTypeId = (String) iter.next();
        IContentType elementContentType = manager.getContentType(elementContentTypeId);
        if (queryContentType.isKindOf(elementContentType)) {
          formatProcessor = (IStructuredFormatProcessor) map.get(elementContentTypeId);
          map.put(contentTypeId, formatProcessor);
          found = true;
          break;
        }
      }

      if (!found) map.put(contentTypeId, null);
    }

    return formatProcessor;
  }
  /**
   * Returns the appropriate IOpenOn for the current partition
   *
   * @return
   */
  public IOpenOn getOpenOn(IDocument document, int offset) {
    IOpenOn openOn = null;

    // determine the current partition
    if (document != null) {
      String contentTypeID = getContentType(document);
      String partitionType = getPartitionType(document, offset);

      IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeID);

      while (openOn == null && contentType != null) {
        // Query OpenOnBuilder and get the list of OpenOns for the
        // current partition
        OpenOnDefinition[] defs =
            OpenOnBuilder.getInstance().getOpenOnDefinitions(contentType.getId(), partitionType);
        contentType = contentType.getBaseType();

        // If more than 1 openon is returned, need to further check
        // which OpenOn is the appropriate one to return
        // for now just returning the first one
        if (defs != null && defs.length > 0) {
          openOn = defs[0].createOpenOn();
        }
      }
    }

    return openOn;
  }
  /**
   * Get the folding strategy for this processor. Retrieved from the extended configuration builder.
   * The processor chosen is set by the plugin.
   *
   * <p>EX:<br>
   * <code>&lt;extension point="org.eclipse.wst.sse.ui.editorConfiguration"&gt;<br />
   *  &lt;provisionalConfiguration<br />
   * 		type="foldingstrategy"<br />
   * 		class="org.eclipse.wst.xml.ui.internal.projection.XMLFoldingStrategy"<br />
   * 		target="org.eclipse.core.runtime.xml, org.eclipse.wst.xml.core.xmlsource" /&gt;<br />
   * &lt;/extension&gt;</code>
   *
   * <p>The type must be equal to <code>AbstractFoldingStrategy.ID</code> (AKA: foldingstrategy) and
   * the class must extend <code>org.eclipse.wst.sse.ui.internal.projection.AbstractFoldingStrategy
   * </code> and the target must be a structured editor content type ID
   *
   * @return the requested folding strategy or null if none can be found
   */
  protected IReconcilingStrategy getFoldingStrategy() {
    if (fFoldingStrategy == null && getDocument() != null) {
      String contentTypeId = getContentType(getDocument());
      if (contentTypeId == null) {
        contentTypeId = IContentTypeManager.CT_TEXT;
      }

      ITextViewer viewer = getTextViewer();
      if (viewer instanceof ProjectionViewer) {
        ExtendedConfigurationBuilder builder = ExtendedConfigurationBuilder.getInstance();

        IContentType type = Platform.getContentTypeManager().getContentType(contentTypeId);
        while (fFoldingStrategy == null && type != null) {
          fFoldingStrategy =
              (AbstractStructuredFoldingStrategy)
                  builder.getConfiguration(AbstractStructuredFoldingStrategy.ID, type.getId());

          type = type.getBaseType();
        }

        if (fFoldingStrategy != null) {
          fFoldingStrategy.setViewer((ProjectionViewer) viewer);
          fFoldingStrategy.setDocument(getDocument());
        }
      }
    }

    return fFoldingStrategy;
  }
  private void checkEncodedContents2(String expectedEncoding, String encodingInContent)
      throws Exception {
    boolean[][] flags = {
      {true, true, false},
      {true, false, false},
      {false, true, false},
      {false, false, false},
      {true, true, true},
      {true, false, true},
      {false, true, true},
      {false, false, true}
    };

    IContentDescription description = null;
    for (int i = 0; i < flags.length; i++) {
      description =
          Platform.getContentTypeManager()
              .getDescriptionFor(
                  getReader(encodingInContent, flags[i][0], flags[i][1], flags[i][2]),
                  "fake.xml",
                  new QualifiedName[] {IContentDescription.CHARSET});
      assertNotNull("1.0: " + flags[i][0] + " " + flags[i][1] + " " + flags[i][2], description);
      assertEquals(
          "1.1: " + flags[i], Platform.PI_RUNTIME + ".xml", description.getContentType().getId());
      assertEquals(
          "1.2: " + flags[i],
          expectedEncoding,
          description.getProperty(IContentDescription.CHARSET));
    }
  }
Ejemplo n.º 9
0
 @Override
 public String getCharsetFor(Reader contents) throws CoreException {
   String charset;
   ResourceInfo info = getResourceInfo(false, false);
   int flags = getFlags(info);
   if (exists(flags, true))
     // the file exists, look for user setting
     if ((charset = workspace.getCharsetManager().getCharsetFor(getFullPath(), false)) != null)
       // if there is a file-specific user setting, use it
       return charset;
   // tries to obtain a description from the contents provided
   IContentDescription description;
   try {
     // TODO need to take project specific settings into account
     IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
     description =
         contentTypeManager.getDescriptionFor(
             contents, getName(), new QualifiedName[] {IContentDescription.CHARSET});
   } catch (IOException e) {
     String message = NLS.bind(Messages.resources_errorContentDescription, getFullPath());
     throw new ResourceException(
         IResourceStatus.FAILED_DESCRIBING_CONTENTS, getFullPath(), message, e);
   }
   if (description != null)
     if ((charset = description.getCharset()) != null)
       // the description contained charset info, we are done
       return charset;
   // could not find out the encoding based on the contents... default to parent's
   return workspace.getCharsetManager().getCharsetFor(getFullPath().removeLastSegments(1), true);
 }
Ejemplo n.º 10
0
 public void setInitializationData(IConfigurationElement config, String propertyName, Object data)
     throws CoreException {
   String pattern = config.getAttribute("pattern"); // $NON-NLS-1$
   if (pattern != null) {
     IContentType newcontentType = Platform.getContentTypeManager().getContentType(pattern);
     if (newcontentType != null) contentType = newcontentType;
   }
 }
 /**
  * Returns JSP fragment content type
  *
  * @return jspf content type
  */
 private IContentType getJSPFContentType() {
   // copied from JSPValidator
   if (fJSPFContentType == null) {
     fJSPFContentType =
         Platform.getContentTypeManager()
             .getContentType(ContentTypeIdForJSP.ContentTypeID_JSPFRAGMENT);
   }
   return fJSPFContentType;
 }
Ejemplo n.º 12
0
 public static boolean isErlangFileContentFileName(final String fileName) {
   final IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
   final IContentType[] contentTypes = contentTypeManager.findContentTypesFor(fileName);
   for (final IContentType contentType : contentTypes) {
     if (contentType.getId().equals("org.erlide.core.content.erlang")) {
       return true;
     }
   }
   return false;
 }
  public void testBug258208() throws Exception {
    IContentDescription description =
        Platform.getContentTypeManager()
            .getDescriptionFor(
                getInputStream(ENCODING_EMPTY, ENCODING_UTF8, false, true, false),
                "fake.xml",
                new QualifiedName[] {IContentDescription.CHARSET});
    assertNull("1.0", description);

    // empty charset should not disable the xml content type
    checkEncodedContents(ENCODING_UTF16, ENCODING_UTF16, ENCODING_UTF16);
  }
Ejemplo n.º 14
0
 static {
   IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
   if (contentTypeManager != null) {
     contentTypeManager.addContentTypeChangeListener(
         new IContentTypeManager.IContentTypeChangeListener() {
           public void contentTypeChanged(ContentTypeChangeEvent event) {
             // we can be more specific here, but content types change so rarely, that
             // I am not concerned about being overly eager to invalidate the cache
             GROOVY_FILE_NAMES = null;
             GROOVY_LIKE_EXTENSIONS = null;
             JAVA_LIKE_BUT_NOT_GROOVY_LIKE_EXTENSIONS = null;
           }
         });
   }
 }
Ejemplo n.º 15
0
 private static Set<String> loadGroovyFileNames() {
   IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
   if (contentTypeManager != null) {
     Set<String> names = null;
     IContentType groovyContentType =
         contentTypeManager.getContentType(GROOVY_SOURCE_CONTENT_TYPE);
     for (IContentType contentType : contentTypeManager.getAllContentTypes()) {
       if (contentType.isKindOf(groovyContentType)) {
         for (String fileName : contentType.getFileSpecs(IContentType.FILE_NAME_SPEC)) {
           if (names == null) names = new TreeSet<String>();
           names.add(fileName);
         }
       }
     }
     if (names != null) return names;
   }
   return Collections.emptySet();
 }
  protected String getContentType(IDocument doc) {
    if (doc == null) return null;

    String contentTypeId = null;

    IContentType ct = null;
    try {
      IContentDescription desc =
          Platform.getContentTypeManager()
              .getDescriptionFor(new StringReader(doc.get()), null, IContentDescription.ALL);
      if (desc != null) {
        ct = desc.getContentType();
        if (ct != null) contentTypeId = ct.getId();
      }
    } catch (IOException e) {
      // just bail
    }
    return contentTypeId;
  }
Ejemplo n.º 17
0
 private static Set<String> loadGroovyFileExtensions() {
   IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
   if (contentTypeManager != null) {
     IContentType groovyContentType =
         contentTypeManager.getContentType(GROOVY_SOURCE_CONTENT_TYPE);
     Set<String> extensions = new HashSet<String>();
     // https://bugs.eclipse.org/bugs/show_bug.cgi?id=121715
     // content types derived from groovy content type should be included
     for (IContentType contentType : contentTypeManager.getAllContentTypes()) {
       if (contentType.isKindOf(
           groovyContentType)) { // note that contentType.isKindOf(javaContentType) == true
         for (String fileExtension : contentType.getFileSpecs(IContentType.FILE_EXTENSION_SPEC)) {
           extensions.add(fileExtension);
         }
       }
     }
     return extensions;
   }
   return Collections.singleton("groovy");
 }
  private EncodingMemento checkForEncodingInContents() throws CoreException, IOException {
    EncodingMemento result = null;

    // if encoding memento already set, and no need to get again.
    if (fEncodingMemento != null) {
      result = fEncodingMemento;
    } else {
      if (fClientSuppliedReader) {
        fReader.reset();
        IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
        try {
          IContentDescription contentDescription =
              contentTypeManager.getDescriptionFor(fReader, fFilename, IContentDescription.ALL);
          if (contentDescription != null) {
            fEncodingMemento = createMemento(contentDescription);
          } else {
            fEncodingMemento = CodedIO.createEncodingMemento("UTF-8"); // $NON-NLS-1$
          }
        } catch (NullPointerException e) {
          // TODO: work around for 5/14 bug in base, should be
          // removed when move up to 5/21
          // just created a simple default one
          fEncodingMemento = CodedIO.createEncodingMemento("UTF-8"); // $NON-NLS-1$
        }
        result = fEncodingMemento;
      } else {
        throw new IllegalStateException(
            "unexpected state: encodingMemento was null but no input stream supplied"); //$NON-NLS-1$
      }
    }
    //		try {
    //			result = getEncodingDetector().getEncodingMemento();
    //			if (result != null && !result.isValid() && !forceDefault()) {
    //				throw new UnsupportedCharsetExceptionWithDetail(result);
    //			}
    //		}
    //		finally {
    //			handleStreamClose(fEncodingDetectorStream);
    //		}
    return result;
  }
Ejemplo n.º 19
0
    @Override
    public Set<IContentType> getAssociatedTypes() {
      IConfigurationElement[] children = conf.getChildren("contentType");

      if (children != null) {
        Set<IContentType> result = new HashSet<IContentType>();

        for (IConfigurationElement child : children) {
          String id = child.getAttribute("ref");
          IContentType ct = Platform.getContentTypeManager().getContentType(id);
          if (ct != null) {
            result.add(ct);
          } else {
            log.error(
                MessageFormat.format("Content type with ID {0} not known by the platform", id));
          }
        }

        return result;
      } else {
        return Collections.emptySet();
      }
    }
 protected IContentType getContentType() {
   return Platform.getContentTypeManager().getContentType(ContentTypeIdForHTML.ContentTypeID_HTML);
 }
Ejemplo n.º 21
0
 /**
  * Adds the content type with the given ID, if one exists, to the list of permitted content types.
  *
  * @param contentType the ID of a content type known to Eclipse
  * @see #addContentType(IContentType)
  */
 public void addContentType(String contentType) {
   addContentType(Platform.getContentTypeManager().getContentType(contentType));
 }
  public void testEncodedContents3() throws Exception {
    boolean[][] flags = {
      {true, true, false},
      {true, false, false},
      {false, true, false},
      {false, false, false},
      {true, true, true},
      {true, false, true},
      {false, true, true},
      {false, false, true}
    };

    IContentDescription description = null;
    for (int i = 0; i < flags.length; i++) {
      description =
          Platform.getContentTypeManager()
              .getDescriptionFor(
                  getInputStream(
                      ENCODING_INCORRECT, ENCODING_UTF8, flags[i][0], flags[i][1], flags[i][2]),
                  "fake.xml",
                  new QualifiedName[] {IContentDescription.CHARSET});
      assertNull("1.0", description);

      description =
          Platform.getContentTypeManager()
              .getDescriptionFor(
                  getInputStream(
                      ENCODING_INCORRECT, ENCODING_UTF16, flags[i][0], flags[i][1], flags[i][2]),
                  "fake.xml",
                  new QualifiedName[] {IContentDescription.CHARSET});
      assertNull("2.0", description);

      description =
          Platform.getContentTypeManager()
              .getDescriptionFor(
                  getReader(ENCODING_INCORRECT, flags[i][0], flags[i][1], flags[i][2]),
                  "fake.xml",
                  new QualifiedName[] {IContentDescription.CHARSET});
      assertNull("3.0", description);
    }

    for (int i = 0; i < flags.length; i++) {
      description =
          Platform.getContentTypeManager()
              .getDescriptionFor(
                  getInputStream(
                      ENCODING_EMPTY, ENCODING_UTF8, flags[i][0], flags[i][1], flags[i][2]),
                  "fake.xml",
                  new QualifiedName[] {IContentDescription.CHARSET});
      assertNull("1.0", description);

      description =
          Platform.getContentTypeManager()
              .getDescriptionFor(
                  getInputStream(
                      ENCODING_EMPTY, ENCODING_UTF16, flags[i][0], flags[i][1], flags[i][2]),
                  "fake.xml",
                  new QualifiedName[] {IContentDescription.CHARSET});
      assertNull("2.0", description);

      description =
          Platform.getContentTypeManager()
              .getDescriptionFor(
                  getReader(ENCODING_EMPTY, flags[i][0], flags[i][1], flags[i][2]),
                  "fake.xml",
                  new QualifiedName[] {IContentDescription.CHARSET});
      assertNull("3.0", description);
    }
  }
public class SpellingValidator extends TaskJavaValidator {

  private final class DocumentResolver implements Runnable {
    private final Content content;
    private IXtextDocument document;

    private DocumentResolver(Content content) {
      this.content = content;
    }

    public void run() {
      Resource resource = content.eResource();
      if (resource == null) {
        return;
      }
      IFile file = getFile(resource.getURI());
      if (file == null) {
        return;
      }
      document = XtextDocumentUtil.get(file);
    }
  }

  private static final IContentType TEXT_CONTENT_TYPE =
      Platform.getContentTypeManager().getContentType(IContentTypeManager.CT_TEXT);

  private SpellingService spellingService;

  @Check
  public void checkSpelling(Task task) {
    doCheckSpelling(task);
  }

  @Check
  public void checkSpelling(Project task) {
    doCheckSpelling(task);
  }

  @Check
  public void checkSpelling(Note task) {
    doCheckSpelling(task);
  }

  private void doCheckSpelling(final Content content) {

    IDocument document = document(content);
    if (document != null) {
      ISpellingProblemCollector collector =
          new ISpellingProblemCollector() {

            public void endCollecting() {}

            public void beginCollecting() {}

            public void accept(SpellingProblem problem) {
              getMessageAcceptor()
                  .acceptWarning(
                      problem.getMessage(),
                      content,
                      problem.getOffset(),
                      problem.getLength(),
                      null,
                      new String[0]);
            }
          };
      spellingService()
          .check(document, regionOf(content), newContext(), collector, new NullProgressMonitor());
    }
  }

  private IRegion[] regionOf(Content content) {
    ICompositeNode node = NodeModelUtils.getNode(content);
    int length = node.getLength();
    int offset = node.getOffset();
    return new Region[] {new Region(offset, length)};
  }

  private SpellingService spellingService() {
    if (spellingService == null) {
      IPreferenceStore preferenceStore = EditorsPlugin.getDefault().getPreferenceStore();
      spellingService = new SpellingService(preferenceStore);
    }
    return spellingService;
  }

  private SpellingContext newContext() {
    SpellingContext context = new SpellingContext();
    context.setContentType(TEXT_CONTENT_TYPE);
    return context;
  }

  private IDocument document(final Content content) {
    DocumentResolver resolver = new DocumentResolver(content);
    Display.getDefault().syncExec(resolver);
    return resolver.document;
  }

  public static IFile getFile(URI uri) {
    if (uri == null) {
      return null;
    }

    String platformString = uri.toPlatformString(true);
    if (platformString == null) {
      return null;
    }

    return ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(platformString));
  }
}
/**
 * The Compare UI plug-in defines the entry point to initiate a configurable compare operation on
 * arbitrary resources. The result of the compare is opened into a compare editor where the details
 * can be browsed and edited in dynamically selected structure and content viewers.
 *
 * <p>The Compare UI provides a registry for content and structure compare viewers, which is
 * initialized from extensions contributed to extension points declared by this plug-in.
 *
 * <p>This class is the plug-in runtime class for the <code>"org.eclipse.compare"</code> plug-in.
 */
public final class CompareUIPlugin extends AbstractUIPlugin {

  static class CompareRegistry {

    private static final String ID_ATTRIBUTE = "id"; // $NON-NLS-1$
    private static final String EXTENSIONS_ATTRIBUTE = "extensions"; // $NON-NLS-1$
    private static final String CONTENT_TYPE_ID_ATTRIBUTE = "contentTypeId"; // $NON-NLS-1$

    private HashMap fIdMap; // maps ids to data
    private HashMap fExtensionMap; // multimap: maps extensions to list of data
    private HashMap fContentTypeBindings; // multimap: maps content type bindings to list of data

    void register(IConfigurationElement element, Object data) {
      String id = element.getAttribute(ID_ATTRIBUTE);
      if (id != null) {
        if (fIdMap == null) fIdMap = new HashMap();
        fIdMap.put(id, data);
      }

      String types = element.getAttribute(EXTENSIONS_ATTRIBUTE);
      if (types != null) {
        if (fExtensionMap == null) fExtensionMap = new HashMap();
        StringTokenizer tokenizer = new StringTokenizer(types, ","); // $NON-NLS-1$
        while (tokenizer.hasMoreElements()) {
          String extension = tokenizer.nextToken().trim();
          List l = (List) fExtensionMap.get(normalizeCase(extension));
          if (l == null) fExtensionMap.put(normalizeCase(extension), l = new ArrayList());
          l.add(data);
        }
      }
    }

    void createBinding(IConfigurationElement element, String idAttributeName) {
      String type = element.getAttribute(CONTENT_TYPE_ID_ATTRIBUTE);
      String id = element.getAttribute(idAttributeName);
      if (id == null)
        logErrorMessage(
            Utilities.getFormattedString(
                "CompareUIPlugin.targetIdAttributeMissing", idAttributeName)); // $NON-NLS-1$
      if (type != null && id != null && fIdMap != null) {
        Object o = fIdMap.get(id);
        if (o != null) {
          IContentType ct = fgContentTypeManager.getContentType(type);
          if (ct != null) {
            if (fContentTypeBindings == null) fContentTypeBindings = new HashMap();
            List l = (List) fContentTypeBindings.get(ct);
            if (l == null) fContentTypeBindings.put(ct, l = new ArrayList());
            l.add(o);
          } else {
            logErrorMessage(
                Utilities.getFormattedString(
                    "CompareUIPlugin.contentTypeNotFound", type)); // $NON-NLS-1$
          }
        } else {
          logErrorMessage(
              Utilities.getFormattedString("CompareUIPlugin.targetNotFound", id)); // $NON-NLS-1$
        }
      }
    }

    Object search(IContentType type) {
      List list = searchAll(type);
      return list != null ? list.get(0) : null;
    }

    List searchAll(IContentType type) {
      if (fContentTypeBindings != null) {
        for (; type != null; type = type.getBaseType()) {
          List data = (List) fContentTypeBindings.get(type);
          if (data != null) return data;
        }
      }
      return null;
    }

    Object search(String extension) {
      List list = searchAll(extension);
      return list != null ? list.get(0) : null;
    }

    List searchAll(String extension) {
      if (fExtensionMap != null) return (List) fExtensionMap.get(normalizeCase(extension));
      return null;
    }
  }

  /** Status code describing an internal error */
  public static final int INTERNAL_ERROR = 1;

  private static boolean NORMALIZE_CASE = true;

  public static final String PLUGIN_ID = "org.eclipse.compare"; // $NON-NLS-1$

  private static final String BINARY_TYPE = "binary"; // $NON-NLS-1$

  private static final String STREAM_MERGER_EXTENSION_POINT = "streamMergers"; // $NON-NLS-1$
  private static final String STREAM_MERGER = "streamMerger"; // $NON-NLS-1$
  private static final String STREAM_MERGER_ID_ATTRIBUTE = "streamMergerId"; // $NON-NLS-1$
  private static final String STRUCTURE_CREATOR_EXTENSION_POINT =
      "structureCreators"; //$NON-NLS-1$
  private static final String STRUCTURE_CREATOR = "structureCreator"; // $NON-NLS-1$
  private static final String STRUCTURE_CREATOR_ID_ATTRIBUTE = "structureCreatorId"; // $NON-NLS-1$

  private static final String VIEWER_TAG = "viewer"; // $NON-NLS-1$
  private static final String STRUCTURE_MERGE_VIEWER_EXTENSION_POINT =
      "structureMergeViewers"; //$NON-NLS-1$
  private static final String STRUCTURE_MERGE_VIEWER_ID_ATTRIBUTE =
      "structureMergeViewerId"; //$NON-NLS-1$
  private static final String CONTENT_MERGE_VIEWER_EXTENSION_POINT =
      "contentMergeViewers"; //$NON-NLS-1$
  private static final String CONTENT_MERGE_VIEWER_ID_ATTRIBUTE =
      "contentMergeViewerId"; //$NON-NLS-1$
  private static final String CONTENT_VIEWER_EXTENSION_POINT = "contentViewers"; // $NON-NLS-1$
  private static final String CONTENT_VIEWER_ID_ATTRIBUTE = "contentViewerId"; // $NON-NLS-1$

  private static final String CONTENT_TYPE_BINDING = "contentTypeBinding"; // $NON-NLS-1$

  private static final String COMPARE_EDITOR = PLUGIN_ID + ".CompareEditor"; // $NON-NLS-1$

  private static final String STRUCTUREVIEWER_ALIASES_PREFERENCE_NAME =
      "StructureViewerAliases"; //$NON-NLS-1$

  // content type
  private static final IContentTypeManager fgContentTypeManager = Platform.getContentTypeManager();

  public static final int NO_DIFFERENCE = 10000;

  /** The plugin singleton. */
  private static CompareUIPlugin fgComparePlugin;

  /** Maps type to icons */
  private static Map fgImages = new Hashtable(10);
  /** Maps type to ImageDescriptors */
  private static Map fgImageDescriptors = new Hashtable(10);
  /** Maps ImageDescriptors to Images */
  private static Map fgImages2 = new Hashtable(10);

  private static List fgDisposeOnShutdownImages = new ArrayList();

  private ResourceBundle fResourceBundle;

  private boolean fRegistriesInitialized;
  private CompareRegistry fStreamMergers = new CompareRegistry();
  private CompareRegistry fStructureCreators = new CompareRegistry();
  private CompareRegistry fStructureMergeViewers = new CompareRegistry();
  private CompareRegistry fContentViewers = new CompareRegistry();
  private CompareRegistry fContentMergeViewers = new CompareRegistry();

  private Map fStructureViewerAliases;
  private CompareFilter fFilter;
  private IPropertyChangeListener fPropertyChangeListener;

  /**
   * Creates the <code>CompareUIPlugin</code> object and registers all structure creators, content
   * merge viewers, and structure merge viewers contributed to this plug-in's extension points.
   *
   * <p>Note that instances of plug-in runtime classes are automatically created by the platform in
   * the course of plug-in activation.
   */
  public CompareUIPlugin() {
    super();
    Assert.isTrue(fgComparePlugin == null);
    fgComparePlugin = this;
  }

  public void start(BundleContext context) throws Exception {
    super.start(context);
  }

  public void stop(BundleContext context) throws Exception {

    IPreferenceStore ps = getPreferenceStore();
    rememberAliases(ps);
    if (fPropertyChangeListener != null) {
      ps.removePropertyChangeListener(fPropertyChangeListener);
      fPropertyChangeListener = null;
    }

    super.stop(context);

    if (fgDisposeOnShutdownImages != null) {
      Iterator i = fgDisposeOnShutdownImages.iterator();
      while (i.hasNext()) {
        Image img = (Image) i.next();
        if (!img.isDisposed()) img.dispose();
      }
      fgImages = null;
    }
  }

  /**
   * Returns the singleton instance of this plug-in runtime class.
   *
   * @return the compare plug-in instance
   */
  public static CompareUIPlugin getDefault() {
    return fgComparePlugin;
  }

  /**
   * Returns this plug-in's resource bundle.
   *
   * @return the plugin's resource bundle
   */
  public ResourceBundle getResourceBundle() {
    if (fResourceBundle == null) fResourceBundle = Platform.getResourceBundle(getBundle());
    return fResourceBundle;
  }

  /**
   * Returns this plug-in's unique identifier.
   *
   * @return the plugin's unique identifier
   */
  public static String getPluginId() {
    return getDefault().getBundle().getSymbolicName();
  }

  private void initializeRegistries() {
    if (!fRegistriesInitialized) {
      registerExtensions();
      fRegistriesInitialized = true;
    }
  }

  /**
   * Registers all stream mergers, structure creators, content merge viewers, and structure merge
   * viewers that are found in the XML plugin files.
   */
  private void registerExtensions() {
    IExtensionRegistry registry = Platform.getExtensionRegistry();

    // collect all IStreamMergers
    IConfigurationElement[] elements =
        registry.getConfigurationElementsFor(PLUGIN_ID, STREAM_MERGER_EXTENSION_POINT);
    for (int i = 0; i < elements.length; i++) {
      IConfigurationElement element = elements[i];
      if (STREAM_MERGER.equals(element.getName()))
        fStreamMergers.register(element, new StreamMergerDescriptor(element));
    }
    for (int i = 0; i < elements.length; i++) {
      IConfigurationElement element = elements[i];
      if (CONTENT_TYPE_BINDING.equals(element.getName()))
        fStreamMergers.createBinding(element, STREAM_MERGER_ID_ATTRIBUTE);
    }

    // collect all IStructureCreators
    elements = registry.getConfigurationElementsFor(PLUGIN_ID, STRUCTURE_CREATOR_EXTENSION_POINT);
    for (int i = 0; i < elements.length; i++) {
      IConfigurationElement element = elements[i];
      String name = element.getName();
      if (!CONTENT_TYPE_BINDING.equals(name)) {
        if (!STRUCTURE_CREATOR.equals(name))
          logErrorMessage(
              Utilities.getFormattedString(
                  "CompareUIPlugin.unexpectedTag",
                  name,
                  STRUCTURE_CREATOR)); //$NON-NLS-1$
        fStructureCreators.register(element, new StructureCreatorDescriptor(element));
      }
    }
    for (int i = 0; i < elements.length; i++) {
      IConfigurationElement element = elements[i];
      if (CONTENT_TYPE_BINDING.equals(element.getName()))
        fStructureCreators.createBinding(element, STRUCTURE_CREATOR_ID_ATTRIBUTE);
    }

    // collect all viewers which define the structure merge viewer extension point
    elements =
        registry.getConfigurationElementsFor(PLUGIN_ID, STRUCTURE_MERGE_VIEWER_EXTENSION_POINT);
    for (int i = 0; i < elements.length; i++) {
      IConfigurationElement element = elements[i];
      String name = element.getName();
      if (!CONTENT_TYPE_BINDING.equals(name)) {
        if (!VIEWER_TAG.equals(name))
          logErrorMessage(
              Utilities.getFormattedString(
                  "CompareUIPlugin.unexpectedTag", name, VIEWER_TAG)); // $NON-NLS-1$		
        fStructureMergeViewers.register(element, new ViewerDescriptor(element));
      }
    }
    for (int i = 0; i < elements.length; i++) {
      IConfigurationElement element = elements[i];
      if (CONTENT_TYPE_BINDING.equals(element.getName()))
        fStructureMergeViewers.createBinding(element, STRUCTURE_MERGE_VIEWER_ID_ATTRIBUTE);
    }

    // collect all viewers which define the content merge viewer extension point
    elements =
        registry.getConfigurationElementsFor(PLUGIN_ID, CONTENT_MERGE_VIEWER_EXTENSION_POINT);
    for (int i = 0; i < elements.length; i++) {
      IConfigurationElement element = elements[i];
      String name = element.getName();
      if (!CONTENT_TYPE_BINDING.equals(name)) {
        if (!VIEWER_TAG.equals(name))
          logErrorMessage(
              Utilities.getFormattedString(
                  "CompareUIPlugin.unexpectedTag", name, VIEWER_TAG)); // $NON-NLS-1$		
        fContentMergeViewers.register(element, new ViewerDescriptor(element));
      }
    }
    for (int i = 0; i < elements.length; i++) {
      IConfigurationElement element = elements[i];
      if (CONTENT_TYPE_BINDING.equals(element.getName()))
        fContentMergeViewers.createBinding(element, CONTENT_MERGE_VIEWER_ID_ATTRIBUTE);
    }

    // collect all viewers which define the content viewer extension point
    elements = registry.getConfigurationElementsFor(PLUGIN_ID, CONTENT_VIEWER_EXTENSION_POINT);
    for (int i = 0; i < elements.length; i++) {
      IConfigurationElement element = elements[i];
      String name = element.getName();
      if (!CONTENT_TYPE_BINDING.equals(name)) {
        if (!VIEWER_TAG.equals(name))
          logErrorMessage(
              Utilities.getFormattedString(
                  "CompareUIPlugin.unexpectedTag", name, VIEWER_TAG)); // $NON-NLS-1$		
        fContentViewers.register(element, new ViewerDescriptor(element));
      }
    }
    for (int i = 0; i < elements.length; i++) {
      IConfigurationElement element = elements[i];
      if (CONTENT_TYPE_BINDING.equals(element.getName()))
        fContentViewers.createBinding(element, CONTENT_VIEWER_ID_ATTRIBUTE);
    }
  }

  public static IWorkbench getActiveWorkbench() {
    CompareUIPlugin plugin = getDefault();
    if (plugin == null) return null;
    return plugin.getWorkbench();
  }

  public static IWorkbenchWindow getActiveWorkbenchWindow() {
    IWorkbench workbench = getActiveWorkbench();
    if (workbench == null) return null;
    return workbench.getActiveWorkbenchWindow();
  }

  /**
   * Returns the active workbench page or <code>null</code> if no active workbench page can be
   * determined.
   *
   * @return the active workbench page or <code>null</code> if no active workbench page can be
   *     determined
   */
  private static IWorkbenchPage getActivePage() {
    IWorkbenchWindow window = getActiveWorkbenchWindow();
    if (window == null) return null;
    return window.getActivePage();
  }

  /**
   * Returns the SWT Shell of the active workbench window or <code>null</code> if no workbench
   * window is active.
   *
   * @return the SWT Shell of the active workbench window, or <code>null</code> if no workbench
   *     window is active
   */
  public static Shell getShell() {
    IWorkbenchWindow window = getActiveWorkbenchWindow();
    if (window == null) return null;
    return window.getShell();
  }

  /**
   * Registers the given image for being disposed when this plug-in is shutdown.
   *
   * @param image the image to register for disposal
   */
  public static void disposeOnShutdown(Image image) {
    if (image != null) fgDisposeOnShutdownImages.add(image);
  }

  /**
   * Performs the comparison described by the given input and opens a compare editor on the result.
   *
   * @param input the input on which to open the compare editor
   * @param page the workbench page on which to create a new compare editor
   * @param editor if not null the input is opened in this editor
   * @param activate if <code>true</code> the editor will be activated
   * @see IWorkbenchPage#openEditor(org.eclipse.ui.IEditorInput, String, boolean)
   * @see CompareEditorInput
   */
  public void openCompareEditor(
      final CompareEditorInput input,
      final IWorkbenchPage page,
      final IReusableEditor editor,
      final boolean activate) {
    CompareConfiguration configuration = input.getCompareConfiguration();
    if (configuration != null) {
      IPreferenceStore ps = configuration.getPreferenceStore();
      if (ps != null)
        configuration.setProperty(
            CompareConfiguration.USE_OUTLINE_VIEW,
            Boolean.valueOf(ps.getBoolean(ComparePreferencePage.USE_OUTLINE_VIEW)));
    }
    if (input.canRunAsJob()) {
      openEditorInBackground(input, page, editor, activate);
    } else {
      if (compareResultOK(input, null)) {
        internalOpenEditor(input, page, editor, activate);
      }
    }
  }

  private void openEditorInBackground(
      final CompareEditorInput input,
      final IWorkbenchPage page,
      final IReusableEditor editor,
      final boolean activate) {
    internalOpenEditor(input, page, editor, activate);
  }

  private void internalOpenEditor(
      final CompareEditorInput input,
      final IWorkbenchPage wp,
      final IReusableEditor editor,
      final boolean activate) {
    Runnable runnable =
        new Runnable() {
          public void run() {
            if (editor != null
                && !editor.getSite().getShell().isDisposed()) { // reuse the given editor
              editor.setInput(input);
              return;
            }

            IWorkbenchPage page = wp;
            if (page == null) page = getActivePage();
            if (page != null) {
              // open new CompareEditor on page
              try {
                page.openEditor(input, COMPARE_EDITOR, activate);
              } catch (PartInitException e) {
                MessageDialog.openError(
                    getShell(),
                    Utilities.getString("CompareUIPlugin.openEditorError"),
                    e.getMessage()); // $NON-NLS-1$
              }
            } else {
              MessageDialog.openError(
                  getShell(),
                  Utilities.getString("CompareUIPlugin.openEditorError"), // $NON-NLS-1$
                  Utilities.getString("CompareUIPlugin.noActiveWorkbenchPage")); // $NON-NLS-1$
            }
          }
        };
    syncExec(runnable);
  }

  /**
   * Performs the comparison described by the given input and opens a compare dialog on the result.
   *
   * @param input the input on which to open the compare editor
   * @see CompareEditorInput
   */
  public void openCompareDialog(final CompareEditorInput input) {
    // We don't ever open dialogs in the background
    if (compareResultOK(input, null)) {
      internalOpenDialog(input);
    }
  }

  public IStatus prepareInput(CompareEditorInput input, IProgressMonitor monitor) {
    try {
      input.run(monitor);
      String message = input.getMessage();
      if (message != null) {
        return new Status(IStatus.ERROR, CompareUIPlugin.PLUGIN_ID, 0, message, null);
      }
      if (input.getCompareResult() == null) {
        return new Status(
            IStatus.ERROR,
            CompareUIPlugin.PLUGIN_ID,
            NO_DIFFERENCE,
            Utilities.getString("CompareUIPlugin.noDifferences"),
            null); //$NON-NLS-1$
      }
      return Status.OK_STATUS;
    } catch (InterruptedException e) {
      throw new OperationCanceledException();
    } catch (InvocationTargetException e) {
      return new Status(
          IStatus.ERROR,
          CompareUIPlugin.PLUGIN_ID,
          0,
          Utilities.getString("CompareUIPlugin.compareFailed"),
          e.getTargetException()); // $NON-NLS-1$
    }
  }

  /*
   * @return <code>true</code> if compare result is OK to show, <code>false</code> otherwise
   */
  public boolean compareResultOK(CompareEditorInput input, IRunnableContext context) {
    final Shell shell = getShell();
    try {

      // run operation in separate thread and make it cancelable
      if (context == null) context = PlatformUI.getWorkbench().getProgressService();
      context.run(true, true, input);

      String message = input.getMessage();
      if (message != null) {
        MessageDialog.openError(
            shell, Utilities.getString("CompareUIPlugin.compareFailed"), message); // $NON-NLS-1$
        return false;
      }

      if (input.getCompareResult() == null) {
        MessageDialog.openInformation(
            shell,
            Utilities.getString("CompareUIPlugin.dialogTitle"),
            Utilities.getString("CompareUIPlugin.noDifferences")); // $NON-NLS-2$ //$NON-NLS-1$
        return false;
      }

      return true;

    } catch (InterruptedException x) {
      // canceled by user
    } catch (InvocationTargetException x) {
      MessageDialog.openError(
          shell,
          Utilities.getString("CompareUIPlugin.compareFailed"),
          x.getTargetException().getMessage()); // $NON-NLS-1$
    }
    return false;
  }

  /*
   * Registers an image for the given type.
   */
  private static void registerImage(String type, Image image, boolean dispose) {
    fgImages.put(normalizeCase(type), image);
    if (image != null && dispose) {
      fgDisposeOnShutdownImages.add(image);
    }
  }

  /**
   * Registers an image descriptor for the given type.
   *
   * @param type the type
   * @param descriptor the image descriptor
   */
  public static void registerImageDescriptor(String type, ImageDescriptor descriptor) {
    fgImageDescriptors.put(normalizeCase(type), descriptor);
  }

  public static ImageDescriptor getImageDescriptor(String relativePath) {
    if (fgComparePlugin == null) return null;
    IPath path = Utilities.getIconPath(null).append(relativePath);
    URL url = FileLocator.find(fgComparePlugin.getBundle(), path, null);
    if (url == null) return null;
    return ImageDescriptor.createFromURL(url);
  }

  /**
   * Returns a shared image for the given type, or a generic image if none has been registered for
   * the given type.
   *
   * <p>Note: Images returned from this method will be automatically disposed of when this plug-in
   * shuts down. Callers must not dispose of these images themselves.
   *
   * @param type the type
   * @return the image
   */
  public static Image getImage(String type) {

    type = normalizeCase(type);

    boolean dispose = false;
    Image image = null;
    if (type != null) image = (Image) fgImages.get(type);
    if (image == null) {
      ImageDescriptor id = (ImageDescriptor) fgImageDescriptors.get(type);
      if (id != null) {
        image = id.createImage();
        dispose = true;
      }

      if (image == null) {
        if (fgComparePlugin != null) {
          if (ITypedElement.FOLDER_TYPE.equals(type)) {
            image =
                getDefault()
                    .getWorkbench()
                    .getSharedImages()
                    .getImage(ISharedImages.IMG_OBJ_FOLDER);
            // image= SharedImages.getImage(ISharedImages.IMG_OBJ_FOLDER);
          } else {
            image = createWorkbenchImage(type);
            dispose = true;
          }
        } else {
          id = (ImageDescriptor) fgImageDescriptors.get(normalizeCase("file")); // $NON-NLS-1$
          image = id.createImage();
          dispose = true;
        }
      }
      if (image != null) registerImage(type, image, dispose);
    }
    return image;
  }

  /**
   * Returns a shared image for the given adaptable. This convenience method queries the given
   * adaptable for its <code>IWorkbenchAdapter.getImageDescriptor</code>, which it uses to create an
   * image if it does not already have one.
   *
   * <p>Note: Images returned from this method will be automatically disposed of when this plug-in
   * shuts down. Callers must not dispose of these images themselves.
   *
   * @param adaptable the adaptable for which to find an image
   * @return an image
   */
  public static Image getImage(IAdaptable adaptable) {
    if (adaptable != null) {
      Object o = adaptable.getAdapter(IWorkbenchAdapter.class);
      if (o instanceof IWorkbenchAdapter) {
        ImageDescriptor id = ((IWorkbenchAdapter) o).getImageDescriptor(adaptable);
        if (id != null) {
          Image image = (Image) fgImages2.get(id);
          if (image == null) {
            image = id.createImage();
            try {
              fgImages2.put(id, image);
            } catch (NullPointerException ex) {
              // NeedWork
            }
            fgDisposeOnShutdownImages.add(image);
          }
          return image;
        }
      }
    }
    return null;
  }

  private static Image createWorkbenchImage(String type) {
    IEditorRegistry er = getDefault().getWorkbench().getEditorRegistry();
    ImageDescriptor id = er.getImageDescriptor("foo." + type); // $NON-NLS-1$
    return id.createImage();
  }

  /**
   * Returns an structure creator descriptor for the given type.
   *
   * @param type the type for which to find a descriptor
   * @return a descriptor for the given type, or <code>null</code> if no descriptor has been
   *     registered
   */
  public StructureCreatorDescriptor getStructureCreator(String type) {
    initializeRegistries();
    return (StructureCreatorDescriptor) fStructureCreators.search(type);
  }

  /**
   * Returns a stream merger for the given type.
   *
   * @param type the type for which to find a stream merger
   * @return a stream merger for the given type, or <code>null</code> if no stream merger has been
   *     registered
   */
  public IStreamMerger createStreamMerger(String type) {
    initializeRegistries();
    StreamMergerDescriptor descriptor = (StreamMergerDescriptor) fStreamMergers.search(type);
    if (descriptor != null) return descriptor.createStreamMerger();
    return null;
  }

  /**
   * Returns a stream merger for the given content type.
   *
   * @param type the type for which to find a stream merger
   * @return a stream merger for the given type, or <code>null</code> if no stream merger has been
   *     registered
   */
  public IStreamMerger createStreamMerger(IContentType type) {
    initializeRegistries();
    StreamMergerDescriptor descriptor = (StreamMergerDescriptor) fStreamMergers.search(type);
    if (descriptor != null) return descriptor.createStreamMerger();
    return null;
  }

  public ViewerDescriptor[] findStructureViewerDescriptor(
      Viewer oldViewer, ICompareInput input, CompareConfiguration configuration) {
    if (input == null) return null;
    // we don't show the structure of additions or deletions
    if (input == null || input.getLeft() == null || input.getRight() == null) return null;

    Set result = new LinkedHashSet();

    // content type search
    IContentType ctype = getCommonType(input);
    if (ctype != null) {
      initializeRegistries();
      List list = fStructureMergeViewers.searchAll(ctype);
      if (list != null) result.addAll(list);
    }

    // old style search
    String[] types = getTypes(input);
    String type = null;
    if (isHomogenous(types)) {
      type = normalizeCase(types[0]);
      initializeRegistries();
      List list = fStructureMergeViewers.searchAll(type);
      if (list != null) result.addAll(list);
      String alias = getStructureViewerAlias(type);
      if (alias != null) {
        list = fStructureMergeViewers.searchAll(alias);
        if (list != null) result.addAll(list);
      }
    }

    return result.size() > 0 ? (ViewerDescriptor[]) result.toArray(new ViewerDescriptor[0]) : null;
  }

  /**
   * Returns a structure compare viewer based on an old viewer and an input object. If the old
   * viewer is suitable for showing the input, the old viewer is returned. Otherwise, the input's
   * type is used to find a viewer descriptor in the registry which in turn is used to create a
   * structure compare viewer under the given parent composite. If no viewer descriptor can be found
   * <code>null</code> is returned.
   *
   * @param oldViewer a new viewer is only created if this old viewer cannot show the given input
   * @param input the input object for which to find a structure viewer
   * @param parent the SWT parent composite under which the new viewer is created
   * @param configuration a configuration which is passed to a newly created viewer
   * @return the compare viewer which is suitable for the given input object or <code>null</code>
   */
  public Viewer findStructureViewer(
      Viewer oldViewer, ICompareInput input, Composite parent, CompareConfiguration configuration) {
    ViewerDescriptor[] descriptors = findStructureViewerDescriptor(oldViewer, input, configuration);
    if (descriptors == null || descriptors.length == 0) {
      // we didn't found any viewer so far.
      // now we try to find a structure creator for the generic StructureDiffViewer
      IContentType ctype = getCommonType(input);

      String[] types = getTypes(input);
      String type = null;
      if (isHomogenous(types)) {
        type = normalizeCase(types[0]);
      }

      StructureCreatorDescriptor scc = null;
      initializeRegistries();
      Object desc = fStructureCreators.search(ctype); // search for content type
      if (desc instanceof StructureCreatorDescriptor) scc = (StructureCreatorDescriptor) desc;
      if (scc == null && type != null)
        scc = getStructureCreator(type); // search for old-style type scheme
      if (scc != null) {
        IStructureCreator sc = scc.createStructureCreator();
        if (sc != null) {
          StructureDiffViewer sdv = new StructureDiffViewer(parent, configuration);
          sdv.setStructureCreator(sc);
          return sdv;
        }
      }
      return null;
    }
    return getViewer(descriptors[0], oldViewer, parent, configuration);
  }

  public ViewerDescriptor[] findContentViewerDescriptor(
      Viewer oldViewer, Object in, CompareConfiguration cc) {
    Set result = new LinkedHashSet();
    if (in instanceof IStreamContentAccessor) {
      String type = ITypedElement.TEXT_TYPE;

      if (in instanceof ITypedElement) {
        ITypedElement tin = (ITypedElement) in;

        IContentType ct = getContentType(tin);
        if (ct != null) {
          initializeRegistries();
          List list = fContentViewers.searchAll(ct);
          if (list != null) result.addAll(list);
        }

        String ty = tin.getType();
        if (ty != null) type = ty;
      }

      initializeRegistries();
      List list = fContentViewers.searchAll(type);
      if (list != null) result.addAll(list);
      // fallback
      result.add(
          fContentViewers.search(
              Platform.getContentTypeManager().getContentType(IContentTypeManager.CT_TEXT)));
      return (ViewerDescriptor[]) result.toArray(new ViewerDescriptor[0]);
    }

    if (!(in instanceof ICompareInput)) return null;

    ICompareInput input = (ICompareInput) in;

    IContentType ctype = getCommonType(input);
    if (ctype != null) {
      initializeRegistries();
      List list = fContentMergeViewers.searchAll(ctype);
      if (list != null) result.addAll(list);
    }

    String[] types = getTypes(input);
    String type = null;
    if (isHomogenous(types)) type = types[0];

    if (ITypedElement.FOLDER_TYPE.equals(type)) return null;

    if (type == null) {
      int n = 0;
      for (int i = 0; i < types.length; i++)
        if (!ITypedElement.UNKNOWN_TYPE.equals(types[i])) {
          n++;
          if (type == null) type = types[i]; // remember the first known type
        }
      if (n > 1) // don't use the type if there were more than one
      type = null;
    }

    if (type != null) {
      initializeRegistries();
      List list = fContentMergeViewers.searchAll(type);
      if (list != null) result.addAll(list);
    }

    // fallback
    String leftType = guessType(input.getLeft());
    String rightType = guessType(input.getRight());

    if (leftType != null || rightType != null) {
      boolean right_text = rightType != null && ITypedElement.TEXT_TYPE.equals(rightType);
      boolean left_text = leftType != null && ITypedElement.TEXT_TYPE.equals(leftType);
      initializeRegistries();
      if ((rightType != null && !right_text) || (leftType != null && !left_text)) {
        List list = fContentMergeViewers.searchAll(BINARY_TYPE);
        if (list != null) result.addAll(list);
      }
      List list = fContentMergeViewers.searchAll(ITypedElement.TEXT_TYPE);
      if (list != null) result.addAll(list);

      return (ViewerDescriptor[]) result.toArray(new ViewerDescriptor[0]);
    }
    return null;
  }

  /**
   * Returns a content compare viewer based on an old viewer and an input object. If the old viewer
   * is suitable for showing the input the old viewer is returned. Otherwise the input's type is
   * used to find a viewer descriptor in the registry which in turn is used to create a content
   * compare viewer under the given parent composite. If no viewer descriptor can be found <code>
   * null</code> is returned.
   *
   * @param oldViewer a new viewer is only created if this old viewer cannot show the given input
   * @param in the input object for which to find a content viewer
   * @param parent the SWT parent composite under which the new viewer is created
   * @param cc a configuration which is passed to a newly created viewer
   * @return the compare viewer which is suitable for the given input object or <code>null</code>
   */
  public Viewer findContentViewer(
      Viewer oldViewer, Object in, Composite parent, CompareConfiguration cc) {
    ViewerDescriptor[] descriptors = findContentViewerDescriptor(oldViewer, in, cc);
    return getViewer(descriptors != null ? descriptors[0] : null, oldViewer, parent, cc);
  }

  private static Viewer getViewer(
      Object descriptor, Viewer oldViewer, Composite parent, CompareConfiguration cc) {
    if (descriptor instanceof IViewerDescriptor)
      return ((IViewerDescriptor) descriptor).createViewer(oldViewer, parent, cc);
    return null;
  }

  private static String[] getTypes(ICompareInput input) {
    ITypedElement ancestor = input.getAncestor();
    ITypedElement left = input.getLeft();
    ITypedElement right = input.getRight();

    ArrayList tmp = new ArrayList();
    if (ancestor != null) {
      String type = ancestor.getType();
      if (type != null) tmp.add(normalizeCase(type));
    }
    if (left != null) {
      String type = left.getType();
      if (type != null) tmp.add(normalizeCase(type));
    }
    if (right != null) {
      String type = right.getType();
      if (type != null) tmp.add(normalizeCase(type));
    }
    return (String[]) tmp.toArray(new String[tmp.size()]);
  }

  private static IContentType getContentType(ITypedElement element) {
    if (element == null) return null;
    String name = element.getName();
    IContentType ct = null;
    if (element instanceof IStreamContentAccessor) {
      IStreamContentAccessor isa = (IStreamContentAccessor) element;
      try {
        InputStream is = isa.getContents();
        if (is != null) {
          InputStream bis = new BufferedInputStream(is);
          try {
            ct = fgContentTypeManager.findContentTypeFor(is, name);
          } catch (IOException e) {
            // silently ignored
          } finally {
            try {
              bis.close();
            } catch (IOException e2) {
              // silently ignored
            }
          }
        }
      } catch (CoreException e1) {
        // silently ignored
      }
    }
    if (ct == null) ct = fgContentTypeManager.findContentTypeFor(name);
    return ct;
  }

  /*
   * Returns true if the given types are homogeneous.
   */
  private static boolean isHomogenous(String[] types) {
    switch (types.length) {
      case 1:
        return true;
      case 2:
        return types[0].equals(types[1]);
      case 3:
        return types[0].equals(types[1]) && types[1].equals(types[2]);
    }
    return false;
  }

  /*
   * Returns the most specific content type that is common to the given inputs or null.
   */
  private static IContentType getCommonType(ICompareInput input) {

    ITypedElement ancestor = input.getAncestor();
    ITypedElement left = input.getLeft();
    ITypedElement right = input.getRight();

    int n = 0;
    IContentType[] types = new IContentType[3];
    IContentType type = null;

    if (ancestor != null) {
      type = getContentType(ancestor);
      if (type != null) types[n++] = type;
    }
    type = getContentType(left);
    if (type != null) types[n++] = type;
    else return null;
    type = getContentType(right);
    if (type != null) types[n++] = type;
    else return null;

    IContentType result = null;
    IContentType[] s0, s1, s2;
    switch (n) {
      case 0:
        return null;
      case 1:
        return types[0];
      case 2:
        if (types[0].equals(types[1])) return types[0];
        s0 = toFullPath(types[0]);
        s1 = toFullPath(types[1]);
        for (int i = 0; i < Math.min(s0.length, s1.length); i++) {
          if (!s0[i].equals(s1[i])) break;
          result = s0[i];
        }
        return result;
      case 3:
        if (types[0].equals(types[1]) && types[1].equals(types[2])) return types[0];
        s0 = toFullPath(types[0]);
        s1 = toFullPath(types[1]);
        s2 = toFullPath(types[2]);
        for (int i = 0; i < Math.min(Math.min(s0.length, s1.length), s2.length); i++) {
          if (!s0[i].equals(s1[i]) || !s1[i].equals(s2[i])) break;
          result = s0[i];
        }
        return result;
    }
    return null;
  }

  private static IContentType[] toFullPath(IContentType ct) {
    List l = new ArrayList();
    for (; ct != null; ct = ct.getBaseType()) l.add(0, ct);
    return (IContentType[]) l.toArray(new IContentType[l.size()]);
  }

  /*
   * Guesses the file type of the given input.
   * Returns ITypedElement.TEXT_TYPE if none of the first 10 lines is longer than 1000 bytes.
   * Returns ITypedElement.UNKNOWN_TYPE otherwise.
   * Returns <code>null</code> if the input isn't an <code>IStreamContentAccessor</code>.
   */
  private static String guessType(ITypedElement input) {
    if (input instanceof IStreamContentAccessor) {
      IStreamContentAccessor sca = (IStreamContentAccessor) input;
      InputStream is = null;
      try {
        is = sca.getContents();
        if (is == null) return null;
        int lineLength = 0;
        int lines = 0;
        while (lines < 10) {
          int c = is.read();
          if (c == -1) // EOF
          break;
          if (c == '\n' || c == '\r') { // reset line length
            lineLength = 0;
            lines++;
          } else lineLength++;
          if (lineLength > 1000) return ITypedElement.UNKNOWN_TYPE;
        }
        return ITypedElement.TEXT_TYPE;
      } catch (CoreException ex) {
        // be silent and return UNKNOWN_TYPE
      } catch (IOException ex) {
        // be silent and return UNKNOWN_TYPE
      } finally {
        if (is != null) {
          try {
            is.close();
          } catch (IOException ex) {
            // silently ignored
          }
        }
      }
      return ITypedElement.UNKNOWN_TYPE;
    }
    return null;
  }

  private static String normalizeCase(String s) {
    if (NORMALIZE_CASE && s != null) return s.toUpperCase();
    return s;
  }

  // ---- alias management

  private String getStructureViewerAlias(String type) {
    return (String) getStructureViewerAliases().get(type);
  }

  public void addStructureViewerAlias(String type, String alias) {
    getStructureViewerAliases().put(normalizeCase(alias), normalizeCase(type));
  }

  private Map getStructureViewerAliases() {
    if (fStructureViewerAliases == null) {
      fStructureViewerAliases = new Hashtable(10);
      String aliases = getPreferenceStore().getString(STRUCTUREVIEWER_ALIASES_PREFERENCE_NAME);
      if (aliases != null && aliases.length() > 0) {
        StringTokenizer st = new StringTokenizer(aliases, " "); // $NON-NLS-1$
        while (st.hasMoreTokens()) {
          String pair = st.nextToken();
          int pos = pair.indexOf('.');
          if (pos > 0) {
            String key = pair.substring(0, pos);
            String alias = pair.substring(pos + 1);
            fStructureViewerAliases.put(key, alias);
          }
        }
      }
    }
    return fStructureViewerAliases;
  }

  public void removeAllStructureViewerAliases(String type) {
    if (fStructureViewerAliases == null) return;
    String t = normalizeCase(type);
    Set entrySet = fStructureViewerAliases.entrySet();
    for (Iterator iter = entrySet.iterator(); iter.hasNext(); ) {
      Map.Entry entry = (Map.Entry) iter.next();
      if (entry.getValue().equals(t)) iter.remove();
    }
  }

  /*
   * Converts the aliases into a single string before they are stored
   * in the preference store.
   * The format is:
   * <key> '.' <alias> ' ' <key> '.' <alias> ...
   */
  private void rememberAliases(IPreferenceStore ps) {
    if (fStructureViewerAliases == null) return;
    StringBuffer buffer = new StringBuffer();
    Iterator iter = fStructureViewerAliases.keySet().iterator();
    while (iter.hasNext()) {
      String key = (String) iter.next();
      String alias = (String) fStructureViewerAliases.get(key);
      buffer.append(key);
      buffer.append('.');
      buffer.append(alias);
      buffer.append(' ');
    }
    ps.setValue(STRUCTUREVIEWER_ALIASES_PREFERENCE_NAME, buffer.toString());
  }

  // ---- filters

  public boolean filter(String name, boolean isFolder, boolean isArchive) {
    if (fFilter == null) {
      fFilter = new CompareFilter();
      final IPreferenceStore ps = getPreferenceStore();
      fFilter.setFilters(ps.getString(ComparePreferencePage.PATH_FILTER));
      fPropertyChangeListener =
          new IPropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent event) {
              if (ComparePreferencePage.PATH_FILTER.equals(event.getProperty()))
                fFilter.setFilters(ps.getString(ComparePreferencePage.PATH_FILTER));
            }
          };
      ps.addPropertyChangeListener(fPropertyChangeListener);
    }
    return fFilter.filter(name, isFolder, isArchive);
  }

  private void internalOpenDialog(final CompareEditorInput input) {
    Runnable runnable =
        new Runnable() {
          public void run() {
            CompareDialog dialog = new CompareDialog(getShell(), input);
            dialog.open();
          }
        };
    syncExec(runnable);
  }

  private void syncExec(Runnable runnable) {
    if (Display.getCurrent() == null) {
      Display.getDefault().syncExec(runnable);
    } else {
      runnable.run();
    }
  }

  // ---- more utilities

  protected void handleNoDifference() {
    Runnable runnable =
        new Runnable() {
          public void run() {
            MessageDialog.openInformation(
                getShell(),
                Utilities.getString("CompareUIPlugin.dialogTitle"),
                Utilities.getString("CompareUIPlugin.noDifferences")); // $NON-NLS-1$//$NON-NLS-2$
          }
        };
    syncExec(runnable);
  }

  /**
   * Returns an array of all editors that have an unsaved content. If the identical content is
   * presented in more than one editor, only one of those editor parts is part of the result.
   *
   * @return an array of all dirty editor parts.
   */
  public static IEditorPart[] getDirtyEditors() {
    Set inputs = new HashSet();
    List result = new ArrayList(0);
    IWorkbench workbench = getDefault().getWorkbench();
    IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();
    for (int i = 0; i < windows.length; i++) {
      IWorkbenchPage[] pages = windows[i].getPages();
      for (int x = 0; x < pages.length; x++) {
        IEditorPart[] editors = pages[x].getDirtyEditors();
        for (int z = 0; z < editors.length; z++) {
          IEditorPart ep = editors[z];
          IEditorInput input = ep.getEditorInput();
          if (!inputs.contains(input)) {
            inputs.add(input);
            result.add(ep);
          }
        }
      }
    }
    return (IEditorPart[]) result.toArray(new IEditorPart[result.size()]);
  }

  public static void logErrorMessage(String message) {
    if (message == null) message = ""; // $NON-NLS-1$
    log(new Status(IStatus.ERROR, getPluginId(), INTERNAL_ERROR, message, null));
  }

  public static void log(Throwable e) {
    log(
        new Status(
            IStatus.ERROR,
            getPluginId(),
            INTERNAL_ERROR,
            CompareMessages.ComparePlugin_internal_error,
            e));
  }

  public static void log(IStatus status) {
    getDefault().getLog().log(status);
  }

  String findContentTypeNameOrType(
      ICompareInput input, ViewerDescriptor vd, CompareConfiguration cc) {
    IContentType ctype = getCommonType(input);
    if (ctype != null) {
      initializeRegistries();
      List list = fContentMergeViewers.searchAll(ctype);
      if (list != null) if (list.contains(vd)) return ctype.getName();
    }

    String[] types = getTypes(input);
    String type = null;
    if (isHomogenous(types)) type = types[0];

    if (ITypedElement.FOLDER_TYPE.equals(type)) return null;

    if (type == null) {
      int n = 0;
      for (int i = 0; i < types.length; i++)
        if (!ITypedElement.UNKNOWN_TYPE.equals(types[i])) {
          n++;
          if (type == null) type = types[i]; // remember the first known type
        }
      if (n > 1) // don't use the type if there were more than one
      type = null;
    }

    if (type != null) {
      initializeRegistries();
      List list = fContentMergeViewers.searchAll(type);
      if (list != null) if (list.contains(vd)) return type;
    }

    // fallback
    String leftType = guessType(input.getLeft());
    String rightType = guessType(input.getRight());

    if (leftType != null || rightType != null) {
      boolean right_text = rightType != null && ITypedElement.TEXT_TYPE.equals(rightType);
      boolean left_text = leftType != null && ITypedElement.TEXT_TYPE.equals(leftType);
      initializeRegistries();
      if ((rightType != null && !right_text) || (leftType != null && !left_text)) {
        List list = fContentMergeViewers.searchAll(BINARY_TYPE);
        if (list != null) if (list.contains(vd)) return type;
      }
      List list = fContentMergeViewers.searchAll(ITypedElement.TEXT_TYPE);
      if (list != null) if (list.contains(vd)) return type;
    }
    return null;
  }

  String findStructureTypeNameOrType(
      ICompareInput input, ViewerDescriptor vd, CompareConfiguration cc) {
    if (input == null) return null;
    // we don't show the structure of additions or deletions
    if (input == null || input.getLeft() == null || input.getRight() == null) return null;

    // content type search
    IContentType ctype = getCommonType(input);
    if (ctype != null) {
      initializeRegistries();
      List list = fStructureMergeViewers.searchAll(ctype);
      if (list != null) if (list.contains(vd)) return ctype.getName();
    }

    // old style search
    String[] types = getTypes(input);
    String type = null;
    if (isHomogenous(types)) {
      type = normalizeCase(types[0]);
      initializeRegistries();
      List list = fStructureMergeViewers.searchAll(type);
      if (list != null) if (list.contains(vd)) return type;
      String alias = getStructureViewerAlias(type);
      if (alias != null) {
        list = fStructureMergeViewers.searchAll(alias);
        if (list != null) if (list.contains(vd)) return alias;
      }
    }

    return null;
  }
}
  public ViewerDescriptor[] findContentViewerDescriptor(
      Viewer oldViewer, Object in, CompareConfiguration cc) {
    Set result = new LinkedHashSet();
    if (in instanceof IStreamContentAccessor) {
      String type = ITypedElement.TEXT_TYPE;

      if (in instanceof ITypedElement) {
        ITypedElement tin = (ITypedElement) in;

        IContentType ct = getContentType(tin);
        if (ct != null) {
          initializeRegistries();
          List list = fContentViewers.searchAll(ct);
          if (list != null) result.addAll(list);
        }

        String ty = tin.getType();
        if (ty != null) type = ty;
      }

      initializeRegistries();
      List list = fContentViewers.searchAll(type);
      if (list != null) result.addAll(list);
      // fallback
      result.add(
          fContentViewers.search(
              Platform.getContentTypeManager().getContentType(IContentTypeManager.CT_TEXT)));
      return (ViewerDescriptor[]) result.toArray(new ViewerDescriptor[0]);
    }

    if (!(in instanceof ICompareInput)) return null;

    ICompareInput input = (ICompareInput) in;

    IContentType ctype = getCommonType(input);
    if (ctype != null) {
      initializeRegistries();
      List list = fContentMergeViewers.searchAll(ctype);
      if (list != null) result.addAll(list);
    }

    String[] types = getTypes(input);
    String type = null;
    if (isHomogenous(types)) type = types[0];

    if (ITypedElement.FOLDER_TYPE.equals(type)) return null;

    if (type == null) {
      int n = 0;
      for (int i = 0; i < types.length; i++)
        if (!ITypedElement.UNKNOWN_TYPE.equals(types[i])) {
          n++;
          if (type == null) type = types[i]; // remember the first known type
        }
      if (n > 1) // don't use the type if there were more than one
      type = null;
    }

    if (type != null) {
      initializeRegistries();
      List list = fContentMergeViewers.searchAll(type);
      if (list != null) result.addAll(list);
    }

    // fallback
    String leftType = guessType(input.getLeft());
    String rightType = guessType(input.getRight());

    if (leftType != null || rightType != null) {
      boolean right_text = rightType != null && ITypedElement.TEXT_TYPE.equals(rightType);
      boolean left_text = leftType != null && ITypedElement.TEXT_TYPE.equals(leftType);
      initializeRegistries();
      if ((rightType != null && !right_text) || (leftType != null && !left_text)) {
        List list = fContentMergeViewers.searchAll(BINARY_TYPE);
        if (list != null) result.addAll(list);
      }
      List list = fContentMergeViewers.searchAll(ITypedElement.TEXT_TYPE);
      if (list != null) result.addAll(list);

      return (ViewerDescriptor[]) result.toArray(new ViewerDescriptor[0]);
    }
    return null;
  }
Ejemplo n.º 26
0
 public PHPContentTypeFilter() {
   super();
   contentType =
       Platform.getContentTypeManager().getContentType(ORG_ECLIPSE_WST_HTML_CORE_HTMLSOURCE);
 }