blob: 3ee333d0542ee6e37506cb21529d1c8950428700 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.core.internal.content;
import java.io.*;
import org.eclipse.core.internal.runtime.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.content.*;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.osgi.service.prefs.Preferences;
public class ContentTypeManager implements IContentTypeManager, IRegistryChangeListener {
private static ContentTypeManager instance;
public static final int BLOCK_SIZE = 0x400;
public static final String CONTENT_TYPE_PREF_NODE = Platform.PI_RUNTIME + IPath.SEPARATOR + "content-types"; //$NON-NLS-1$
private static final String OPTION_DEBUG_CONTENT_TYPES = Platform.PI_RUNTIME + "/contenttypes/debug"; //$NON-NLS-1$;
static final boolean DEBUGGING = Boolean.TRUE.toString().equalsIgnoreCase(InternalPlatform.getDefault().getOption(OPTION_DEBUG_CONTENT_TYPES));
private ContentTypeCatalog catalog;
/**
* List of registered listeners (element type:
* <code>IContentTypeChangeListener</code>).
* These listeners are to be informed when
* something in a content type changes.
*/
protected ListenerList contentTypeListeners = new ListenerList();
/**
* Creates and initializes the platform's content type manager. A reference to the
* content type manager can later be obtained by calling <code>getInstance()</code>.
* <p>
* Since calling this method will cause the content type manager to register a registry change listener,
* this method must be called while the extension registry is available.
* </p>
*/
public static void startup() {
instance = new ContentTypeManager();
Platform.getExtensionRegistry().addRegistryChangeListener(instance, Platform.PI_RUNTIME);
}
/**
* Shuts down the platform's content type manager. After this call returns,
* the content type manager will be closed for business.
* <p>
* Since calling this method will cause the content type manager to unregister a registry change listener,
* this method must be called while the extension registry is available.
* </p>
*/
public static void shutdown() {
Platform.getExtensionRegistry().removeRegistryChangeListener(instance);
instance = null;
}
/**
* Obtains this platform's content type manager.
* <p>
* It has to have been created first by a call to <code>create()</code>,
* otherwise an <code>AssertionFailedException</code> will be thrown.
* </p>
*
* @return the content type manager
*/
public static ContentTypeManager getInstance() {
Assert.isNotNull(instance); //$NON-NLS-1$
return instance;
}
/*
* Returns the extension for a file name (omiting the leading '.').
*/
static String getFileExtension(String fileName) {
int dotPosition = fileName.lastIndexOf('.');
return (dotPosition == -1 || dotPosition == fileName.length() - 1) ? null : fileName.substring(dotPosition + 1);
}
protected static LazyInputStream readBuffer(InputStream contents) {
return new LazyInputStream(contents, BLOCK_SIZE);
}
protected static LazyReader readBuffer(Reader contents) {
return new LazyReader(contents, BLOCK_SIZE);
}
public ContentTypeManager() {
// nothing to do
}
private ContentTypeCatalog buildCatalog() {
ContentTypeCatalog newCatalog = new ContentTypeCatalog(this);
createBuilder(newCatalog).buildCatalog();
return newCatalog;
}
protected ContentTypeBuilder createBuilder(ContentTypeCatalog newCatalog) {
return new ContentTypeBuilder(newCatalog);
}
public IContentType findContentTypeFor(InputStream contents, String fileName) throws IOException {
IContentType[] all = findContentTypesFor(contents, fileName);
return all.length > 0 ? all[0] : null;
}
public IContentType findContentTypeFor(String fileName) {
// basic implementation just gets all content types
IContentType[] associated = findContentTypesFor(fileName);
return associated.length == 0 ? null : associated[0];
}
public IContentType[] findContentTypesFor(InputStream contents, String fileName) throws IOException {
return getCatalog().findContentTypesFor(contents, fileName);
}
public IContentType[] findContentTypesFor(String fileName) {
return getCatalog().findContentTypesFor(fileName);
}
public IContentType[] getAllContentTypes() {
return getCatalog().getAllContentTypes();
}
protected synchronized ContentTypeCatalog getCatalog() {
if (catalog == null)
catalog = buildCatalog();
return catalog;
}
public IContentType getContentType(String contentTypeIdentifier) {
return getCatalog().getContentType(contentTypeIdentifier);
}
public IContentDescription getDescriptionFor(InputStream contents, String fileName, QualifiedName[] options) throws IOException {
return getCatalog().getDescriptionFor(contents, fileName, options);
}
public IContentDescription getDescriptionFor(Reader contents, String fileName, QualifiedName[] options) throws IOException {
return getCatalog().getDescriptionFor(contents, fileName, options);
}
Preferences getPreferences() {
return new InstanceScope().getNode(CONTENT_TYPE_PREF_NODE);
}
public synchronized void registryChanged(IRegistryChangeEvent event) {
// no changes related to the content type registry
if (event.getExtensionDeltas(Platform.PI_RUNTIME, ContentTypeBuilder.PT_CONTENTTYPES).length == 0)
return;
if (catalog == null)
// nothing to discard
return;
catalog = null;
if (ContentTypeManager.DEBUGGING)
Policy.debug("Event caused content type registry to be discarded: " + event); //$NON-NLS-1$
}
/* (non-Javadoc)
* @see IContentTypeManager#addContentTypeChangeListener(IContentTypeChangeListener)
*/
public void addContentTypeChangeListener(IContentTypeChangeListener listener) {
contentTypeListeners.add(listener);
}
/* (non-Javadoc)
* @see IContentTypeManager#removeContentTypeChangeListener(IContentTypeChangeListener)
*/
public void removeContentTypeChangeListener(IContentTypeChangeListener listener) {
contentTypeListeners.remove(listener);
}
public void fireContentTypeChangeEvent(ContentType type) {
Object[] listeners = this.contentTypeListeners.getListeners();
for (int i = 0; i < listeners.length; i++) {
final ContentTypeChangeEvent event = new ContentTypeChangeEvent(type);
final IContentTypeChangeListener listener = (IContentTypeChangeListener) listeners[i];
ISafeRunnable job = new ISafeRunnable() {
public void handleException(Throwable exception) {
// already logged in Platform#run()
}
public void run() throws Exception {
listener.contentTypeChanged(event);
}
};
Platform.run(job);
}
}
}