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.util.repository; 020 021import java.io.File; 022import java.util.ArrayList; 023import java.util.Collection; 024import java.util.Collections; 025import java.util.LinkedHashSet; 026import java.util.List; 027 028import org.eclipse.aether.artifact.Artifact; 029import org.eclipse.aether.repository.WorkspaceReader; 030import org.eclipse.aether.repository.WorkspaceRepository; 031 032import static java.util.Objects.requireNonNull; 033 034/** 035 * A workspace reader that delegates to a chain of other readers, effectively aggregating their contents. 036 */ 037public final class ChainedWorkspaceReader implements WorkspaceReader { 038 039 private final List<WorkspaceReader> readers = new ArrayList<>(); 040 041 private WorkspaceRepository repository; 042 043 /** 044 * Creates a new workspace reader by chaining the specified readers. 045 * 046 * @param readers The readers to chain, may be {@code null}. 047 * @see #newInstance(WorkspaceReader, WorkspaceReader) 048 */ 049 public ChainedWorkspaceReader(WorkspaceReader... readers) { 050 if (readers != null) { 051 Collections.addAll(this.readers, readers); 052 } 053 054 StringBuilder buffer = new StringBuilder(); 055 for (WorkspaceReader reader : this.readers) { 056 if (buffer.length() > 0) { 057 buffer.append('+'); 058 } 059 buffer.append(reader.getRepository().getContentType()); 060 } 061 062 repository = new WorkspaceRepository(buffer.toString(), new Key(this.readers)); 063 } 064 065 /** 066 * Creates a new workspace reader by chaining the specified readers. In contrast to the constructor, this factory 067 * method will avoid creating an actual chained reader if one of the specified readers is actually {@code null}. 068 * 069 * @param reader1 The first workspace reader, may be {@code null}. 070 * @param reader2 The second workspace reader, may be {@code null}. 071 * @return The chained reader or {@code null} if no workspace reader was supplied. 072 */ 073 public static WorkspaceReader newInstance(WorkspaceReader reader1, WorkspaceReader reader2) { 074 if (reader1 == null) { 075 return reader2; 076 } else if (reader2 == null) { 077 return reader1; 078 } 079 return new ChainedWorkspaceReader(reader1, reader2); 080 } 081 082 public File findArtifact(Artifact artifact) { 083 requireNonNull(artifact, "artifact cannot be null"); 084 File file = null; 085 086 for (WorkspaceReader reader : readers) { 087 file = reader.findArtifact(artifact); 088 if (file != null) { 089 break; 090 } 091 } 092 093 return file; 094 } 095 096 public List<String> findVersions(Artifact artifact) { 097 requireNonNull(artifact, "artifact cannot be null"); 098 Collection<String> versions = new LinkedHashSet<>(); 099 100 for (WorkspaceReader reader : readers) { 101 versions.addAll(reader.findVersions(artifact)); 102 } 103 104 return Collections.unmodifiableList(new ArrayList<>(versions)); 105 } 106 107 public WorkspaceRepository getRepository() { 108 Key key = new Key(readers); 109 if (!key.equals(repository.getKey())) { 110 repository = new WorkspaceRepository(repository.getContentType(), key); 111 } 112 return repository; 113 } 114 115 private static class Key { 116 117 private final List<Object> keys = new ArrayList<>(); 118 119 Key(List<WorkspaceReader> readers) { 120 for (WorkspaceReader reader : readers) { 121 keys.add(reader.getRepository().getKey()); 122 } 123 } 124 125 @Override 126 public boolean equals(Object obj) { 127 if (this == obj) { 128 return true; 129 } 130 if (obj == null || !getClass().equals(obj.getClass())) { 131 return false; 132 } 133 return keys.equals(((Key) obj).keys); 134 } 135 136 @Override 137 public int hashCode() { 138 return keys.hashCode(); 139 } 140 } 141}