/* * Copyright 2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.gradle.api.internal.file; import org.gradle.api.UncheckedIOException; import org.gradle.internal.exceptions.DiagnosticsVisitor; import org.gradle.internal.nativeintegration.filesystem.FileSystem; import org.gradle.internal.typeconversion.*; import java.io.File; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Path; import java.util.regex.Matcher; import java.util.regex.Pattern; public class FileOrUriNotationConverter implements NotationConverter<Object, Object> { private static final Pattern URI_SCHEME = Pattern.compile("[a-zA-Z][a-zA-Z0-9+-\\.]*:.+"); private static final Pattern ENCODED_URI = Pattern.compile("%([0-9a-fA-F]{2})"); private final FileSystem fileSystem; public FileOrUriNotationConverter(FileSystem fileSystem) { this.fileSystem = fileSystem; } public static NotationParser<Object, Object> parser(FileSystem fileSystem) { return NotationParserBuilder .toType(Object.class) .typeDisplayName("a File or URI") .converter(new FileOrUriNotationConverter(fileSystem)) .toComposite(); } @Override public void describe(DiagnosticsVisitor visitor) { visitor.candidate("A String or CharSequence path").example("'src/main/java' or '/usr/include'"); visitor.candidate("A String or CharSequence URI").example("'file:/usr/include'"); visitor.candidate("A File instance."); visitor.candidate("A Path instance."); visitor.candidate("A URI or URL instance."); } public void convert(Object notation, NotationConvertResult<? super Object> result) throws TypeConversionException { if (notation instanceof File) { result.converted(notation); return; } if (notation instanceof Path) { result.converted(((Path)notation).toFile()); return; } if (notation instanceof URL) { try { notation = ((URL) notation).toURI(); } catch (URISyntaxException e) { throw new UncheckedIOException(e); } } if (notation instanceof URI) { URI uri = (URI) notation; if (uri.getScheme().equals("file")) { result.converted(new File(uri.getPath())); } else { result.converted(uri); } return; } if (notation instanceof CharSequence) { String notationString = notation.toString(); if (notationString.startsWith("file:")) { result.converted(new File(uriDecode(notationString.substring(5)))); return; } for (File file : File.listRoots()) { String rootPath = file.getAbsolutePath(); String normalisedStr = notationString; if (!fileSystem.isCaseSensitive()) { rootPath = rootPath.toLowerCase(); normalisedStr = normalisedStr.toLowerCase(); } if (normalisedStr.startsWith(rootPath) || normalisedStr.startsWith(rootPath.replace(File.separatorChar, '/'))) { result.converted(new File(notationString)); return; } } // Check if string starts with a URI scheme if (URI_SCHEME.matcher(notationString).matches()) { try { result.converted(new URI(notationString)); return; } catch (URISyntaxException e) { throw new UncheckedIOException(e); } } result.converted(new File(notationString)); } } private String uriDecode(String path) { StringBuffer builder = new StringBuffer(); Matcher matcher = ENCODED_URI.matcher(path); while (matcher.find()) { String val = matcher.group(1); matcher.appendReplacement(builder, String.valueOf((char) (Integer.parseInt(val, 16)))); } matcher.appendTail(builder); return builder.toString(); } }