/* * Copyright (c) 2008-2012, 2015, 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: * Simon McDuff - initial API and implementation * Eike Stepper - maintenance */ package org.eclipse.emf.cdo.util; import org.eclipse.emf.cdo.common.CDOCommonRepository; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.id.CDOIDUtil; import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; import org.eclipse.emf.cdo.eresource.CDOResource; import org.eclipse.emf.cdo.session.CDOSession; 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.internal.cdo.view.PluginContainerViewProvider; import org.eclipse.net4j.util.StringUtil; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.ResourceSet; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; /** * Various static methods that may help with CDO-specific {@link URI URIs}. * <p> * CDO URIs are in one of two different formats, either canonical or connection-aware. The canonical format is: * * <blockquote><b>cdo://</b> <i>RepositoryUUID</i> <b>/</b> <i>ResourcePath</i> [<b>?</b> <i>Param</i><b>=</b><i>Value</i> * (<b>&</b> <i>Param</i><b>=</b><i>Value</i>)*]</blockquote> * * The non-terminals being: * <p> * <ul> * <li><i>RepositoryUUID</i>: the {@link CDOCommonRepository#getUUID() UUID} of the repository. By default it's generated when a repository is first started. * If the default format is not adequate the UUID value can be overridden in the repository setup with the <code>overrideUUID</code> property. * <li><i>ResourcePath</i>: the full path of the {@link CDOResource resource} within the repository, segments separated by slashes, no leading slash. * <li><i>Param</i>: one of the following * <ul> * <li><b>prefetch</b>: a boolean value. The value <b>true</b> attempts to load all objects contained by the resource in a single server-round trip and cache the results. * </ul> * </ul> * * URIs in the canonical form to resolve to {@link CDOResource resources} properly require the {@link ResourceSet resource set} to be * configured <i>externally</i> so that the connection to the correct repository can be established, for example: * <blockquote><code>session.openView(resourceSet);</code></blockquote> * * Note that resources preserve their original URI in the scope of the managing {@link CDOView view}, that is not necessarily in canonical format. * <p> * For a description of the connection-aware URI format refer to {@link CDOURIData}. * * @author Simon McDuff * @since 2.0 */ public final class CDOURIUtil { /** * @since 4.0 */ public static final String PROTOCOL_NAME = CDOProtocolConstants.PROTOCOL_NAME; public static final char SEGMENT_SEPARATOR_CHAR = '/'; public static final String SEGMENT_SEPARATOR = new String(new char[] { SEGMENT_SEPARATOR_CHAR }); static { CDOUtil.registerResourceFactory(null); // Ensure that the normal resource factory is registered } private CDOURIUtil() { } /** * @deprecated */ @Deprecated public static void validateURI(URI uri) throws InvalidURIException { // if (!CDOProtocolConstants.PROTOCOL_NAME.equals(uri.scheme())) // { // throw new InvalidURIException(uri); // } // // if (!uri.isHierarchical()) // { // throw new InvalidURIException(uri); // } } /** * @deprecated */ @Deprecated public static String extractRepositoryUUID(URI uri) { return PluginContainerViewProvider.getRepositoryUUID(uri); } public static String[] extractResourceFolderAndName(URI uri) throws InvalidURIException { String path = extractResourcePath(uri); int lastSeparator = path.lastIndexOf(SEGMENT_SEPARATOR_CHAR); if (lastSeparator == -1) { return new String[] { null, path }; } String folder = path.substring(0, lastSeparator); String name = path.substring(lastSeparator + 1); return new String[] { folder, name }; } public static String extractResourcePath(URI uri) throws InvalidURIException { CDOViewProvider[] viewProviders = CDOViewProviderRegistry.INSTANCE.getViewProviders(uri); if (viewProviders != null) { for (int i = 0; i < viewProviders.length; i++) { if (viewProviders[i] instanceof CDOViewProvider2) { CDOViewProvider2 viewProvider = (CDOViewProvider2)viewProviders[i]; String path = viewProvider.getPath(uri); if (path != null && !StringUtil.isEmpty(path)) { return path; } } } } if (!PROTOCOL_NAME.equals(uri.scheme())) { CDOURIData data = new CDOURIData(uri); return data.getResourcePath().toPortableString(); } String path = uri.path(); if (path == null) { return SEGMENT_SEPARATOR; } return path; } /** * <p> * cdo://repositoryUUID/path * <p> * The path is added at the end of "cdo://repositoryUUID". If path doesn't start with '/', it will be added * automatically. <br> * e.g.: /resA or resA will give the same result → cdo://repositoryUUID/resA <br> * authority = repositoryUUID <br> * path = /resA * * @deprecated This method is subject to removal in a future release. */ @Deprecated public static URI createResourceURI(String repositoryUUID, String path) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(PROTOCOL_NAME); stringBuilder.append(":"); //$NON-NLS-1$ if (repositoryUUID != null) { stringBuilder.append("//"); //$NON-NLS-1$ stringBuilder.append(repositoryUUID); } if (!SEGMENT_SEPARATOR.equals(path)) { if (path.charAt(0) != SEGMENT_SEPARATOR_CHAR) { stringBuilder.append(SEGMENT_SEPARATOR_CHAR); } stringBuilder.append(path); } return URI.createURI(stringBuilder.toString()); } public static URI createResourceURI(CDOView view, String path) { return view == null ? null : view.createResourceURI(path); } /** * @deprecated This method is subject to removal in a future release. */ @Deprecated public static URI createResourceURI(CDOSession session, String path) { return createResourceURI(session == null ? null : session.getRepositoryInfo().getUUID(), path); } /** * Converting temporary CDOID to External CDOID <br> * e.g.: <br> * baseURI = cdo://2a57dfcf-8f97-4d39-8e17-9d99ae5c4b3c/resB#5/2<br> * newCDOID = OID2<br> * return = cdo://2a57dfcf-8f97-4d39-8e17-9d99ae5c4b3c/resB#1/2 */ public static CDOID convertExternalCDOID(URI baseURI, CDOID newCDOID) { StringBuilder builder = new StringBuilder(); CDOIDUtil.write(builder, newCDOID); baseURI = baseURI.trimFragment().appendFragment(builder.toString()); return CDOIDUtil.createExternal(baseURI.toString()); } public static List<String> analyzePath(URI uri) { String path = extractResourcePath(uri); return analyzePath(path); } public static List<String> analyzePath(String path) { List<String> segments = new ArrayList<String>(); StringTokenizer tokenizer = new StringTokenizer(path, CDOURIUtil.SEGMENT_SEPARATOR); while (tokenizer.hasMoreTokens()) { String name = tokenizer.nextToken(); if (name != null) { segments.add(name); } } return segments; } /** * @since 4.0 */ public static Map<String, String> getParameters(String query) { Map<String, String> result = new HashMap<String, String>(); StringTokenizer tokenizer = new StringTokenizer(query, "&"); //$NON-NLS-1$ while (tokenizer.hasMoreTokens()) { String parameter = tokenizer.nextToken(); if (!StringUtil.isEmpty(parameter)) { int pos = parameter.indexOf('='); if (pos == -1) { String key = parameter.trim(); result.put(key, ""); //$NON-NLS-1$ } else { String key = parameter.substring(0, pos).trim(); String value = parameter.substring(pos + 1); result.put(key, value); } } } return result; } }