blob: 96829a3d540134285e69058077d6e69603c64fdc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Jens Lukowski/Innoopract - initial renaming/restructuring
*
*******************************************************************************/
package org.eclipse.wst.sse.core.internal.modelhandler;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.eclipse.wst.sse.core.internal.Logger;
import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
import org.eclipse.wst.sse.core.internal.util.Utilities;
public class ModelHandlerRegistry {
private static ModelHandlerRegistry instance = null;
private static IContentTypeManager getContentTypeRegistry() {
IContentTypeManager registry = Platform.getContentTypeManager();
return registry;
}
/**
*/
public synchronized static ModelHandlerRegistry getInstance() {
if (instance == null) {
instance = new ModelHandlerRegistry();
}
return instance;
}
private IModelHandler defaultHandler = null;
private ModelHandlerRegistryReader reader = new ModelHandlerRegistryReader();
/*
* @see ContentTypeRegistry#getTypeFor(String)
*/
/**
* Constructor for ContentTypeRegistryImpl.
*/
protected ModelHandlerRegistry() {
super();
reader = new ModelHandlerRegistryReader().readRegistry();
}
/**
* Finds the default model handler. Note: we still go through the registry
* to be sure to get the existing instance, but then we do remember it, so
* subsequent requests will be faster. The first time through, we do check
* the whole list, to be sure there is only one.
*
*/
final public IModelHandler getDefault() {
if (defaultHandler == null) {
IConfigurationElement[] elements = reader.elements;
for (int i = 0; i < elements.length; i++) {
boolean ofInterest = reader.isElementDefault(elements[i]);
if (ofInterest) {
// if, here within the search loop we've already found
// one defaultHandler, then something is wrong!
if (defaultHandler == null) {
defaultHandler = reader.getInstance(elements[i]);
} else {
String errorString = "Program or configuration error. More than one default content handler found"; //$NON-NLS-1$
Logger.log(Logger.ERROR, errorString);
throw new IllegalStateException(errorString);
}
}
}
}
if (defaultHandler == null) {
String errorString = "Program or configuration error. No default content type handler found."; //$NON-NLS-1$
Logger.log(Logger.ERROR, errorString);
throw new IllegalStateException(errorString);
}
return defaultHandler;
}
/**
* Finds the contentTypeDescription based on outcome of the
* ContentTypeDescription's canHandle(IResource) method.
*
* @throws CoreException
*/
public IModelHandler getHandlerFor(IFile iFile) throws CoreException {
IModelHandler modelHandler = null;
IContentDescription contentDescription = null;
IContentType contentType = null;
boolean exists = iFile.exists();
if (exists) {
// try the optimized method first as the description may be cached
contentDescription = iFile.getContentDescription();
if (contentDescription != null) {
// use the provided description
contentType = contentDescription.getContentType();
} else {
// use the more thorough discovery method to get a description
InputStream contents = null;
try {
contents = iFile.getContents(true);
contentDescription = Platform.getContentTypeManager().getDescriptionFor(contents, iFile.getName(), IContentDescription.ALL);
if (contentDescription != null) {
contentType = contentDescription.getContentType();
}
} catch (IOException e) {
// nothing further can be done, but will log for debugging
Logger.logException(e);
} finally {
if (contents != null) {
try {
contents.close();
} catch (IOException e1) {
// nothing can be done
}
}
}
}
}
// if we couldn't get the content type from a description, try basing
// it on the filename
if (contentType == null) {
contentType = Platform.getContentTypeManager().findContentTypeFor(iFile.getName());
}
if (contentType != null) {
modelHandler = getHandlerForContentType(contentType);
} else {
// temp hard coding for null content type
modelHandler = getHandlerForID("org.eclipse.wst.sse.core.handler.xml"); //$NON-NLS-1$
}
return modelHandler;
}
/**
* @see ContentTypeRegistry#add(ContentTypeDescription)
*/
// void add(IModelHandler contentTypeDescription) {
// arrayList.add(contentTypeDescription);
// }
/*
* @see ContentTypeRegistry#getModelFor(String)
*/
/**
* @throws IOException
* @see ContentTypeRegistry#getTypeFor(String, InputStream)
*/
public IModelHandler getHandlerFor(String filename, InputStream inputStream) throws IOException {
InputStream iStream = Utilities.getMarkSupportedStream(inputStream);
IModelHandler modelHandler = null;
IContentType contentType = null;
if (inputStream != null) {
try {
iStream.mark(CodedIO.MAX_MARK_SIZE);
contentType = getContentTypeRegistry().findContentTypeFor(Utilities.getLimitedStream(iStream), filename);
}
// XXX: Remove when we build with the fix for Eclipse bug #63625
catch (FileNotFoundException fnfe) {
Logger.logException(fnfe);
} finally {
if (iStream != null && iStream.markSupported()) {
iStream.reset();
}
}
}
if (contentType == null) {
contentType = getContentTypeRegistry().findContentTypeFor(filename);
}
// if all else failed, try to detect solely on contents; done last for performance reasons
if (contentType == null) {
contentType = getContentTypeRegistry().findContentTypeFor(Utilities.getLimitedStream(iStream), null);
}
modelHandler = getHandlerForContentType(contentType);
return modelHandler;
}
/**
* Gets registered modelHandlers for given content type. TODO: eventually
* need to look at contentType's parent types to see if more general type
* can handle (e.g. if we got xsl which was a subtype of xml).
*
* @param contentType
* @return
*/
private IModelHandler getHandlerForContentType(IContentType contentType) {
IModelHandler found = null;
// temp hard coding for null content type
if (contentType == null) {
found = getHandlerForID("org.eclipse.wst.sse.core.handler.xml"); //$NON-NLS-1$
} else {
//String associatedContentTypeId = contentType.getId();
IConfigurationElement[] elements = reader.elements;
if (elements != null) {
for (int i = 0; i < elements.length; i++) {
String currentId = reader.getAssociatedContentTypeId(elements[i]);
IContentType modelContentType = Platform.getContentTypeManager().getContentType(currentId);
if (contentType.isKindOf(modelContentType)) {
IModelHandler item = reader.getInstance(elements[i]);
found = item;
}
}
} else {
Logger.log(Logger.WARNING_DEBUG, "There were no Model Handler found in registry"); //$NON-NLS-1$
}
}
return found;
}
/**
* Finds the ModelHandler based on literal content type id. This should
* not normally be needed, in is in cases when a model needs to be
* created, and there is no resource. Its basically a "first found first
* returned". Note the order is fairly unpredictable, so non-unique ids
* would cause problems, and are not checked.
*/
public IModelHandler getHandlerForContentTypeId(String contentTypeId) {
IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeId);
return getHandlerForContentType(contentType);
// IModelHandler found = null;
// IConfigurationElement[] elements = reader.elements;
// if (elements != null) {
// for (int i = 0; i < elements.length; i++) {
// String currentId = reader.getAssociatedContentTypeId(elements[i]);
// if (contentTypeId.equals(currentId)) {
// IModelHandler item = reader.getInstance(elements[i]);
// found = item;
// }
// }
// }
// else {
// Logger.log(Logger.WARNING_DEBUG, "There were no Model Handler found
// in registry");
// }
// return found;
}
/**
* Finds the ModelHandler based on literal id. Its basically a "first
* found first returned". Note the order is fairly unpredictable, so
* non-unique ids would cause problems, and are not checked.
*/
private IModelHandler getHandlerForID(String modelId) {
IModelHandler found = null;
IConfigurationElement[] elements = reader.elements;
if (elements != null) {
for (int i = 0; i < elements.length; i++) {
String currentId = reader.getId(elements[i]);
if (modelId.equals(currentId)) {
IModelHandler item = reader.getInstance(elements[i]);
found = item;
}
}
} else {
Logger.log(Logger.WARNING_DEBUG, "There were no Model Handler found in registry"); //$NON-NLS-1$
}
return found;
}
}