/* * Copyright (c) 2009-2016 Eike Stepper (Berlin, Germany) 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: * Victor Roldan Betancort - initial API and implementation * Eike Stepper - maintenance */ package org.eclipse.emf.internal.cdo.view; import org.eclipse.emf.cdo.util.CDOUtil; import org.eclipse.emf.cdo.view.AbstractCDOViewProvider; import org.eclipse.emf.cdo.view.CDOView; import org.eclipse.emf.cdo.view.CDOViewProvider; import org.eclipse.emf.cdo.view.CDOViewProvider.CDOViewProvider2; import org.eclipse.emf.cdo.view.CDOViewProviderRegistry; import org.eclipse.emf.cdo.view.CDOViewSet; import org.eclipse.emf.internal.cdo.bundle.OM; import org.eclipse.emf.internal.cdo.messages.Messages; import org.eclipse.emf.internal.cdo.session.CDOViewContainerImpl; import org.eclipse.net4j.util.StringUtil; import org.eclipse.net4j.util.WrappedException; import org.eclipse.net4j.util.collection.Pair; import org.eclipse.net4j.util.container.Container; import org.eclipse.net4j.util.om.OMPlatform; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.spi.cdo.InternalCDOView; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.Platform; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * When instanced in Eclipse, it's populated with contributions from the viewProvider Extension Point. A default * CDOViewProvider implementation is registered, regardless of the execution environment. * * @author Victor Roldan Betancort * @since 2.0 * @see CDOViewProvider */ public class CDOViewProviderRegistryImpl extends Container<CDOViewProvider> implements CDOViewProviderRegistry { public static final CDOViewProviderRegistryImpl INSTANCE = new CDOViewProviderRegistryImpl(); private static final String EXT_POINT = "viewProviders"; //$NON-NLS-1$ private List<CDOViewProvider> viewProviders = new ArrayList<CDOViewProvider>(); public CDOViewProviderRegistryImpl() { addViewProvider(PluginContainerViewProvider.INSTANCE); } public CDOView provideView(URI uri, ResourceSet resourceSet) { if (uri == null) { return null; } CDOViewSet viewSet = CDOUtil.getViewSet(resourceSet); // if (viewSet != null) // { // try // { // String uuid = CDOURIUtil.extractRepositoryUUID(uri); // CDOView view = viewSet.resolveView(uuid); // if (view != null) // { // return view; // } // } // catch (Exception ignore) // { // // Do nothing // } // } for (CDOViewProvider viewProvider : getViewProviders(uri)) { InternalCDOView view = provideView(uri, resourceSet, viewSet, viewProvider); if (view != null) { CDOViewProvider provider = view.getProvider(); if (provider != null) { if (provider != viewProvider) { throw new IllegalStateException("View providers don't match"); } } else { view.setProvider(viewProvider); } return view; } } return null; } private InternalCDOView provideView(URI uri, ResourceSet resourceSet, CDOViewSet viewSet, CDOViewProvider viewProvider) { if (viewSet != null && viewProvider instanceof CDOViewProvider2) { URI viewURI; try { viewURI = ((CDOViewProvider2)viewProvider).getViewURI(uri); } catch (IllegalArgumentException ex) { throw new IllegalArgumentException(ex.getMessage() + ": " + uri, ex); } catch (Error ex) { throw ex; } try { InternalCDOView view = (InternalCDOView)viewSet.resolveView(viewURI); if (view != null) { return view; } } catch (Exception ex) { //$FALL-THROUGH$ } } try { CDOViewContainerImpl.VIEW_PROVIDER.set(viewProvider); InternalCDOView view = (InternalCDOView)viewProvider.getView(uri, resourceSet); if (view != null) { return view; } } finally { CDOViewContainerImpl.VIEW_PROVIDER.remove(); } return null; } @Deprecated public Pair<CDOView, CDOViewProvider> provideViewWithInfo(URI uri, ResourceSet resourceSet) { CDOView view = provideView(uri, resourceSet); if (view != null) { return Pair.create(view, view.getProvider()); } return null; } public CDOViewProvider[] getViewProviders(URI uri) { List<CDOViewProvider> result = new ArrayList<CDOViewProvider>(); synchronized (viewProviders) { for (CDOViewProvider viewProvider : viewProviders) { if (viewProvider.matchesRegex(uri)) { result.add(viewProvider); } } } // Sort highest priority first Collections.sort(result, new Comparator<CDOViewProvider>() { public int compare(CDOViewProvider o1, CDOViewProvider o2) { return -Integer.valueOf(o1.getPriority()).compareTo(o2.getPriority()); } }); return result.toArray(new CDOViewProvider[result.size()]); } public boolean hasViewProvider(CDOViewProvider viewProvider) { synchronized (viewProviders) { return viewProviders.contains(viewProvider); } } public void addViewProvider(CDOViewProvider viewProvider) { boolean added; synchronized (viewProviders) { added = !viewProviders.contains(viewProvider); if (added) { viewProviders.add(viewProvider); } } if (added) { fireElementAddedEvent(viewProvider); } } public void removeViewProvider(CDOViewProvider viewProvider) { boolean removed; synchronized (viewProviders) { removed = viewProviders.remove(viewProvider); } if (removed) { fireElementRemovedEvent(viewProvider); } } public CDOViewProvider[] getElements() { synchronized (viewProviders) { return viewProviders.toArray(new CDOViewProvider[viewProviders.size()]); } } @Override public boolean isEmpty() { synchronized (viewProviders) { return viewProviders.isEmpty(); } } @Override protected void doActivate() throws Exception { super.doActivate(); if (OMPlatform.INSTANCE.isOSGiRunning()) { try { readExtensions(); } catch (Throwable t) { OM.LOG.error(t); } } } public void readExtensions() { IExtensionRegistry registry = Platform.getExtensionRegistry(); IConfigurationElement[] configurationElements = registry.getConfigurationElementsFor(OM.BUNDLE_ID, EXT_POINT); for (IConfigurationElement element : configurationElements) { try { CDOViewProviderDescriptor descriptor = new CDOViewProviderDescriptor(element); addViewProvider(descriptor); } catch (Exception ex) { OM.LOG.error(ex); } } } /** * @author Eike Stepper */ public static final class CDOViewProviderDescriptor extends AbstractCDOViewProvider { private IConfigurationElement element; public CDOViewProviderDescriptor(IConfigurationElement element) { super(getRegex(element), getPriority(element)); this.element = element; if (StringUtil.isEmpty(element.getAttribute("class"))) //$NON-NLS-1$ { throw new IllegalArgumentException(MessageFormat.format(Messages.getString("CDOViewProviderRegistryImpl.4"), element)); //$NON-NLS-1$ } } public CDOView getView(URI uri, ResourceSet resourceSet) { return getViewProvider().getView(uri, resourceSet); } @Override public URI getResourceURI(CDOView view, String path) { return getViewProvider().getResourceURI(view, path); } @Override public URI getViewURI(URI uri) { CDOViewProvider viewProvider = getViewProvider(); if (viewProvider instanceof CDOViewProvider2) { return ((CDOViewProvider2)viewProvider).getViewURI(uri); } return super.getViewURI(uri); } @Override public String getPath(URI uri) { CDOViewProvider viewProvider = getViewProvider(); if (viewProvider instanceof CDOViewProvider2) { return ((CDOViewProvider2)viewProvider).getPath(uri); } return super.getPath(uri); } private CDOViewProvider getViewProvider() { try { return (CDOViewProvider)element.createExecutableExtension("class"); //$NON-NLS-1$ } catch (CoreException ex) { throw WrappedException.wrap(ex); } } private static String getRegex(IConfigurationElement element) { String value = element.getAttribute("regex"); if (StringUtil.isEmpty(value)) { throw new IllegalArgumentException(MessageFormat.format(Messages.getString("CDOViewProviderRegistryImpl.6"), element)); //$NON-NLS-1$ } return value; } private static int getPriority(IConfigurationElement element) { try { String value = element.getAttribute("priority"); return Integer.parseInt(value); } catch (Exception ex) { return DEFAULT_PRIORITY; } } } }