Coverage Report - de.smartics.properties.resource.maven.repository.MavenRepository
 
Classes in this File Line Coverage Branch Coverage Complexity
MavenRepository
0%
0/74
0%
0/8
1.667
 
 1  
 /*
 2  
  * Copyright 2012-2013 smartics, Kronseder & Reiner GmbH
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package de.smartics.properties.resource.maven.repository;
 17  
 
 18  
 import java.io.File;
 19  
 import java.net.MalformedURLException;
 20  
 import java.net.URI;
 21  
 import java.net.URL;
 22  
 import java.util.ArrayList;
 23  
 import java.util.List;
 24  
 
 25  
 import org.apache.commons.lang.StringUtils;
 26  
 import org.apache.maven.repository.internal.DefaultArtifactDescriptorReader;
 27  
 import org.apache.maven.repository.internal.DefaultVersionRangeResolver;
 28  
 import org.apache.maven.repository.internal.DefaultVersionResolver;
 29  
 import org.apache.maven.repository.internal.MavenRepositorySystemSession;
 30  
 import org.sonatype.aether.RepositorySystem;
 31  
 import org.sonatype.aether.RepositorySystemSession;
 32  
 import org.sonatype.aether.artifact.Artifact;
 33  
 import org.sonatype.aether.collection.CollectRequest;
 34  
 import org.sonatype.aether.connector.file.FileRepositoryConnectorFactory;
 35  
 import org.sonatype.aether.connector.wagon.WagonProvider;
 36  
 import org.sonatype.aether.connector.wagon.WagonRepositoryConnectorFactory;
 37  
 import org.sonatype.aether.graph.Dependency;
 38  
 import org.sonatype.aether.graph.DependencyFilter;
 39  
 import org.sonatype.aether.graph.DependencyNode;
 40  
 import org.sonatype.aether.impl.ArtifactDescriptorReader;
 41  
 import org.sonatype.aether.impl.VersionRangeResolver;
 42  
 import org.sonatype.aether.impl.VersionResolver;
 43  
 import org.sonatype.aether.impl.internal.DefaultServiceLocator;
 44  
 import org.sonatype.aether.repository.Authentication;
 45  
 import org.sonatype.aether.repository.LocalRepository;
 46  
 import org.sonatype.aether.repository.RemoteRepository;
 47  
 import org.sonatype.aether.resolution.DependencyRequest;
 48  
 import org.sonatype.aether.resolution.DependencyResolutionException;
 49  
 import org.sonatype.aether.resolution.DependencyResult;
 50  
 import org.sonatype.aether.spi.connector.RepositoryConnectorFactory;
 51  
 import org.sonatype.aether.util.graph.PreorderNodeListGenerator;
 52  
 
 53  
 import de.smartics.properties.resource.domain.ArtifactId;
 54  
 import de.smartics.properties.resource.domain.ArtifactRef;
 55  
 import de.smartics.properties.resource.domain.ClassPathEnvironment;
 56  
 
 57  
 /**
 58  
  * The repository to access artifacts to resolve for property descriptor
 59  
  * information.
 60  
  */
 61  
 public final class MavenRepository
 62  
 { // NOPMD
 63  
   // ********************************* Fields *********************************
 64  
 
 65  
   // --- constants ------------------------------------------------------------
 66  
 
 67  
   // --- members --------------------------------------------------------------
 68  
 
 69  
   /**
 70  
    * The remote artifact repository.
 71  
    */
 72  
   private final RemoteRepository remoteRepository;
 73  
 
 74  
   /**
 75  
    * The local artifact repository, where the remote artifacts are stored.
 76  
    */
 77  
   private final LocalRepository localRepository;
 78  
 
 79  
   /**
 80  
    * The internal repository system as the interface to the repository access
 81  
    * implementation.
 82  
    */
 83  
   private final RepositorySystem repositorySystem;
 84  
 
 85  
   /**
 86  
    * The list of dependency filters to apply to the dependency request.
 87  
    */
 88  
   private final List<DependencyFilter> dependencyFilters;
 89  
 
 90  
   /**
 91  
    * The flag to control accessing the local repository only.
 92  
    */
 93  
   private final boolean offline;
 94  
 
 95  
   // ****************************** Initializer *******************************
 96  
 
 97  
   // ****************************** Constructors ******************************
 98  
 
 99  
   /**
 100  
    * Convenience constructor without dependency filters and no authentication.
 101  
    *
 102  
    * @param remoteRepositoryUrl the URL to the remote repository of artifacts.
 103  
    * @param localRepositoryPath the directory path to the local repository of
 104  
    *          artifacts.
 105  
    */
 106  
   public MavenRepository(final String remoteRepositoryUrl,
 107  
       final String localRepositoryPath)
 108  
   {
 109  0
     this(remoteRepositoryUrl, null, localRepositoryPath,
 110  
         new ArrayList<DependencyFilter>(), false);
 111  0
   }
 112  
 
 113  
   /**
 114  
    * Convenience constructor without dependency filters.
 115  
    *
 116  
    * @param remoteRepositoryUrl the URL to the remote repository of artifacts.
 117  
    * @param localRepositoryPath the directory path to the local repository of
 118  
    *          artifacts.
 119  
    */
 120  
   public MavenRepository(final String remoteRepositoryUrl,
 121  
       final Authentication auth, final String localRepositoryPath)
 122  
   {
 123  0
     this(remoteRepositoryUrl, auth, localRepositoryPath,
 124  
         new ArrayList<DependencyFilter>(), false);
 125  0
   }
 126  
 
 127  
   /**
 128  
    * Default constructor.
 129  
    *
 130  
    * @param remoteRepositoryUrl the URL to the remote repository of artifacts.
 131  
    * @param localRepositoryPath the directory path to the local repository of
 132  
    *          artifacts.
 133  
    * @param dependencyFilters the list of dependency filters to apply to the
 134  
    *          dependency request.
 135  
    */
 136  
   public MavenRepository(final String remoteRepositoryUrl,
 137  
       final Authentication auth, final String localRepositoryPath,
 138  
       final List<DependencyFilter> dependencyFilters, final boolean offline)
 139  0
   {
 140  0
     this.remoteRepository = createRemoteRepository(remoteRepositoryUrl, auth);
 141  0
     this.localRepository = createLocalRepository(localRepositoryPath);
 142  0
     this.repositorySystem = createRepositorySystem();
 143  0
     this.dependencyFilters = new ArrayList<DependencyFilter>(dependencyFilters);
 144  0
     this.offline = offline;
 145  0
   }
 146  
 
 147  
   // ****************************** Inner Classes *****************************
 148  
 
 149  
   // ********************************* Methods ********************************
 150  
 
 151  
   // --- init -----------------------------------------------------------------
 152  
 
 153  
   private static RemoteRepository createRemoteRepository(
 154  
       final String remoteRepositoryUrl, final Authentication auth)
 155  
   {
 156  0
     final RemoteRepository repo =
 157  
         new RemoteRepository("central", "default", remoteRepositoryUrl);
 158  0
     if (auth != null)
 159  
     {
 160  0
       repo.setAuthentication(auth);
 161  
     }
 162  0
     return repo;
 163  
   }
 164  
 
 165  
   private static LocalRepository createLocalRepository(
 166  
       final String localRepositoryPath)
 167  
   {
 168  0
     return new LocalRepository(localRepositoryPath);
 169  
   }
 170  
 
 171  
   private static RepositorySystem createRepositorySystem()
 172  
   {
 173  0
     final DefaultServiceLocator locator = new DefaultServiceLocator();
 174  
 
 175  0
     locator.addService(RepositoryConnectorFactory.class,
 176  
         FileRepositoryConnectorFactory.class);
 177  0
     locator.addService(RepositoryConnectorFactory.class,
 178  
         WagonRepositoryConnectorFactory.class);
 179  0
     locator.addService(VersionResolver.class, DefaultVersionResolver.class);
 180  0
     locator.addService(VersionRangeResolver.class,
 181  
         DefaultVersionRangeResolver.class);
 182  0
     locator.addService(ArtifactDescriptorReader.class,
 183  
         DefaultArtifactDescriptorReader.class);
 184  
 
 185  0
     locator.setServices(WagonProvider.class, new RepositoryWagonProvider());
 186  
 
 187  0
     return locator.getService(RepositorySystem.class);
 188  
   }
 189  
 
 190  
   // --- get&set --------------------------------------------------------------
 191  
 
 192  
   // --- business -------------------------------------------------------------
 193  
 
 194  
   /**
 195  
    * Creates a session to communicate with the repository.
 196  
    *
 197  
    * @return a new session instance.
 198  
    */
 199  
   public RepositorySystemSession createSession()
 200  
   {
 201  0
     final MavenRepositorySystemSession session =
 202  
         new MavenRepositorySystemSession();
 203  
 
 204  0
     session.setLocalRepositoryManager(repositorySystem
 205  
         .newLocalRepositoryManager(localRepository));
 206  0
     session.setOffline(offline);
 207  
 
 208  0
     session.setRepositoryListener(new ResourceRepositoryLogListener());
 209  
     // session.setTransferListener( new ConsoleTransferListener() );
 210  
 
 211  0
     return session;
 212  
   }
 213  
 
 214  
   /**
 215  
    * Resolves the artifact so that it is locally accessible.
 216  
    *
 217  
    * @param session the session used for communication.
 218  
    * @param artifact the artifact to resolve.
 219  
    * @return the reference to the resolved artifact that is now stored locally
 220  
    *         ready for access.
 221  
    * @throws DependencyResolutionException if the dependency tree could not be
 222  
    *           built or any dependency artifact could not be resolved.
 223  
    */
 224  
   public ClassPathEnvironment resolve(final RepositorySystemSession session,
 225  
       final Artifact artifact) throws DependencyResolutionException
 226  
   {
 227  0
     final Dependency dependency = createDependency(artifact);
 228  
 
 229  0
     final DependencyRequest dependencyRequest = createRequest(dependency);
 230  
 
 231  
     try
 232  
     {
 233  0
       final DependencyNode rootNode =
 234  
           repositorySystem.resolveDependencies(session, dependencyRequest)
 235  
               .getRoot();
 236  0
       final PreorderNodeListGenerator generator =
 237  
           new PreorderNodeListGenerator();
 238  0
       rootNode.accept(generator);
 239  
 
 240  0
       final ClassPathEnvironment resources = createResult(generator);
 241  0
       return resources;
 242  
     }
 243  0
     catch (final NullPointerException e) // NOPMD aether problem
 244  
     {
 245  
       // Only occurs if a parent dependency of the resource cannot be resolved
 246  
       // TODO We should log this information somehow...
 247  0
       throw new DependencyResolutionException(new DependencyResult(
 248  
           dependencyRequest), e);
 249  
     }
 250  
   }
 251  
 
 252  
   /**
 253  
    * Returns the URL to the remote repository.
 254  
    *
 255  
    * @return the URL to the remote repository.
 256  
    */
 257  
   public String getRemoteRepositoryUrl()
 258  
   {
 259  0
     return remoteRepository.getUrl();
 260  
   }
 261  
 
 262  
   private static Dependency createDependency(final Artifact artifact)
 263  
   {
 264  0
     final Dependency dependency = new Dependency(artifact, "runtime");
 265  0
     return dependency;
 266  
   }
 267  
 
 268  
   private DependencyRequest createRequest(final Dependency dependency)
 269  
   {
 270  0
     final CollectRequest collectRequest = new CollectRequest();
 271  0
     collectRequest.setRoot(dependency);
 272  0
     collectRequest.addRepository(remoteRepository);
 273  
 
 274  0
     final DependencyRequest dependencyRequest = new DependencyRequest();
 275  0
     dependencyRequest.setCollectRequest(collectRequest);
 276  0
     for (final DependencyFilter filter : dependencyFilters)
 277  
     {
 278  0
       dependencyRequest.setFilter(filter);
 279  
     }
 280  0
     return dependencyRequest;
 281  
   }
 282  
 
 283  
   private static ClassPathEnvironment createResult(
 284  
       final PreorderNodeListGenerator generator)
 285  
   {
 286  0
     final ClassPathEnvironment env = new ClassPathEnvironment();
 287  0
     final List<DependencyNode> nodes = generator.getNodes();
 288  
 
 289  
     // TODO: Should we copy the artifacts to a local folder?
 290  0
     for (final DependencyNode node : nodes)
 291  
     {
 292  0
       final ArtifactRef artifactRef = createArtifact(node);
 293  0
       env.addArchiveArtifactRef(artifactRef);
 294  0
     }
 295  
 
 296  
     // final PropertySetClassesLoader declarationLoader =
 297  
     // new PropertySetClassesLoader();
 298  
     // final Set<Class<?>> declarations =
 299  
     // declarationLoader.getPropertySetTypes(urls);
 300  
     //
 301  
     // final PropertiesFilesLoader definitionLoader = new
 302  
     // PropertiesFilesLoader();
 303  
     // final Set<String> definitions =
 304  
     // definitionLoader.getPropertiesFiles(urls);
 305  
     //
 306  
     // final PropertiesResources resources =
 307  
     // new PropertiesResources(env, declarations, definitions);
 308  
     // return resources;
 309  0
     return env;
 310  
   }
 311  
 
 312  
   private static URL toUrl(final File file) throws IllegalStateException
 313  
   {
 314  0
     final URI uri = file.toURI();
 315  
     try
 316  
     {
 317  0
       final URL url = uri.toURL();
 318  0
       return url;
 319  
     }
 320  0
     catch (final MalformedURLException e)
 321  
     {
 322  0
       throw new IllegalStateException("Cannot resolve URL: "
 323  
                                       + uri.toASCIIString(), e); // FIXME
 324  
     }
 325  
   }
 326  
 
 327  
   private static ArtifactRef createArtifact(final DependencyNode node)
 328  
   {
 329  0
     final Artifact artifact = node.getDependency().getArtifact();
 330  0
     final ArtifactId.Builder builder = new ArtifactId.Builder();
 331  0
     final String classifier = normalize(artifact);
 332  0
     builder.withGroupId(artifact.getGroupId())
 333  
         .withName(artifact.getArtifactId()).withVersion(artifact.getVersion())
 334  
         .withArchiveType(artifact.getExtension()).withClassifier(classifier);
 335  0
     final ArtifactId id = builder.build();
 336  0
     final File file = artifact.getFile();
 337  0
     final URL url = toUrl(file);
 338  0
     final ArtifactRef ref = new ArtifactRef(id, url);
 339  0
     return ref;
 340  
   }
 341  
 
 342  
   private static String normalize(final Artifact artifact)
 343  
   {
 344  0
     String classifier = artifact.getClassifier();
 345  0
     if (StringUtils.isBlank(classifier))
 346  
     {
 347  0
       classifier = null;
 348  
     }
 349  0
     return classifier;
 350  
   }
 351  
 
 352  
   // --- object basics --------------------------------------------------------
 353  
 
 354  
 }