Return-Path: Delivered-To: apmail-maven-commits-archive@www.apache.org Received: (qmail 42438 invoked from network); 23 May 2008 23:00:06 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 23 May 2008 23:00:06 -0000 Received: (qmail 31387 invoked by uid 500); 23 May 2008 23:00:05 -0000 Delivered-To: apmail-maven-commits-archive@maven.apache.org Received: (qmail 31296 invoked by uid 500); 23 May 2008 23:00:05 -0000 Mailing-List: contact commits-help@maven.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@maven.apache.org Delivered-To: mailing list commits@maven.apache.org Received: (qmail 31286 invoked by uid 99); 23 May 2008 23:00:05 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 23 May 2008 16:00:05 -0700 X-ASF-Spam-Status: No, hits=-1999.3 required=10.0 tests=ALL_TRUSTED,FRT_LEVITRA X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 23 May 2008 22:59:06 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 80C5623889C1; Fri, 23 May 2008 15:59:27 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r659700 [1/4] - in /maven/sandbox/trunk/mercury: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/maven/ src/main/java/org/apache/maven/mercury/ src/main/java/org/apache/maven/mercury/cl... Date: Fri, 23 May 2008 22:59:25 -0000 To: commits@maven.apache.org From: jvanzyl@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080523225927.80C5623889C1@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: jvanzyl Date: Fri May 23 15:59:23 2008 New Revision: 659700 URL: http://svn.apache.org/viewvc?rev=659700&view=rev Log: o first of mercury http client Added: maven/sandbox/trunk/mercury/ maven/sandbox/trunk/mercury/pom.xml (with props) maven/sandbox/trunk/mercury/src/ maven/sandbox/trunk/mercury/src/main/ maven/sandbox/trunk/mercury/src/main/java/ maven/sandbox/trunk/mercury/src/main/java/org/ maven/sandbox/trunk/mercury/src/main/java/org/apache/ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/BatchException.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/Binding.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/ChecksumCalculator.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/FileExchange.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/HandshakeExchange.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/BatchIdGenerator.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DefaultDeployResponse.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DefaultDeployer.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployCallback.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployRequest.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployResponse.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/Deployer.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeploymentTarget.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/FilePutExchange.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/RandomBatchIdGenerator.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/DefaultRetrievalResponse.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/DefaultRetriever.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/FileGetExchange.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/RetrievalCallback.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/RetrievalRequest.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/RetrievalResponse.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/RetrievalTarget.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/Retriever.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/server/ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/server/BatchFilter.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/server/StagingBatchFilter.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/validate/ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/validate/PomValidator.java (with props) maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/validate/Validator.java (with props) maven/sandbox/trunk/mercury/src/main/resources/ maven/sandbox/trunk/mercury/src/test/ maven/sandbox/trunk/mercury/src/test/java/ maven/sandbox/trunk/mercury/src/test/java/org/ maven/sandbox/trunk/mercury/src/test/java/org/apache/ maven/sandbox/trunk/mercury/src/test/java/org/apache/maven/ maven/sandbox/trunk/mercury/src/test/java/org/apache/maven/mercury/ maven/sandbox/trunk/mercury/src/test/java/org/apache/maven/mercury/client/ maven/sandbox/trunk/mercury/src/test/java/org/apache/maven/mercury/client/JettyDeployerTest.java (with props) maven/sandbox/trunk/mercury/src/test/java/org/apache/maven/mercury/client/JettyRetrieverTest.java (with props) maven/sandbox/trunk/mercury/src/test/java/org/apache/maven/mercury/client/RetrievalRequestImpl.java (with props) maven/sandbox/trunk/mercury/src/test/java/org/apache/maven/mercury/server/ maven/sandbox/trunk/mercury/src/test/java/org/apache/maven/mercury/server/BatchFilterTest.java (with props) maven/sandbox/trunk/mercury/src/test/java/org/apache/maven/mercury/server/SimplePutServer.java (with props) maven/sandbox/trunk/mercury/src/test/java/org/apache/maven/mercury/server/SimpleTestServer.java (with props) maven/sandbox/trunk/mercury/src/test/resources/ maven/sandbox/trunk/mercury/src/test/resources/testRepo/ maven/sandbox/trunk/mercury/src/test/resources/testRepo/README.TXT (with props) maven/sandbox/trunk/mercury/src/test/resources/testRepo/file0.txt (with props) maven/sandbox/trunk/mercury/src/test/resources/testRepo/file0.txt.sha1 maven/sandbox/trunk/mercury/src/test/resources/testRepo/file1.txt (with props) maven/sandbox/trunk/mercury/src/test/resources/testRepo/file2.txt (with props) maven/sandbox/trunk/mercury/src/test/resources/testRepo/file2.txt.sha1 maven/sandbox/trunk/mercury/src/test/resources/testRepo/file3.jar (with props) maven/sandbox/trunk/mercury/src/test/resources/testRepo/file3.jar.sha1 maven/sandbox/trunk/mercury/src/test/resources/testRepo/file4.so (with props) maven/sandbox/trunk/mercury/src/test/resources/testRepo/file4.so.sha1 maven/sandbox/trunk/mercury/src/test/resources/testRepo/file5.jpg (with props) maven/sandbox/trunk/mercury/src/test/resources/testRepo/file5.jpg.sha1 Added: maven/sandbox/trunk/mercury/pom.xml URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/pom.xml?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/pom.xml (added) +++ maven/sandbox/trunk/mercury/pom.xml Fri May 23 15:59:23 2008 @@ -0,0 +1,69 @@ + + 4.0.0 + org.sonatype.jetty + mercury + 1.0-SNAPSHOT + jar + Batch HTTP Client + + scm:svn:https://svn.sonatype.org/mercury/trunk + scm:svn:https://svn.sonatype.org/mercury + + + install + + + maven-compiler-plugin + + 1.5 + 1.5 + false + + + + + com.google.code.maven-license-plugin + maven-license-plugin + + ${basedir} +
${basedir}/header.txt
+ false + + src/** + + true + true +
+
+
+
+ + + org.mortbay.jetty + jetty-client + 7.0.0pre0 + + + org.mortbay.jetty + jetty-servlet + 7.0.0pre0 + + + org.codehaus.plexus + plexus-utils + 1.5.1 + + + junit + junit + 3.8.1 + test + + + org.mortbay.jetty + jetty-servlet-tester + 7.0.0pre0 + test + + +
Propchange: maven/sandbox/trunk/mercury/pom.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/pom.xml ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/BatchException.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/BatchException.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/BatchException.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/BatchException.java Fri May 23 15:59:23 2008 @@ -0,0 +1,57 @@ +//======================================================================== +//Copyright 2008 Sonatype Inc. +//------------------------------------------------------------------------ +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +//http://www.apache.org/licenses/LICENSE-2.0 +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +//======================================================================== + +package org.apache.maven.mercury.client; + +/** + * BatchException + *

+ * Exception that occurs whilst deploying or retrieving files + * asynchronously. + */ +public class BatchException + extends Exception +{ + private Binding binding; + + public BatchException( Binding b, String s ) + { + super( s ); + binding = b; + } + + public BatchException( Binding b, String s, Throwable throwable ) + { + super( s, throwable ); + binding = b; + } + + public BatchException( Binding b, Throwable throwable ) + { + super( throwable ); + binding = b; + } + + public Binding getBinding() + { + return binding; + } + + + public String getMessage() + { + return super.getMessage() + " for " + binding; + } + +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/BatchException.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/BatchException.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/Binding.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/Binding.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/Binding.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/Binding.java Fri May 23 15:59:23 2008 @@ -0,0 +1,66 @@ +//======================================================================== +//Copyright 2008 Sonatype Inc. +//------------------------------------------------------------------------ +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +//http://www.apache.org/licenses/LICENSE-2.0 +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +//======================================================================== + +package org.apache.maven.mercury.client; + +import java.io.File; + +/** + * Binding + *

+ * A Binding represents a remote url whose contents are to be downloaded + * and stored in a local file, or a local file whose contents are to be + * uploaded to the remote url. + */ +public class Binding +{ + protected String remoteUrl; + protected File localFile; + protected boolean lenientChecksum; + + public String getRemoteUrl() + { + return remoteUrl; + } + + public void setRemoteUrl( String remoteUrl ) + { + this.remoteUrl = remoteUrl; + } + + public File getLocalFile() + { + return localFile; + } + + public void setLocalFile( File localFile ) + { + this.localFile = localFile; + } + + public boolean isLenientChecksum() + { + return lenientChecksum; + } + + public void setLenientChecksum( boolean leniantChecksum ) + { + this.lenientChecksum = leniantChecksum; + } + + public String toString() + { + return "[" + remoteUrl + "," + localFile + "," + lenientChecksum + "]"; + } +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/Binding.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/Binding.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/ChecksumCalculator.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/ChecksumCalculator.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/ChecksumCalculator.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/ChecksumCalculator.java Fri May 23 15:59:23 2008 @@ -0,0 +1,64 @@ +package org.apache.maven.mercury.client; + +import org.mortbay.util.IO; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; + +public class ChecksumCalculator +{ + private static final byte[] __HEX_DIGITS = "0123456789abcdef".getBytes(); + + + public static String encodeToAsciiHex( byte[] bytes ) + { + int l = bytes.length; + + byte[] raw = new byte[l * 2]; + + for ( int i = 0, j = 0; i < l; i++ ) + { + raw[j++] = __HEX_DIGITS[( 0xF0 & bytes[i] ) >>> 4]; + raw[j++] = __HEX_DIGITS[0x0F & bytes[i]]; + } + + return new String( raw ); + } + + public static String readChecksumFromFile( File f ) throws FileNotFoundException, IOException + { + if ( f == null ) + { + return null; + } + if ( !isChecksumFile( f ) ) + { + throw new IOException( "Not a checksum file" ); + } + + FileInputStream fis = new FileInputStream( f ); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + IO.copy( fis, baos ); + return baos.toString( "UTF-8" ); + } + + public static boolean isChecksumFile( File f ) + { + if ( f == null ) + { + return false; + } + + String fileName = f.getName().toLowerCase(); + if ( fileName.endsWith( ".sha" ) || fileName.endsWith( ".sha1" ) ) + { + return true; + } + + return false; + } + +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/ChecksumCalculator.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/ChecksumCalculator.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/FileExchange.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/FileExchange.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/FileExchange.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/FileExchange.java Fri May 23 15:59:23 2008 @@ -0,0 +1,83 @@ +// ======================================================================== +// Copyright 2008 Sonatype Inc. +// ------------------------------------------------------------------------ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ======================================================================== +package org.apache.maven.mercury.client; + +import org.mortbay.io.Buffer; +import org.mortbay.jetty.client.HttpClient; +import org.mortbay.jetty.client.HttpExchange; + +import java.io.File; + +/** + * FileExchange + *

+ * Base class for asynchronously PUTting or GETting a file. + */ +public abstract class FileExchange extends HttpExchange +{ + public static final String __BATCH_HEADER = "Jetty-Batch-Id"; + public static final String __BATCH_SUPPORTED_HEADER = "Jetty-Batch-Supported"; + public static final String __BATCH_COMMIT_HEADER = "Jetty-Batch-Commit"; + public static final String __BATCH_DISCARD_HEADER = "Jetty-Batch-Discard"; + public static final String _digestAlgorithm = "SHA-1"; + + protected HttpClient _httpClient; + protected boolean _digestRequired; + protected int _status; + protected String _url; + protected File _localFile; + protected Binding _binding; + + public abstract void onFileComplete( String url, File localFile, String digest ); + + public abstract void onFileError( String url, Exception e ); + + + public FileExchange( Binding binding, File localFile, boolean digestRequired, HttpClient client ) + { + _binding = binding; + _url = binding.getRemoteUrl(); + _localFile = localFile; + _httpClient = client; + _digestRequired = digestRequired; + setURL( _url ); + } + + public void send() + { + try + { + _httpClient.send( this ); + } + catch ( Exception e ) + { + onFileError( _url, e ); + } + } + + protected void onResponseStatus( Buffer version, int status, Buffer reason ) + { + _status = status; + } + + protected void onException( Throwable ex ) + { + onFileError( _url, new Exception( ex ) ); + } + + protected void onExpire() + { + onFileError( _url, new Exception( "Timeout occurred" ) ); + } +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/FileExchange.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/FileExchange.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/HandshakeExchange.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/HandshakeExchange.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/HandshakeExchange.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/HandshakeExchange.java Fri May 23 15:59:23 2008 @@ -0,0 +1,104 @@ +// ======================================================================== +// Copyright 2008 Sonatype Inc. +// ------------------------------------------------------------------------ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ======================================================================== +package org.apache.maven.mercury.client; + +import org.mortbay.io.Buffer; +import org.mortbay.jetty.client.HttpClient; +import org.mortbay.jetty.client.HttpExchange; + +import javax.servlet.http.HttpServletResponse; +import java.util.Map; + +/** + * HandshakeExchange + *

+ * Asychronous http message sending. Used to generate a commit or discard + * message to the remote server after the mercury upload is finished. + */ +public abstract class HandshakeExchange extends HttpExchange +{ + private HttpClient _httpClient; + private String _method; + private String _url; + private Map _headers; + private int _status; + + public abstract void onHandshakeComplete( String url ); + + public abstract void onHandshakeError( String url, Exception e ); + + /** + * @param httpClient + * @param method + * @param url + * @param headers + */ + public HandshakeExchange( HttpClient httpClient, String method, String url, Map headers ) + { + _httpClient = httpClient; + _method = method; + _url = url; + _headers = headers; + } + + public void send() + { + try + { + setMethod( _method ); + setURL( _url ); + if ( _headers != null ) + { + for ( Map.Entry e : _headers.entrySet() ) + { + setRequestHeader( e.getKey(), e.getValue() ); + } + } + _httpClient.send( this ); + } + catch ( Exception e ) + { + onHandshakeError( _url, new Exception( null, e ) ); + } + } + + + protected void onResponseStatus( Buffer version, int status, Buffer reason ) + { + _status = status; + } + + protected void onException( Throwable ex ) + { + onHandshakeError( _url, new Exception( ex ) ); + } + + protected void onExpire() + { + onHandshakeError( _url, new Exception( "Timeout occurred" ) ); + } + + protected void onResponseComplete() + { + if ( _status != HttpServletResponse.SC_OK ) + { + onHandshakeError( _url, new Exception( "Http Error Code:" + _status ) ); + } + else + { + onHandshakeComplete( _url ); + } + } + +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/HandshakeExchange.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/HandshakeExchange.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/BatchIdGenerator.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/BatchIdGenerator.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/BatchIdGenerator.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/BatchIdGenerator.java Fri May 23 15:59:23 2008 @@ -0,0 +1,20 @@ +// ======================================================================== +//Copyright 2008 Sonatype Inc. +//------------------------------------------------------------------------ +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +//http://www.apache.org/licenses/LICENSE-2.0 +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +//======================================================================== + +package org.apache.maven.mercury.client.deploy; + +public interface BatchIdGenerator +{ + public String getId(); +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/BatchIdGenerator.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/BatchIdGenerator.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DefaultDeployResponse.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DefaultDeployResponse.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DefaultDeployResponse.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DefaultDeployResponse.java Fri May 23 15:59:23 2008 @@ -0,0 +1,45 @@ +// ======================================================================== +// Copyright 2008 Sonatype Inc. +// ------------------------------------------------------------------------ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ======================================================================== +package org.apache.maven.mercury.client.deploy; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.apache.maven.mercury.client.BatchException; + +public class DefaultDeployResponse implements DeployResponse +{ + private Set _exceptions = Collections.synchronizedSet( new HashSet() ); + + public DefaultDeployResponse() + { + } + + public void add( BatchException e ) + { + _exceptions.add( e ); + } + + public Set getExceptions() + { + return _exceptions; + } + + public String toString() + { + return _exceptions.toString(); + } + +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DefaultDeployResponse.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DefaultDeployResponse.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DefaultDeployer.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DefaultDeployer.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DefaultDeployer.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DefaultDeployer.java Fri May 23 15:59:23 2008 @@ -0,0 +1,280 @@ +// ======================================================================== +// Copyright 2008 Sonatype Inc. +// ------------------------------------------------------------------------ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ======================================================================== +package org.apache.maven.mercury.client.deploy; + +import org.apache.maven.mercury.client.BatchException; +import org.apache.maven.mercury.client.Binding; +import org.apache.maven.mercury.client.FileExchange; +import org.apache.maven.mercury.client.HandshakeExchange; +import org.mortbay.jetty.HttpMethods; +import org.mortbay.jetty.client.HttpClient; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * JettyDeployer + *

+ * Implementation of Deployer using Jetty async HttpClient. + */ +public class DefaultDeployer implements Deployer +{ + private HttpClient _httpClient; + private BatchIdGenerator _idGenerator; + + + public DefaultDeployer() + throws BatchException + { + _idGenerator = new RandomBatchIdGenerator(); + _httpClient = new HttpClient(); + _httpClient.setConnectorType( HttpClient.CONNECTOR_SELECT_CHANNEL ); + try + { + _httpClient.start(); + } + catch ( Exception e ) + { + throw new BatchException( null, "unable to start http client", e ); + } + } + + public DefaultDeployer( HttpClient client, BatchIdGenerator idGenerator ) + throws BatchException + { + _idGenerator = idGenerator; + if ( _idGenerator == null ) + { + throw new BatchException( null, "no id generator supplied" ); + } + + _httpClient = client; + try + { + if ( _httpClient.isStarted() ) + { + _httpClient.start(); + } + } + catch ( Exception e ) + { + throw new BatchException( null, "unable to start http client", e ); + } + } + + public BatchIdGenerator getBatchIdGenerator() + { + return _idGenerator; + } + + public HttpClient getHttpClient() + { + return _httpClient; + } + + /** + * Deploy a set files synchronously. This call will return when either all + * files have been successfully deployed, or one or more failures have + * occurred, depending on the failFast setting of the DeployRequest. + * + * @see org.apache.maven.mercury.client.deploy.Deployer#deploy(org.apache.maven.mercury.client.deploy.DeployRequest) + */ + public DeployResponse deploy( DeployRequest request ) + { + final DeployResponse[] response = new DeployResponse[]{null}; + + deploy( request, new DeployCallback() + { + public void onComplete( DeployResponse r ) + { + synchronized ( response ) + { + response[0] = r; + response.notify(); + } + } + } ); + + synchronized ( response ) + { + try + { + while ( response[0] == null ) + { + response.wait(); + } + } + catch ( InterruptedException e ) + { + return null; + } + return response[0]; + } + } + + /** + * Deploy a set of files, returning immediately. The callback will be called when + * all the files have been deployed or one or more errors occur (depends on the FailFast + * setting of the DeployRequest). + * + * @see org.apache.maven.mercury.client.deploy.Deployer#deploy(org.apache.maven.mercury.client.deploy.DeployRequest, org.apache.maven.mercury.client.deploy.DeployCallback) + */ + public void deploy( final DeployRequest request, final DeployCallback callback ) + { + if ( request == null ) + { + throw new IllegalArgumentException( "No request" ); + } + + if ( callback == null ) + { + throw new IllegalArgumentException( "No callback" ); + } + + final String batchId = _idGenerator.getId(); + final AtomicInteger count = new AtomicInteger( request.getBindings().size() ); + final List targets = new ArrayList( request.getBindings().size() ); + final DefaultDeployResponse response = new DefaultDeployResponse(); + final Set remoteHandshakeUrls = new HashSet(); + + Binding[] bindings = new Binding[request.getBindings().size()]; + request.getBindings().toArray( bindings ); + for ( int i = 0; i < bindings.length && count.get() > 0; i++ ) + { + final Binding binding = bindings[i]; + DeploymentTarget target = null; + try + { + target = new DeploymentTarget( _httpClient, batchId, binding, request.getValidators() ) + { + public void onComplete() + { + if ( getRemoteJettyUrl() != null ) + { + remoteHandshakeUrls.add( getRemoteJettyUrl() ); + } + //uploaded the file - have we uploaded all of them? + checkComplete( callback, batchId, count, request, response, remoteHandshakeUrls ); + } + + public void onError( BatchException exception ) + { + if ( getRemoteJettyUrl() != null ) + { + remoteHandshakeUrls.add( getRemoteJettyUrl() ); + } + response.add( exception ); + checkComplete( callback, batchId, count, request, response, remoteHandshakeUrls ); + } + }; + targets.add( target ); + } + catch ( Exception e ) + { + response.add( new BatchException( binding, e ) ); + checkComplete( callback, batchId, count, request, response, remoteHandshakeUrls ); + } + } + + for ( final DeploymentTarget target : targets ) + { + target.deploy(); //upload file + } + } + + private synchronized void checkComplete( final DeployCallback callback, + String batchId, + AtomicInteger count, + DeployRequest request, + DeployResponse response, + Set remoteHandshakeUrls ) + { + int x = count.decrementAndGet(); + boolean completor = x == 0; + if ( !completor && request.isFailFast() && response.getExceptions().size() > 0 ) + { + completor = count.getAndSet( 0 ) > 0; + } + + if ( completor ) + { + commit( callback, response, batchId, remoteHandshakeUrls ); + } + } + + /** + * Send message to remote server (if Jetty) to indicate all + * files uploaded should now be commited or discarded if there were exceptions. + * + * @param batchId + */ + private void commit( final DeployCallback callback, + final DeployResponse response, + final String batchId, + final Set remoteHandshakeUrls ) + { + if ( remoteHandshakeUrls.isEmpty() ) + { + callback.onComplete( response ); + } + else + { + final AtomicInteger count = new AtomicInteger( remoteHandshakeUrls.size() ); + Map headers = new HashMap(); + //if no errors, then commit, otherwise send a discard message + if ( response.getExceptions().isEmpty() ) + { + headers.put( FileExchange.__BATCH_COMMIT_HEADER, batchId ); + } + else + { + headers.put( FileExchange.__BATCH_DISCARD_HEADER, batchId ); + } + for ( final String remoteUrl : remoteHandshakeUrls ) + { + HandshakeExchange exchange = new HandshakeExchange( _httpClient, HttpMethods.POST, remoteUrl, headers ) + { + public void onHandshakeComplete( String url ) + { + checkHandshakeComplete( callback, response, count ); + + } + + public void onHandshakeError( String url, Exception e ) + { + response.getExceptions().add( new BatchException( null, e ) ); + checkHandshakeComplete( callback, response, count ); + } + }; + } + } + } + + + private void checkHandshakeComplete( final DeployCallback callback, + final DeployResponse response, + AtomicInteger count ) + { + boolean completor = count.decrementAndGet() == 0; + if ( completor ) + { + callback.onComplete( response ); + } + } +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DefaultDeployer.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DefaultDeployer.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployCallback.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployCallback.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployCallback.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployCallback.java Fri May 23 15:59:23 2008 @@ -0,0 +1,32 @@ +// ======================================================================== +// Copyright 2008 Sonatype Inc. +// ------------------------------------------------------------------------ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ======================================================================== + +package org.apache.maven.mercury.client.deploy; + + +/** + * DeployCallback + *

+ * Classes that implement this method will be notified when a given job has + * been completed and validated. + */ +public interface DeployCallback +{ + /** + * Callback for asynchronous version of Retriever.retrieve. + * + * @param response empty if all artifacts retrieved ok, list of exceptions otherwise + */ + void onComplete( DeployResponse response ); +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployCallback.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployCallback.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployRequest.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployRequest.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployRequest.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployRequest.java Fri May 23 15:59:23 2008 @@ -0,0 +1,35 @@ +// ======================================================================== +// Copyright 2008 Sonatype Inc. +// ------------------------------------------------------------------------ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ======================================================================== + +package org.apache.maven.mercury.client.deploy; + +import java.util.Set; + +import org.apache.maven.mercury.client.Binding; +import org.apache.maven.mercury.validate.Validator; + + +/** + * RetrievalRequest + *

+ * A set of files to retrieve from remote locations. + */ +public interface DeployRequest +{ + public abstract Set getBindings(); + + public abstract boolean isFailFast(); + + public Set getValidators(); +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployRequest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployRequest.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployResponse.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployResponse.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployResponse.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployResponse.java Fri May 23 15:59:23 2008 @@ -0,0 +1,37 @@ +// ======================================================================== +// Copyright 2008 Sonatype Inc. +// ------------------------------------------------------------------------ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ======================================================================== + +package org.apache.maven.mercury.client.deploy; + +import java.util.Set; + +import org.apache.maven.mercury.client.BatchException; + +/** + * DeployResponse + *

+ * A response to a request to upload a set of files to + * remote location(s). + */ +public interface DeployResponse +{ + /** + * The set will be empty if the operation completed successfully, + * or will contain a single entry if the Request is failFast, otherwise + * there will be one exception for every Binding in the Request. + * + * @return + */ + public Set getExceptions(); +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployResponse.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeployResponse.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/Deployer.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/Deployer.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/Deployer.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/Deployer.java Fri May 23 15:59:23 2008 @@ -0,0 +1,35 @@ +// ======================================================================== +// Copyright 2008 Sonatype Inc. +// ------------------------------------------------------------------------ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ======================================================================== + +package org.apache.maven.mercury.client.deploy; + + +/** + * Deployer + *

+ * Deploy a set of files to remote locations as an atomic operation. + */ +public interface Deployer +{ + /** Deploy a set of files and return when all done. */ + DeployResponse deploy( DeployRequest request ); + + + /** + * Deploy a set of files and return immediately without waiting. + * The callback will be called when files are ready or an error + * has occurred. + */ + void deploy( DeployRequest request, DeployCallback callback ); +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/Deployer.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/Deployer.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeploymentTarget.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeploymentTarget.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeploymentTarget.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeploymentTarget.java Fri May 23 15:59:23 2008 @@ -0,0 +1,277 @@ +// ======================================================================== +// Copyright 2008 Sonatype Inc. +// ------------------------------------------------------------------------ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ======================================================================== +package org.apache.maven.mercury.client.deploy; + +import org.apache.maven.mercury.client.BatchException; +import org.apache.maven.mercury.client.Binding; +import org.apache.maven.mercury.validate.Validator; +import org.mortbay.jetty.client.HttpClient; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.util.Set; + +public abstract class DeploymentTarget +{ + public static final String __DIGEST_SUFFIX = ".sha1"; + + + private HttpClient _httpClient; + private String _batchId; + private Binding _binding; + private Set _validators; + private File _localChecksumFile; + private String _calculatedChecksum; + private TargetState _targetState; + private TargetState _checksumState; + private BatchException _exception; + private String _remoteJettyUrl; + + + public abstract void onComplete(); + + public abstract void onError( BatchException exception ); + + + public class TargetState + { + public static final int __START_STATE = 1; + public static final int __REQUESTED_STATE = 2; + public static final int __READY_STATE = 3; + + private int _state; + private Exception _exception; + + public TargetState() + { + _state = __START_STATE; + } + + public synchronized void ready() + { + setState( __READY_STATE ); + } + + public synchronized void ready( Exception e ) + { + setState( __READY_STATE ); + _exception = e; + } + + public synchronized void requested() + { + setState( __REQUESTED_STATE ); + } + + public synchronized boolean isStart() + { + return _state == __START_STATE; + } + + public synchronized boolean isRequested() + { + return _state == __REQUESTED_STATE; + } + + public synchronized boolean isError() + { + return _exception != null; + } + + public boolean isReady() + { + return _state == __READY_STATE; + } + + public synchronized void setState( int status ) + { + _state = status; + } + + public synchronized int getState() + { + return _state; + } + + public synchronized Exception getException() + { + return _exception; + } + } + + public DeploymentTarget( HttpClient client, String batchId, Binding binding, Set validators ) + { + _httpClient = client; + _batchId = batchId; + _binding = binding; + _validators = validators; + if ( _binding == null || _binding.getLocalFile() == null || !_binding.getLocalFile().exists() ) + { + throw new IllegalArgumentException( "No local file to deploy" ); + } + _localChecksumFile = new File( _binding.getLocalFile().getParentFile(), + _binding.getLocalFile().getName() + __DIGEST_SUFFIX ); + _targetState = new TargetState(); + _checksumState = new TargetState(); + } + + + public void deploy() + { + updateState( null ); + } + + private synchronized void updateState( Throwable t ) + { + if ( t != null && _exception == null ) + { + _exception = ( t instanceof BatchException ? (BatchException) t : new BatchException( _binding, t ) ); + } + + //if the target file can be fetched then get it + if ( _targetState.isStart() ) + { + System.err.println( "Starting deployment of " + _binding.getLocalFile().getName() ); + deployLocalFile( _localChecksumFile.exists() ); + } + + //if there is a local checksum file, then get it + if ( _checksumState.isStart() && _localChecksumFile.exists() ) + { + System.err.println( "Starting deployment of checksum file for " + _binding.getLocalFile().getName() ); + deployChecksumFile(); + } + + //if the local checksum file doesn't exist then only upload it after the target file has been sent, + //as we need to calculate the checksum as we send it + if ( _targetState.isReady() && _checksumState.isStart() && !_localChecksumFile.exists() ) + { + System.err.println( "Calculated checksum ready, starting deployment" ); + deployChecksumFile(); + } + + if ( _targetState.isReady() && _checksumState.isReady() ) + { + if ( _exception == null ) + { + onComplete(); + } + else + { + onError( _exception ); + } + } + } + + private void deployLocalFile( boolean checksumExists ) + { + FilePutExchange exchange = new FilePutExchange( _batchId, _binding, _binding.getLocalFile(), true, _httpClient ) + { + public void onFileComplete( String url, File localFile, + String digest ) + { + DeploymentTarget.this._remoteJettyUrl = getRemoteJettyUrl(); + _calculatedChecksum = digest; + _targetState.ready(); + System.err.println( "File complete " + url ); + updateState( null ); + } + + public void onFileError( String url, Exception e ) + { + DeploymentTarget.this._remoteJettyUrl = getRemoteJettyUrl(); + _targetState.ready( e ); + System.err.println( "File complete " + url ); + updateState( e ); + } + }; + _targetState.requested(); + exchange.send(); + } + + + private void deployChecksumFile() + { + Binding binding = _binding; + File file = _localChecksumFile; + if ( !_localChecksumFile.exists() && _calculatedChecksum != null ) + { + //No local checksum file, so make a temporary one using the checksum we + //calculated as we uploaded the file + try + { + binding = new Binding(); + binding.setRemoteUrl( _binding.getRemoteUrl() + __DIGEST_SUFFIX ); + file = File.createTempFile( _binding.getLocalFile().getName() + __DIGEST_SUFFIX, ".tmp" ); + OutputStreamWriter fw = new OutputStreamWriter( new FileOutputStream( file ), "UTF-8" ); + fw.write( _calculatedChecksum ); + fw.close(); + binding.setLocalFile( file ); + } + catch ( Exception e ) + { + _checksumState.ready( e ); + } + } + else + { + binding = new Binding(); + binding.setRemoteUrl( _binding.getRemoteUrl() + __DIGEST_SUFFIX ); + binding.setLocalFile( _localChecksumFile ); + } + + //upload the checksum file + FilePutExchange exchange = new FilePutExchange( _batchId, binding, file, false, _httpClient ) + { + public void onFileComplete( String url, File localFile, String digest ) + { + DeploymentTarget.this._remoteJettyUrl = getRemoteJettyUrl(); + _checksumState.ready(); + System.err.println( "Checksum file complete: " + url ); + updateState( null ); + } + + public void onFileError( String url, Exception e ) + { + DeploymentTarget.this._remoteJettyUrl = getRemoteJettyUrl(); + _checksumState.ready( e ); + System.err.println( "Checksum file error: " + url ); + updateState( e ); + } + }; + _checksumState.requested(); + exchange.send(); + } + + public boolean isRemoteJetty() + { + return _remoteJettyUrl != null; + } + + public String getRemoteJettyUrl() + { + return _remoteJettyUrl; + } + + public synchronized boolean isComplete() + { + return ( _checksumState.isReady() && _targetState.isReady() ); + } + + public String toString() + { + return "DeploymentTarget:" + _binding.getRemoteUrl() + ":" + _targetState + ":" + _checksumState + ":" + isComplete(); + } +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeploymentTarget.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/DeploymentTarget.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/FilePutExchange.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/FilePutExchange.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/FilePutExchange.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/FilePutExchange.java Fri May 23 15:59:23 2008 @@ -0,0 +1,156 @@ +// ======================================================================== +// Copyright 2008 Sonatype Inc. +// ------------------------------------------------------------------------ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ======================================================================== +package org.apache.maven.mercury.client.deploy; + +import org.apache.maven.mercury.client.BatchException; +import org.apache.maven.mercury.client.Binding; +import org.apache.maven.mercury.client.ChecksumCalculator; +import org.apache.maven.mercury.client.FileExchange; +import org.mortbay.io.Buffer; +import org.mortbay.jetty.HttpMethods; +import org.mortbay.jetty.client.HttpClient; + +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.DigestInputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + + +/** + * FilePutExchange + *

+ * Asynchronously PUT a file to a remote server. The file that is being uploaded can also + * have it's SHA-1 digest calculated as it is being streamed up. + */ +public abstract class FilePutExchange extends FileExchange +{ + + private String _batchId; + private InputStream _inputStream; + private String _remoteRepoUrl; + private String _remoteBatchId; + + public abstract void onFileComplete( String url, File localFile, String digest ); + + public abstract void onFileError( String url, Exception e ); + + + public FilePutExchange( String batchId, Binding binding, File localFile, boolean digestRequired, HttpClient client ) + { + super( binding, localFile, digestRequired, client ); + _batchId = batchId; + } + + + /** + * Start the upload. Ensure that the id of the mercury is set as a request header + * so all files part of the same mercury can be identified as an atomic unit. + */ + public void send() + { + try + { + setMethod( HttpMethods.PUT ); + setRequestContentSource( getInputStream() ); + setRequestHeader( "Content-Type", "application/octet-stream" ); + setRequestHeader( "Content-Length", String.valueOf( _localFile.length() ) ); + setRequestHeader( __BATCH_HEADER, _batchId ); + System.err.println( "Sending PUT for " + getURI() ); + super.send(); + } + catch ( Exception e ) + { + onFileError( _url, e ); + } + } + + public boolean isRemoteJetty() + { + return _remoteRepoUrl != null; + } + + public String getRemoteJettyUrl() + { + return _remoteRepoUrl; + } + + + protected void onResponseHeader( Buffer name, Buffer value ) + { + if ( name.toString().equalsIgnoreCase( __BATCH_SUPPORTED_HEADER ) ) + { + _remoteRepoUrl = value.toString(); + } + else if ( name.toString().equalsIgnoreCase( __BATCH_HEADER ) ) + { + _remoteBatchId = value.toString(); + } + } + + protected void onResponseComplete() + { + System.err.println( "On ResponseComplete for put for " + _url ); + String digest = null; + try + { + if ( _status != HttpServletResponse.SC_OK && _status != HttpServletResponse.SC_CREATED && _status != HttpServletResponse.SC_NO_CONTENT ) + { + onFileError( _url, new BatchException( _binding, "Http status code=" + _status ) ); + return; + } + + if ( _remoteBatchId != null && !_batchId.equals( _remoteBatchId ) ) + { + onFileError( _url, new BatchException( _binding, + "Non matching mercury ids. Sent=" + _batchId + " received=" + _remoteBatchId ) ); + return; + } + + if ( _digestRequired && _inputStream != null ) + { + byte[] bytes = ( (DigestInputStream) _inputStream ).getMessageDigest().digest(); + digest = ChecksumCalculator.encodeToAsciiHex( bytes ); + } + onFileComplete( _url, _localFile, digest ); + } + catch ( Exception e ) + { + onFileError( _url, new BatchException( _binding, e.getLocalizedMessage() ) ); + } + } + + + private InputStream getInputStream() + throws IOException, NoSuchAlgorithmException + { + if ( _inputStream == null ) + { + if ( !_digestRequired ) + { + _inputStream = new FileInputStream( _localFile ); + } + else + { + MessageDigest digest = MessageDigest.getInstance( _digestAlgorithm ); + _inputStream = new DigestInputStream( new FileInputStream( _localFile ), digest ); + } + } + System.err.println( "Returning input stream for " + _localFile.getName() ); + return _inputStream; + } +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/FilePutExchange.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/FilePutExchange.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/RandomBatchIdGenerator.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/RandomBatchIdGenerator.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/RandomBatchIdGenerator.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/RandomBatchIdGenerator.java Fri May 23 15:59:23 2008 @@ -0,0 +1,77 @@ +// ======================================================================== +//Copyright 2008 Sonatype Inc. +//------------------------------------------------------------------------ +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +//http://www.apache.org/licenses/LICENSE-2.0 +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +//======================================================================== +package org.apache.maven.mercury.client.deploy; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Random; + + +public class RandomBatchIdGenerator implements BatchIdGenerator +{ + protected final static String SESSION_ID_RANDOM_ALGORITHM = "SHA1PRNG"; + private Random _random; + private boolean _initialized; + + + public RandomBatchIdGenerator() + { + } + + public String getId() + { + init(); + String id = ""; + if ( !( _random instanceof SecureRandom ) ) + { + id = String.valueOf( hashCode() ^ Runtime.getRuntime().freeMemory() ^ _random.nextInt() ); + } + else + { + id = String.valueOf( _random.nextLong() ); + } + return id; + } + + public void setRandom( Random random ) + { + _random = random; + } + + public Random getRandom() + { + return _random; + } + + private void init() + { + synchronized ( this ) + { + if ( !_initialized ) + { + try + { + _random = SecureRandom.getInstance( SESSION_ID_RANDOM_ALGORITHM ); + } + catch ( NoSuchAlgorithmException e ) + { + _random = new Random(); + } + _random.setSeed( + _random.nextLong() ^ System.currentTimeMillis() ^ hashCode() ^ Runtime.getRuntime().freeMemory() ); + _initialized = true; + } + } + } +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/RandomBatchIdGenerator.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/deploy/RandomBatchIdGenerator.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/DefaultRetrievalResponse.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/DefaultRetrievalResponse.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/DefaultRetrievalResponse.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/DefaultRetrievalResponse.java Fri May 23 15:59:23 2008 @@ -0,0 +1,45 @@ +// ======================================================================== +// Copyright 2008 Sonatype Inc. +// ------------------------------------------------------------------------ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ======================================================================== +package org.apache.maven.mercury.client.retrieve; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.apache.maven.mercury.client.BatchException; + +public class DefaultRetrievalResponse implements RetrievalResponse +{ + private Set _exceptions = Collections.synchronizedSet( new HashSet() ); + + public DefaultRetrievalResponse() + { + } + + protected void add( BatchException exception ) + { + _exceptions.add( exception ); + } + + public Set getExceptions() + { + return _exceptions; + } + + public String toString() + { + return _exceptions.toString(); + } + +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/DefaultRetrievalResponse.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/DefaultRetrievalResponse.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/DefaultRetriever.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/DefaultRetriever.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/DefaultRetriever.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/DefaultRetriever.java Fri May 23 15:59:23 2008 @@ -0,0 +1,245 @@ +// ======================================================================== +// Copyright 2008 Sonatype Inc. +// ------------------------------------------------------------------------ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ======================================================================== +package org.apache.maven.mercury.client.retrieve; + +import org.apache.maven.mercury.client.BatchException; +import org.apache.maven.mercury.client.Binding; +import org.mortbay.jetty.client.HttpClient; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + + +public class DefaultRetriever implements Retriever +{ + private HttpClient _httpClient; + + public DefaultRetriever() + throws BatchException + { + // TODO take the default settings for now + _httpClient = new HttpClient(); + _httpClient.setConnectorType( HttpClient.CONNECTOR_SELECT_CHANNEL ); + try + { + _httpClient.start(); + } + catch ( Exception e ) + { + throw new BatchException( null, "unable to start http client", e ); + } + } + + public DefaultRetriever( HttpClient client ) + throws BatchException + { + // TODO take the default settings for now + _httpClient = client; + try + { + if ( _httpClient.isStarted() ) + { + _httpClient.start(); + } + } + catch ( Exception e ) + { + throw new BatchException( null, "unable to start http client", e ); + } + } + + + /** + * Retrieve a set of artifacts and wait until all retrieved successfully + * or an error occurs. + *

+ * Note: whilst this method is synchronous for the caller, the implementation + * will be asynchronous so many artifacts are fetched in parallel. + * + * @param request + * @return the list of errors, if any + */ + public RetrievalResponse retrieve( RetrievalRequest request ) + { + final RetrievalResponse[] response = new RetrievalResponse[]{null}; + + retrieve( request, new RetrievalCallback() + { + public void onComplete( RetrievalResponse r ) + { + synchronized ( response ) + { + response[0] = r; + response.notify(); + } + } + } ); + + synchronized ( response ) + { + try + { + while ( response[0] == null ) + { + response.wait(); + } + } + catch ( InterruptedException e ) + { + return null; + } + return response[0]; + } + } + + /** + * Retrieve a set of artifacts without waiting for the results. + * When all results have been obtained (or an error occurs) the + * RetrievalResponse will be called. + * + * @param request + * @param callback + */ + public void retrieve( final RetrievalRequest request, final RetrievalCallback callback ) + { + if ( request == null ) + { + throw new IllegalArgumentException( "No request" ); + } + + if ( callback == null ) + { + throw new IllegalArgumentException( "No callback" ); + } + + final AtomicInteger count = new AtomicInteger( request.getBindings().size() ); + + final List targets = new ArrayList( request.getBindings().size() ); + final DefaultRetrievalResponse response = new DefaultRetrievalResponse(); + + Binding[] bindings = new Binding[request.getBindings().size()]; + request.getBindings().toArray( bindings ); + + for ( int i = 0; i < bindings.length && count.get() > 0; i++ ) + { + final Binding binding = bindings[i]; + RetrievalTarget target = null; + try + { + target = new RetrievalTarget( DefaultRetriever.this, binding, request.getValidators() ) + { + public void onComplete() + { + //got the file, check the checksum + boolean checksumOK = verifyChecksum(); + if ( !checksumOK ) + { + response.add( new BatchException( binding, + "Checksum failed: " + getRetrievedChecksum() + "!=" + getCalculatedChecksum() ) ); + } + + //if the file checksum is ok, then apply the validators + if ( checksumOK ) + { + List validateErrors = new ArrayList(); + if ( !validate( validateErrors ) ) + { + for ( String s : validateErrors ) + { + response.add( new BatchException( binding, s ) ); + } + } + } + + if ( DefaultRetriever.this.isComplete( count, request, response, targets ) ) + { + callback.onComplete( response ); + } + } + + public void onError( BatchException exception ) + { + response.add( exception ); + if ( DefaultRetriever.this.isComplete( count, request, response, targets ) ) + { + callback.onComplete( response ); + } + } + }; + + targets.add( target ); + } + catch ( Exception e ) + { + response.add( new BatchException( binding, e ) ); + if ( isComplete( count, request, response, targets ) ) + { + callback.onComplete( response ); + } + } + } + + for ( final RetrievalTarget target : targets ) + { + target.retrieve(); //go get the remote file + } + } + + private boolean isComplete( AtomicInteger count, + RetrievalRequest request, + RetrievalResponse response, + List targets ) + { + boolean completor = count.decrementAndGet() == 0; + if ( !completor && request.isFailFast() && response.getExceptions().size() > 0 ) + { + completor = count.getAndSet( 0 ) > 0; + } + + if ( completor ) + { + if ( response.getExceptions().size() == 0 ) + { + for ( RetrievalTarget t : targets ) + { + if ( t != null ) + { + t.move(); + } + } + } + + for ( RetrievalTarget t : targets ) + { + t.cleanup(); + } + return true; + } + + return false; + } + + + /** + * Get the jetty async client + * + * @return + */ + public HttpClient getHttpClient() + { + return _httpClient; + } + +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/DefaultRetriever.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/DefaultRetriever.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/FileGetExchange.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/FileGetExchange.java?rev=659700&view=auto ============================================================================== --- maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/FileGetExchange.java (added) +++ maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/FileGetExchange.java Fri May 23 15:59:23 2008 @@ -0,0 +1,147 @@ +// ======================================================================== +// Copyright 2008 Sonatype Inc. +// ------------------------------------------------------------------------ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ======================================================================== +package org.apache.maven.mercury.client.retrieve; + +import org.apache.maven.mercury.client.BatchException; +import org.apache.maven.mercury.client.Binding; +import org.apache.maven.mercury.client.ChecksumCalculator; +import org.apache.maven.mercury.client.FileExchange; +import org.mortbay.io.Buffer; +import org.mortbay.jetty.HttpMethods; +import org.mortbay.jetty.client.HttpClient; + +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.security.DigestOutputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + + +/** + * FileGetExchange + *

+ * Make an asynchronous request to download a file and stream its bytes to a file. + * When all bytes have been received onFileComplete will be called. + *

+ * As an optimization, the file that is being downloaded can have it's + * SHA-1 digest calculated as it is being streamed down. + */ +public abstract class FileGetExchange extends FileExchange +{ + private OutputStream _outputStream; + + /** + * Constructor. + * + * @param binding the remote file to fetch + * @param localFile the local file location to store the remote file + * @param digestRequired if true, the file stream will be passed thru the digest calculator + * @param client async http client + */ + public FileGetExchange( Binding binding, File localFile, boolean digestRequired, HttpClient client ) + { + super( binding, localFile, digestRequired, client ); + } + + + /** Start the retrieval. */ + public void send() + { + setMethod( HttpMethods.GET ); + super.send(); + } + + + protected void onResponseComplete() + { + //All bytes of file have been received + String digest = null; + + try + { + if ( _status == HttpServletResponse.SC_NOT_FOUND ) + { + onFileError( _url, new FileNotFoundException( "File not found on remote server" ) ); + return; + } + else if ( _status != HttpServletResponse.SC_OK ) + { + onFileError( _url, new Exception( "Http status code=" + _status ) ); + return; + } + + if ( _digestRequired && _outputStream != null ) + { + byte[] bytes = ( (DigestOutputStream) _outputStream ).getMessageDigest().digest(); + digest = ChecksumCalculator.encodeToAsciiHex( bytes ); + } + onFileComplete( _url, _localFile, digest ); + } + catch ( Exception e ) + { + onFileError( _url, new BatchException( _binding, e.getLocalizedMessage() ) ); + } + } + + + /** + * Stream the downloaded bytes to a file + * + * @see org.mortbay.jetty.client.HttpExchange$ContentExchange#onResponseContent(org.sonatype.io.Buffer) + */ + protected void onResponseContent( Buffer content ) + throws IOException + { + try + { + OutputStream os = getOutputStream(); + content.writeTo( os ); + } + catch ( NoSuchAlgorithmException e ) + { + throw new IOException( e.getLocalizedMessage() ); + } + } + + + /** + * Get an output stream for the file contents. A digest can be optionally calculated + * for the file contents as they are being streamed. + * + * @return OutputStream for file contents + * @throws IOException if io error occurs + * @throws NoSuchAlgorithmException if the SHA-1 algorithm is not supported + */ + protected OutputStream getOutputStream() + throws IOException, NoSuchAlgorithmException + { + if ( _outputStream == null ) + { + if ( !_digestRequired ) + { + _outputStream = new FileOutputStream( _localFile ); + } + else + { + MessageDigest digest = MessageDigest.getInstance( _digestAlgorithm ); + _outputStream = new DigestOutputStream( new FileOutputStream( _localFile ), digest ); + } + } + return _outputStream; + } +} Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/FileGetExchange.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/mercury/src/main/java/org/apache/maven/mercury/client/retrieve/FileGetExchange.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision"