package org.xmind.ui.internal.editor;
import static org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants.ATT_CLASS;
import static org.xmind.ui.internal.RegistryConstants.ATT_SCHEME;
import static org.xmind.ui.internal.RegistryConstants.EXT_WORKBOOK_REF_FACTORIES;
import static org.xmind.ui.internal.RegistryConstants.TAG_AVAILABLE_FOR_URI_SCHEME;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IRegistryEventListener;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.ui.IMemento;
import org.xmind.ui.internal.MindMapUIPlugin;
import org.xmind.ui.internal.RegistryConstants;
import org.xmind.ui.mindmap.IWorkbookRef;
import org.xmind.ui.mindmap.IWorkbookRefFactory;
import org.xmind.ui.mindmap.MindMapUI;
public class WorkbookRefFactoryManager
implements IWorkbookRefFactory, IRegistryEventListener {
private static class WorkbookRefFactoryDescriptor {
private IConfigurationElement element;
private final Set<String> schemes;
private volatile IWorkbookRefFactory factoryInstance;
private WorkbookRefFactoryDescriptor(IConfigurationElement element) {
if (element.getAttribute(ATT_CLASS) == null) {
throw new IllegalArgumentException(
"No 'class' attribute on factory element (contributed by " //$NON-NLS-1$
+ element.getContributor().getName() + ")"); //$NON-NLS-1$
}
this.element = element;
this.schemes = new HashSet<String>();
for (IConfigurationElement schemeTag : element
.getChildren(TAG_AVAILABLE_FOR_URI_SCHEME)) {
String scheme = schemeTag.getAttribute(ATT_SCHEME);
if (scheme != null) {
this.schemes.add(scheme);
}
}
}
public synchronized IWorkbookRefFactory getInstance() {
if (this.factoryInstance == null && this.element != null) {
Object ins = null;
try {
ins = this.element.createExecutableExtension(ATT_CLASS);
} catch (CoreException e) {
MindMapUIPlugin.getDefault().getLog().log(e.getStatus());
}
if (ins != null && ins instanceof IWorkbookRefFactory) {
this.factoryInstance = (IWorkbookRefFactory) ins;
}
}
return this.factoryInstance;
}
public synchronized void dispose() {
this.schemes.clear();
this.element = null;
this.factoryInstance = null;
}
public boolean isAvailableForURIScheme(String scheme) {
return this.schemes.contains(scheme);
}
public boolean isFromExtension(IExtension ext) {
return element != null && ext != null
&& ext.equals(element.getDeclaringExtension());
}
}
private List<WorkbookRefFactoryDescriptor> factories = null;
private IExtensionRegistry registry = null;
public WorkbookRefFactoryManager() {
super();
}
public synchronized IWorkbookRef createWorkbookRef(URI uri,
IMemento state) {
IWorkbookRefFactory factory = getWorkbookRefFactoryForURI(uri);
if (factory != null)
return factory.createWorkbookRef(uri, state);
return URLWorkbookRef.create(uri, state);
}
private synchronized IWorkbookRefFactory getWorkbookRefFactoryForURI(
URI uri) {
ensureLoaded();
String scheme = uri.getScheme();
for (WorkbookRefFactoryDescriptor factory : factories) {
if (factory.isAvailableForURIScheme(scheme)) {
return factory.getInstance();
}
}
return null;
}
private synchronized void ensureLoaded() {
if (factories != null)
return;
factories = new ArrayList<WorkbookRefFactoryDescriptor>();
registry = Platform.getExtensionRegistry();
if (registry == null) {
MindMapUIPlugin.getDefault().getLog()
.log(new Status(IStatus.WARNING, MindMapUIPlugin.PLUGIN_ID,
"Extension registry is not available")); //$NON-NLS-1$
return;
}
IExtensionPoint extPoint = registry.getExtensionPoint(
MindMapUI.PLUGIN_ID, EXT_WORKBOOK_REF_FACTORIES);
if (extPoint == null) {
MindMapUIPlugin.getDefault().getLog()
.log(new Status(IStatus.WARNING, MindMapUIPlugin.PLUGIN_ID,
"Extension point '" + MindMapUI.PLUGIN_ID //$NON-NLS-1$
+ "." + EXT_WORKBOOK_REF_FACTORIES //$NON-NLS-1$
+ "' not found.")); //$NON-NLS-1$
return;
}
registry.addListener(this, extPoint.getUniqueIdentifier());
readExtensions(extPoint.getExtensions());
}
private void readExtensions(IExtension[] extensions) {
for (IExtension ext : extensions) {
for (IConfigurationElement element : ext
.getConfigurationElements()) {
if (RegistryConstants.TAG_FACTORY.equals(element.getName())) {
WorkbookRefFactoryDescriptor desc = new WorkbookRefFactoryDescriptor(
element);
factories.add(desc);
}
}
}
}
public synchronized void dispose() {
if (factories != null) {
for (Object o : factories.toArray()) {
((WorkbookRefFactoryDescriptor) o).dispose();
}
factories.clear();
factories = null;
}
if (registry != null) {
registry.removeListener(this);
registry = null;
}
}
public void added(IExtension[] extensions) {
readExtensions(extensions);
}
public void removed(IExtension[] extensions) {
for (IExtension ext : extensions) {
for (Object o : factories.toArray()) {
if (((WorkbookRefFactoryDescriptor) o).isFromExtension(ext)) {
factories.remove(o);
((WorkbookRefFactoryDescriptor) o).dispose();
}
}
}
}
public void added(IExtensionPoint[] extensionPoints) {
// do not care about other extension points
}
public void removed(IExtensionPoint[] extensionPoints) {
// do not care about other extension points
}
}