1 package net.trajano.wagon.git.internal;
2
3 import static java.lang.String.format;
4
5 import java.io.File;
6 import java.io.FileInputStream;
7 import java.io.FileOutputStream;
8 import java.io.IOException;
9 import java.net.URI;
10 import java.net.URISyntaxException;
11 import java.util.LinkedList;
12 import java.util.List;
13 import java.util.ResourceBundle;
14 import java.util.concurrent.ConcurrentHashMap;
15 import java.util.concurrent.ConcurrentMap;
16 import java.util.logging.Level;
17 import java.util.logging.Logger;
18
19 import org.apache.maven.wagon.ConnectionException;
20 import org.apache.maven.wagon.InputData;
21 import org.apache.maven.wagon.OutputData;
22 import org.apache.maven.wagon.ResourceDoesNotExistException;
23 import org.apache.maven.wagon.StreamWagon;
24 import org.apache.maven.wagon.TransferFailedException;
25 import org.apache.maven.wagon.authentication.AuthenticationException;
26 import org.apache.maven.wagon.authorization.AuthorizationException;
27 import org.codehaus.plexus.util.FileUtils;
28 import org.eclipse.jgit.api.Git;
29 import org.eclipse.jgit.api.errors.GitAPIException;
30 import org.eclipse.jgit.api.errors.InvalidRemoteException;
31 import org.eclipse.jgit.errors.NoRemoteRepositoryException;
32 import org.eclipse.jgit.lib.Constants;
33 import org.eclipse.jgit.lib.RefUpdate;
34 import org.eclipse.jgit.transport.CredentialsProvider;
35 import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
36
37
38
39
40 public abstract class AbstractGitWagon extends StreamWagon {
41
42
43
44
45 private static final Logger LOG;
46
47
48
49
50 private static final String MESSAGES = "META-INF/Messages";
51
52
53
54
55 private static final ResourceBundle R;
56
57 static {
58 LOG = Logger.getLogger("net.trajano.wagon.git", MESSAGES);
59 R = ResourceBundle.getBundle(MESSAGES);
60 }
61
62
63
64
65 private CredentialsProvider credentialsProvider;
66
67
68
69
70 private final ConcurrentMap<String, Git> gitCache = new ConcurrentHashMap<String, Git>();
71
72
73
74
75 private GitUri gitUri;
76
77
78
79
80
81
82
83
84
85
86
87 public abstract GitUri buildGitUri(URI repositoryUrl) throws IOException,
88 URISyntaxException;
89
90
91
92
93
94
95 @Override
96 public void closeConnection() throws ConnectionException {
97 try {
98 for (final String gitRemoteUri : gitCache.keySet()) {
99 final Git git = gitCache.get(gitRemoteUri);
100 git.add().addFilepattern(".").call();
101 git.commit().setMessage(R.getString("commitmessage")).call();
102 git.push().setRemote(gitRemoteUri)
103 .setCredentialsProvider(credentialsProvider).call();
104 git.close();
105 FileUtils.deleteDirectory(git.getRepository().getDirectory());
106 }
107 } catch (final GitAPIException e) {
108 throw new ConnectionException(e.getMessage(), e);
109 } catch (final IOException e) {
110 throw new ConnectionException(e.getMessage(), e);
111 }
112 }
113
114
115
116
117
118
119
120
121
122
123 @Override
124 public void fillInputData(final InputData inputData)
125 throws TransferFailedException, ResourceDoesNotExistException,
126 AuthorizationException {
127 try {
128 final File file = getFileForResource(inputData.getResource()
129 .getName());
130 if (!file.exists()) {
131 throw new ResourceDoesNotExistException(format(
132 R.getString("filenotfound"), file));
133 }
134 if (!file.canRead()) {
135 throw new AuthorizationException(format(
136 R.getString("cannotreadfile"), file));
137 }
138 inputData.setInputStream(new FileInputStream(file));
139 inputData.getResource().setContentLength(file.length());
140 } catch (final IOException e) {
141 throw new TransferFailedException(e.getMessage(), e);
142 } catch (final GitAPIException e) {
143 throw new TransferFailedException(e.getMessage(), e);
144 } catch (final URISyntaxException e) {
145 throw new TransferFailedException(e.getMessage(), e);
146 }
147 }
148
149
150
151
152 @Override
153 public void fillOutputData(final OutputData outputData)
154 throws TransferFailedException {
155 try {
156 final File file = getFileForResource(outputData.getResource()
157 .getName());
158 if (!file.getParentFile().mkdirs()
159 && !file.getParentFile().exists()) {
160 throw new TransferFailedException(format(
161 R.getString("unabletocreatedirs"),
162 file.getParentFile()));
163 }
164 outputData.setOutputStream(new FileOutputStream(file));
165 } catch (final IOException e) {
166 throw new TransferFailedException(e.getMessage(), e);
167 } catch (final GitAPIException e) {
168 throw new TransferFailedException(e.getMessage(), e);
169 } catch (final URISyntaxException e) {
170 throw new TransferFailedException(e.getMessage(), e);
171 }
172 }
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 protected abstract File getFileForResource(String resourceName)
189 throws GitAPIException, IOException, URISyntaxException;
190
191
192
193
194
195
196
197
198 @Override
199 @SuppressWarnings("all")
200 public List<String> getFileList(final String directory)
201 throws TransferFailedException, ResourceDoesNotExistException,
202 AuthorizationException {
203 final File dir;
204 try {
205 dir = getFileForResource(directory);
206 } catch (final GitAPIException e) {
207 throw new AuthorizationException(e.getMessage(), e);
208 } catch (final IOException e) {
209 throw new TransferFailedException(e.getMessage(), e);
210 } catch (final URISyntaxException e) {
211 throw new ResourceDoesNotExistException(e.getMessage(), e);
212 }
213 final File[] files = dir.listFiles();
214 if (files == null) {
215 throw new ResourceDoesNotExistException(format(
216 R.getString("dirnotfound"), dir));
217 }
218 final List<String> list = new LinkedList<String>();
219 for (final File file : files) {
220 String name = file.getName();
221 if (file.isDirectory() && !name.endsWith("/")) {
222 name += "/";
223 }
224 list.add(name);
225 }
226 return list;
227 }
228
229
230
231
232
233
234
235
236
237
238
239
240
241 protected Git getGit(final String gitRepositoryUri) throws GitAPIException,
242 IOException, URISyntaxException, ResourceDoesNotExistException {
243 final Git cachedGit = gitCache.get(gitRepositoryUri);
244 LOG.fine("Loading " + gitRepositoryUri);
245 if (cachedGit != null) {
246 return cachedGit;
247 }
248 final File gitDir = File.createTempFile(
249 gitRepositoryUri.replaceAll("[^A-Za-z]", "_"), "wagon-git");
250 gitDir.delete();
251 gitDir.mkdir();
252
253 if (getAuthenticationInfo().getUserName() != null) {
254 credentialsProvider = new UsernamePasswordCredentialsProvider(
255 getAuthenticationInfo().getUserName(),
256 getAuthenticationInfo().getPassword() == null ? ""
257 : getAuthenticationInfo().getPassword());
258 } else {
259 credentialsProvider = new PassphraseCredentialsProvider(
260 getAuthenticationInfo().getPassword());
261 }
262 try {
263 final Git git = Git.cloneRepository().setURI(gitRepositoryUri)
264 .setCredentialsProvider(credentialsProvider)
265 .setBranch(gitUri.getBranchName()).setDirectory(gitDir)
266 .call();
267 if (!gitUri.getBranchName().equals(git.getRepository().getBranch())) {
268 LOG.log(Level.INFO, "missingbranch", gitUri.getBranchName());
269 final RefUpdate refUpdate = git.getRepository()
270 .getRefDatabase().newUpdate(Constants.HEAD, true);
271 refUpdate.setForceUpdate(true);
272 refUpdate.link("refs/heads/" + gitUri.getBranchName());
273 }
274 gitCache.put(gitRepositoryUri, git);
275 return git;
276 } catch (final InvalidRemoteException e) {
277 throw new ResourceDoesNotExistException(e.getMessage(), e);
278 } catch (final NoRemoteRepositoryException e) {
279 throw new ResourceDoesNotExistException(e.getMessage(), e);
280 }
281 }
282
283 protected GitUri getGitUri() {
284 return gitUri;
285 }
286
287
288
289
290 @Override
291 protected void openConnectionInternal() throws ConnectionException,
292 AuthenticationException {
293 URI uri;
294 try {
295 uri = new URI(
296 new URI(getRepository().getUrl().replace("##", "#"))
297 .getSchemeSpecificPart()).normalize();
298 gitUri = buildGitUri(uri);
299 } catch (final URISyntaxException e) {
300 throw new ConnectionException(e.getMessage(), e);
301 } catch (final IOException e) {
302 throw new ConnectionException(e.getMessage(), e);
303 }
304 }
305
306
307
308
309
310
311
312 @Override
313 @SuppressWarnings("all")
314 public void putDirectory(final File sourceDirectory,
315 final String destinationDirectory) throws TransferFailedException,
316 ResourceDoesNotExistException, AuthorizationException {
317 try {
318 if (!sourceDirectory.isDirectory()) {
319 throw new ResourceDoesNotExistException(format(
320 R.getString("dirnotfound"), sourceDirectory));
321 }
322 final File fileForResource = getFileForResource(destinationDirectory);
323 FileUtils.copyDirectoryStructure(sourceDirectory, fileForResource);
324 } catch (final IOException e) {
325 throw new TransferFailedException(e.getMessage(), e);
326 } catch (final GitAPIException e) {
327 throw new TransferFailedException(e.getMessage(), e);
328 } catch (final URISyntaxException e) {
329 throw new TransferFailedException(e.getMessage(), e);
330 }
331 }
332
333
334
335
336 @Override
337 public boolean resourceExists(final String resourceName)
338 throws TransferFailedException {
339 final File file;
340 try {
341 file = getFileForResource(resourceName);
342 } catch (final GitAPIException e) {
343 throw new TransferFailedException(e.getMessage(), e);
344 } catch (final IOException e) {
345 throw new TransferFailedException(e.getMessage(), e);
346 } catch (final URISyntaxException e) {
347 throw new TransferFailedException(e.getMessage(), e);
348 }
349
350 if (resourceName.endsWith("/")) {
351 return file.isDirectory();
352 }
353
354 return file.exists();
355 }
356
357
358
359
360
361
362 @Override
363 public boolean supportsDirectoryCopy() {
364 return true;
365 }
366 }