View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.start.fileinits;
20  
21  import java.io.IOException;
22  import java.net.URI;
23  import java.nio.file.Files;
24  import java.nio.file.Path;
25  
26  import org.eclipse.jetty.start.BaseHome;
27  import org.eclipse.jetty.start.FS;
28  import org.eclipse.jetty.start.FileInitializer;
29  import org.eclipse.jetty.start.StartLog;
30  import org.eclipse.jetty.start.Utils;
31  
32  /**
33   * Attempt to download a <code>maven://</code> URI, by first attempting to find
34   * the resource in the maven repository system (starting with local, then
35   * central)
36   * <p>
37   * Valid URI Formats:
38   * <dl>
39   * <dt><code>maven://&lt;groupId&gt;/&lt;artifactId&gt;/&lt;version&gt;</code></dt>
40   * <dd>minimum requirement (type defaults to <code>jar</code>, with no
41   * classifier)</dd>
42   * <dt><code>maven://&lt;groupId&gt;/&lt;artifactId&gt;/&lt;version&gt;/&lt;type&gt;</code></dt>
43   * <dd>optional type requirement</dd>
44   * <dt>
45   * <code>maven://&lt;groupId&gt;/&lt;artifactId&gt;/&lt;version&gt;/&lt;type&gt;/&lt;classifier&gt;</code>
46   * </dt>
47   * <dd>optional type and classifier requirement</dd>
48   * </dl>
49   */
50  public class MavenLocalRepoFileInitializer extends UriFileInitializer implements FileInitializer
51  {
52      public static class Coordinates
53      {
54          public String groupId;
55          public String artifactId;
56          public String version;
57          public String type;
58          public String classifier;
59  
60          public String toPath()
61          {
62              StringBuilder pathlike = new StringBuilder();
63              pathlike.append(groupId.replace('.','/'));
64              pathlike.append('/').append(artifactId);
65              pathlike.append('/').append(version);
66              pathlike.append('/').append(artifactId);
67              pathlike.append('-').append(version);
68              if (classifier != null)
69              {
70                  pathlike.append('-').append(classifier);
71              }
72              pathlike.append('.').append(type);
73              return pathlike.toString();
74          }
75  
76          public URI toCentralURI()
77          {
78              return URI.create("http://central.maven.org/maven2/" + toPath());
79          }
80      }
81  
82      private Path localRepositoryDir;
83  
84      public MavenLocalRepoFileInitializer(BaseHome baseHome)
85      {
86          this(baseHome,null);
87      }
88  
89      public MavenLocalRepoFileInitializer(BaseHome baseHome, Path localRepoDir)
90      {
91          super(baseHome);
92          this.localRepositoryDir = localRepoDir;
93      }
94  
95      @Override
96      public boolean init(URI uri, Path file, String fileRef) throws IOException
97      {
98          Coordinates coords = getCoordinates(uri);
99          if (coords == null)
100         {
101             // Skip, not a maven:// URI
102             return false;
103         }
104 
105         if (isFilePresent(file, baseHome.getPath(fileRef)))
106         {
107             // All done
108             return true;
109         }
110 
111         // If using local repository
112         if (this.localRepositoryDir != null)
113         {
114             // Grab copy from local repository (download if needed to local
115             // repository)
116             Path localRepoFile = getLocalRepoFile(coords);
117             StartLog.log("COPY","%s to %s",localRepoFile,baseHome.toShortForm(file));
118             Files.copy(localRepoFile,file);
119         }
120         else
121         {
122             // normal non-local repo version
123             download(coords.toCentralURI(),file);
124         }
125         return true;
126     }
127 
128     private Path getLocalRepoFile(Coordinates coords) throws IOException
129     {
130         Path localFile = localRepositoryDir.resolve(coords.toPath());
131         if (FS.canReadFile(localFile))
132         {
133             return localFile;
134         }
135 
136         // Download, if needed
137         download(coords.toCentralURI(),localFile);
138         return localFile;
139     }
140 
141     public Coordinates getCoordinates(URI uri)
142     {
143         if (!"maven".equalsIgnoreCase(uri.getScheme()))
144         {
145             return null;
146         }
147 
148         String ssp = uri.getSchemeSpecificPart();
149 
150         if (ssp.startsWith("//"))
151         {
152             ssp = ssp.substring(2);
153         }
154 
155         String parts[] = ssp.split("/");
156 
157         if (StartLog.isDebugEnabled())
158         {
159             StartLog.debug("ssp = %s",ssp);
160             StartLog.debug("parts = %d",parts.length);
161             for (int i = 0; i < parts.length; i++)
162             {
163                 StartLog.debug("  part[%2d]: [%s]",i,parts[i]);
164             }
165         }
166 
167         if (parts.length < 3)
168         {
169             throw new RuntimeException("Not a valid maven:// uri - " + uri);
170         }
171 
172         Coordinates coords = new Coordinates();
173         coords.groupId = parts[0];
174         coords.artifactId = parts[1];
175         coords.version = parts[2];
176         coords.type = "jar";
177         coords.classifier = null;
178 
179         if (parts.length >= 4)
180         {
181             if (Utils.isNotBlank(parts[3]))
182             {
183                 coords.type = parts[3];
184             }
185 
186             if ((parts.length == 5) && (Utils.isNotBlank(parts[4])))
187             {
188                 coords.classifier = parts[4];
189             }
190         }
191 
192         return coords;
193     }
194 }