001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.transport.file; 020 021import javax.inject.Named; 022 023import java.io.IOException; 024import java.io.UncheckedIOException; 025import java.net.URI; 026import java.nio.file.FileSystem; 027import java.nio.file.FileSystemNotFoundException; 028import java.nio.file.FileSystems; 029import java.nio.file.Path; 030import java.nio.file.Paths; 031import java.util.HashMap; 032import java.util.Map; 033 034import org.eclipse.aether.RepositorySystemSession; 035import org.eclipse.aether.repository.RemoteRepository; 036import org.eclipse.aether.repository.RepositoryUriUtils; 037import org.eclipse.aether.spi.connector.transport.Transporter; 038import org.eclipse.aether.spi.connector.transport.TransporterFactory; 039import org.eclipse.aether.transfer.NoTransporterException; 040 041import static java.util.Objects.requireNonNull; 042 043/** 044 * A transporter factory for repositories using the {@code file:} or {@code bundle:} protocol. 045 */ 046@Named(FileTransporterFactory.NAME) 047public final class FileTransporterFactory implements TransporterFactory { 048 public static final String NAME = "file"; 049 050 private float priority; 051 052 @Override 053 public float getPriority() { 054 return priority; 055 } 056 057 /** 058 * Sets the priority of this component. 059 * 060 * @param priority The priority. 061 * @return This component for chaining, never {@code null}. 062 */ 063 public FileTransporterFactory setPriority(float priority) { 064 this.priority = priority; 065 return this; 066 } 067 068 /** 069 * Creates new instance of {@link FileTransporter}. 070 * 071 * @param session The session. 072 * @param repository The remote repository. 073 */ 074 @Override 075 public Transporter newInstance(RepositorySystemSession session, RemoteRepository repository) 076 throws NoTransporterException { 077 requireNonNull(session, "session cannot be null"); 078 requireNonNull(repository, "repository cannot be null"); 079 080 String repositoryUrl = repository.getUrl(); 081 if (repositoryUrl.startsWith("bundle:")) { 082 try { 083 repositoryUrl = repositoryUrl.substring("bundle:".length()); 084 URI bundlePath = URI.create("jar:" 085 + Paths.get(RepositoryUriUtils.toUri(repositoryUrl)) 086 .toAbsolutePath() 087 .toUri() 088 .toASCIIString()); 089 Map<String, String> env = new HashMap<>(); 090 FileSystem fileSystem = FileSystems.newFileSystem(bundlePath, env); 091 return new FileTransporter( 092 fileSystem, 093 true, 094 false, 095 fileSystem.getPath(fileSystem.getSeparator()), 096 FileTransporter.WriteOp.COPY); 097 } catch (IOException e) { 098 throw new UncheckedIOException(e); // hard failure; most probably user error (ie wrong path or perm) 099 } 100 } else { 101 // special case in file: transport: to support custom FS providers (like JIMFS), we cannot 102 // cover all possible protocols (to throw NoTransporterEx), hence we rely on FS rejecting the URI 103 FileTransporter.WriteOp writeOp = FileTransporter.WriteOp.COPY; 104 if (repositoryUrl.startsWith("symlink+")) { 105 writeOp = FileTransporter.WriteOp.SYMLINK; 106 repositoryUrl = repositoryUrl.substring("symlink+".length()); 107 } else if (repositoryUrl.startsWith("hardlink+")) { 108 writeOp = FileTransporter.WriteOp.HARDLINK; 109 repositoryUrl = repositoryUrl.substring("hardlink+".length()); 110 } 111 try { 112 Path basePath = 113 Paths.get(RepositoryUriUtils.toUri(repositoryUrl)).toAbsolutePath(); 114 return new FileTransporter( 115 basePath.getFileSystem(), 116 false, 117 !basePath.getFileSystem().isReadOnly(), 118 basePath, 119 writeOp); 120 } catch (FileSystemNotFoundException | IllegalArgumentException e) { 121 throw new NoTransporterException(repository, e); 122 } 123 } 124 } 125}