/******************************************************************************* * Copyright (c) 2009-2013 CWI * 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: * * Davy Landman - Davy.Landman@cwi.nl *******************************************************************************/ package org.rascalmpl.uri; import java.io.File; import java.net.URI; import java.net.URISyntaxException; import org.rascalmpl.value.ISourceLocation; import org.rascalmpl.value.IValueFactory; import org.rascalmpl.values.ValueFactoryFactory; public class URIUtil { private static final IValueFactory vf = ValueFactoryFactory.getValueFactory(); /** * Create a new URI, non-encoded input is assumed. * @throws URISyntaxException */ public static URI create(String scheme, String authority, String path, String query, String fragment) throws URISyntaxException { return fixUnicode(new URI(scheme, authority, path, query, fragment)); } /** * Create a new URI, non-encoded input is assumed. * This is a shorthand for common cases were the query and fragment part are empty. * @throws URISyntaxException */ public static URI create(String scheme, String authority, String path) throws URISyntaxException { return create(scheme, authority, path, null, null); } /** * Create a new URI, non-encoded input is assumed. * This is a version in case of a scheme which has a server-based authority part. * And thus allows to set user information, host, and port. * @throws URISyntaxException */ public static URI create(String scheme, String userInformation, String host, int port, String path, String query, String fragment) throws URISyntaxException { return fixUnicode(new URI(scheme, userInformation, host, port, path, query, fragment)); } /** * Shorthand for creating a file:// URI, non-encoded input is assumed. * @throws URISyntaxException */ public static URI createFile(String path) throws URISyntaxException { path = fixWindowsPath(path); return fixUnicode(new URI("file","", path, null)); } public static ISourceLocation createFileLocation(String path) throws URISyntaxException { return vf.sourceLocation(createFile(path)); } private static String fixWindowsPath(String path) { if (!path.startsWith("/")) { path = "/" + path; } return path; } /** * Create a rascal module URI, moduleName is assumed to be correct. */ @Deprecated public static URI createRascalModule(String moduleName) { return assumeCorrect("rascal", moduleName, ""); } /** * Create a URI from a string which already contains an fully encoded URI */ public static URI createFromEncoded(String value) throws URISyntaxException { return fixUnicode(new URI(value)); } /** * The non throwing variant of <a>createFromEncoded</a> */ public static URI assumeCorrect(String value) { try { return createFromEncoded(value); } catch (URISyntaxException e) { IllegalArgumentException y = new IllegalArgumentException(); y.initCause(e); throw y; } } /** * Non throwing variant of <a>create</a>, in case of scenarios where input can be trusted. */ public static URI assumeCorrect(String scheme, String authority, String path) { try { return create(scheme, authority, path); } catch (URISyntaxException e) { IllegalArgumentException y = new IllegalArgumentException(); y.initCause(e); throw y; } } public static ISourceLocation correctLocation(String scheme, String authority, String path) { try { return createLocation(scheme, authority, path); } catch (URISyntaxException e) { IllegalArgumentException y = new IllegalArgumentException(); y.initCause(e); throw y; } } private static ISourceLocation createLocation(String scheme, String authority, String path) throws URISyntaxException { return vf.sourceLocation(scheme, authority, path); } private static final URI invalidURI = URI.create("unknown:///"); /** * Returns an URI which cannot be read/write to. * @return */ public static URI invalidURI() { return invalidURI; } private static final ISourceLocation invalidLocation = vf.sourceLocation(invalidURI); public static ISourceLocation invalidLocation() { return invalidLocation; } /** * Create a URI with only a scheme part set * @param scheme * @return */ public static URI rootScheme(String scheme) { return URI.create(scheme + ":///"); } public static ISourceLocation rootLocation(String scheme) { try { return vf.sourceLocation(scheme, "", "/"); } catch (URISyntaxException e) { assert false; return null; } } /** * In case you want to use an external URI not created by this class, call this method to ensure RFC compliant unicode support. * @throws URISyntaxException */ public static URI fixUnicode(URI uri) throws URISyntaxException { return new URI(uri.toASCIIString()); } private static String getCorrectAuthority(URI uri) { if (uri.getAuthority() == null) { return ""; } return uri.getAuthority(); } private static String getCorrectAuthority(ISourceLocation uri) { if (!uri.hasAuthority()) { return ""; } return uri.getAuthority(); } public static URI changeScheme(URI uri, String newScheme) throws URISyntaxException { return create(newScheme, getCorrectAuthority(uri), uri.getPath(), uri.getQuery(), uri.getFragment()); } public static ISourceLocation changeScheme(ISourceLocation loc, String newScheme) throws URISyntaxException { ISourceLocation newLoc = vf.sourceLocation(newScheme, getCorrectAuthority(loc), loc.getPath(), loc.hasQuery() ? loc.getQuery() : null, loc.hasFragment() ? loc.getFragment() : null); if (loc.hasLineColumn()) { newLoc = vf.sourceLocation(newLoc, loc.getOffset(), loc.getLength(), loc.getBeginLine(), loc.getEndLine(), loc.getBeginColumn(), loc.getEndColumn()); } else if (loc.hasOffsetLength()) { newLoc = vf.sourceLocation(newLoc, loc.getOffset(), loc.getLength()); } return newLoc; } public static URI changeAuthority(URI uri, String newAuthority) throws URISyntaxException { return create(uri.getScheme(), newAuthority == null ? "" : newAuthority, uri.getPath(), uri.getQuery(), uri.getFragment()); } public static URI changePath(URI uri, String newPath) throws URISyntaxException { return create(uri.getScheme(), getCorrectAuthority(uri), newPath, uri.getQuery(), uri.getFragment()); } public static ISourceLocation changePath(ISourceLocation uri, String newPath) throws URISyntaxException { return vf.sourceLocation(uri.getScheme(), getCorrectAuthority(uri), newPath, uri.getQuery(), uri.getFragment()); } public static URI changeQuery(URI uri, String newQuery) throws URISyntaxException { return create(uri.getScheme(), getCorrectAuthority(uri), uri.getPath(), newQuery, uri.getFragment()); } public static ISourceLocation changeQuery(ISourceLocation uri, String newQuery) throws URISyntaxException { return vf.sourceLocation(uri.getScheme(), getCorrectAuthority(uri), uri.getPath(), newQuery, uri.getFragment()); } public static URI changeFragment(URI uri, String newFragment) throws URISyntaxException { return create(uri.getScheme(), getCorrectAuthority(uri), uri.getPath(), uri.getQuery(), newFragment); } /* special server-authority URI constructors */ public static URI changeUserInformation(URI uri, String newUserInformation) throws URISyntaxException { return create(uri.getScheme(), newUserInformation, uri.getHost(), uri.getPort(), uri.getPath(), uri.getQuery(), uri.getFragment()); } public static URI changeHost(URI uri, String newHost) throws URISyntaxException { return create(uri.getScheme(), uri.getUserInfo(), newHost, uri.getPort(), uri.getPath(), uri.getQuery(), uri.getFragment()); } public static URI changePort(URI uri, int newPort) throws URISyntaxException { return create(uri.getScheme(), uri.getUserInfo(), uri.getHost(), newPort, uri.getPath(), uri.getQuery(), uri.getFragment()); } /** * @return a parent uri or null if there is none */ public static URI getParentURI(URI uri) { File file = new File(uri.getPath()); File parent = file.getParentFile(); if (parent != null && !parent.getName().isEmpty()) { try { return changePath(uri, parent.getAbsolutePath()); } catch (URISyntaxException e) { // can not happen } } return null; // there is no parent; } public static ISourceLocation getParentLocation(ISourceLocation loc) { File file = new File(loc.getPath()); File parent = file.getParentFile(); if (parent != null && !parent.getName().isEmpty()) { try { return vf.sourceLocation(loc.getScheme(), getCorrectAuthority(loc), parent.getPath(), loc.hasQuery() ? loc.getQuery() : null, loc.hasFragment() ? loc.getFragment() : null); } catch (URISyntaxException e) { assert false; return loc; } } return loc; } public static ISourceLocation getChildLocation(ISourceLocation loc, String child) { String childPath = loc.getPath(); if (childPath == null || childPath.isEmpty()) { childPath = "/"; } else if (!childPath.endsWith("/")) { childPath += "/"; } childPath += child; try { return vf.sourceLocation(loc.getScheme(), getCorrectAuthority(loc), childPath, loc.hasQuery() ? loc.getQuery() : null, loc.hasFragment() ? loc.getFragment() : null); } catch (URISyntaxException e) { assert false; return loc; } } public static URI getChildURI(URI uri, String child) { File file = new File(uri.getPath()); File childFile = new File(file, child); try { return changePath(uri, childFile.getAbsolutePath()); } catch (URISyntaxException e) { // can not happen } return null; // there is no child?; } public static String getURIName(URI uri) { File file = new File(uri.getPath()); return file.getName(); } public static String getLocationName(ISourceLocation uri) { File file = new File(uri.getPath()); return file.getName(); } public static ISourceLocation removeAuthority(ISourceLocation loc) { try { ISourceLocation res = vf.sourceLocation(loc.getScheme(),"", loc.getPath(), loc.hasQuery() ? loc.getQuery() : null, loc.hasFragment()? loc.getFragment() : null); if (loc.hasLineColumn()) { return vf.sourceLocation(res, loc.getOffset(), loc.getLength(), loc.getBeginLine(), loc.getEndLine(), loc.getBeginColumn(), loc.getEndColumn()); } if (loc.hasOffsetLength()) { return vf.sourceLocation(res, loc.getOffset(), loc.getLength(), loc.getBeginLine(), loc.getEndLine(), loc.getBeginColumn(), loc.getEndColumn()); } return res; } catch (UnsupportedOperationException | URISyntaxException e) { assert false; // can't happen return loc; } } public static ISourceLocation removeOffset(ISourceLocation prev) { return prev.top(); } }