From e54b2753e4356339f64171cda07850ae6de3fa9a Mon Sep 17 00:00:00 2001 From: Alex Klyubin Date: Mon, 13 Jun 2016 10:19:26 -0700 Subject: [PATCH] More general OutputStreamDataSink. This replaces the less general DataSink which outputs into a ByteArrayOutputStream with a more general DataSink which outputs into an OutputStream. Bug: 27461702 Change-Id: I9467f38c41f586b71f35edb3602fd6e57153184f --- .../core/DefaultApkSignerEngine.java | 17 ++-- .../util/ByteArrayOutputStreamSink.java | 62 --------------- .../internal/util/OutputStreamDataSink.java | 78 +++++++++++++++++++ .../apksigner/core/util/DataSinks.java | 36 +++++++++ 4 files changed, 125 insertions(+), 68 deletions(-) delete mode 100644 tools/apksigner/core/src/com/android/apksigner/core/internal/util/ByteArrayOutputStreamSink.java create mode 100644 tools/apksigner/core/src/com/android/apksigner/core/internal/util/OutputStreamDataSink.java create mode 100644 tools/apksigner/core/src/com/android/apksigner/core/util/DataSinks.java diff --git a/tools/apksigner/core/src/com/android/apksigner/core/DefaultApkSignerEngine.java b/tools/apksigner/core/src/com/android/apksigner/core/DefaultApkSignerEngine.java index 612f4fd6f..1c6b622c0 100644 --- a/tools/apksigner/core/src/com/android/apksigner/core/DefaultApkSignerEngine.java +++ b/tools/apksigner/core/src/com/android/apksigner/core/DefaultApkSignerEngine.java @@ -19,12 +19,13 @@ package com.android.apksigner.core; import com.android.apksigner.core.internal.apk.v1.DigestAlgorithm; import com.android.apksigner.core.internal.apk.v1.V1SchemeSigner; import com.android.apksigner.core.internal.apk.v2.V2SchemeSigner; -import com.android.apksigner.core.internal.util.ByteArrayOutputStreamSink; import com.android.apksigner.core.internal.util.MessageDigestSink; import com.android.apksigner.core.internal.util.Pair; import com.android.apksigner.core.util.DataSink; +import com.android.apksigner.core.util.DataSinks; import com.android.apksigner.core.util.DataSource; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.security.InvalidKeyException; import java.security.MessageDigest; @@ -593,7 +594,8 @@ public class DefaultApkSignerEngine implements ApkSignerEngine { private final Object mLock = new Object(); private boolean mDone; - private ByteArrayOutputStreamSink mBuf; + private DataSink mDataSink; + private ByteArrayOutputStream mDataSinkBuf; private GetJarEntryDataRequest(String entryName) { mEntryName = entryName; @@ -608,10 +610,13 @@ public class DefaultApkSignerEngine implements ApkSignerEngine { public DataSink getDataSink() { synchronized (mLock) { checkNotDone(); - if (mBuf == null) { - mBuf = new ByteArrayOutputStreamSink(); + if (mDataSinkBuf == null) { + mDataSinkBuf = new ByteArrayOutputStream(); } - return mBuf; + if (mDataSink == null) { + mDataSink = DataSinks.asDataSink(mDataSinkBuf); + } + return mDataSink; } } @@ -644,7 +649,7 @@ public class DefaultApkSignerEngine implements ApkSignerEngine { if (!mDone) { throw new IllegalStateException("Not yet done"); } - return (mBuf != null) ? mBuf.getData() : new byte[0]; + return (mDataSinkBuf != null) ? mDataSinkBuf.toByteArray() : new byte[0]; } } } diff --git a/tools/apksigner/core/src/com/android/apksigner/core/internal/util/ByteArrayOutputStreamSink.java b/tools/apksigner/core/src/com/android/apksigner/core/internal/util/ByteArrayOutputStreamSink.java deleted file mode 100644 index ca79df7db..000000000 --- a/tools/apksigner/core/src/com/android/apksigner/core/internal/util/ByteArrayOutputStreamSink.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * 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 com.android.apksigner.core.internal.util; - -import com.android.apksigner.core.util.DataSink; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; - -/** - * Data sink which stores all input data into an internal {@link ByteArrayOutputStream}, thus - * accepting an arbitrary amount of data. - */ -public class ByteArrayOutputStreamSink implements DataSink { - - private final ByteArrayOutputStream mBuf = new ByteArrayOutputStream(); - - @Override - public void consume(byte[] buf, int offset, int length) { - mBuf.write(buf, offset, length); - } - - @Override - public void consume(ByteBuffer buf) { - if (!buf.hasRemaining()) { - return; - } - - if (buf.hasArray()) { - mBuf.write( - buf.array(), - buf.arrayOffset() + buf.position(), - buf.remaining()); - buf.position(buf.limit()); - } else { - byte[] tmp = new byte[buf.remaining()]; - buf.get(tmp); - mBuf.write(tmp, 0, tmp.length); - } - } - - /** - * Returns the data received so far. - */ - public byte[] getData() { - return mBuf.toByteArray(); - } -} diff --git a/tools/apksigner/core/src/com/android/apksigner/core/internal/util/OutputStreamDataSink.java b/tools/apksigner/core/src/com/android/apksigner/core/internal/util/OutputStreamDataSink.java new file mode 100644 index 000000000..bf18ca0cb --- /dev/null +++ b/tools/apksigner/core/src/com/android/apksigner/core/internal/util/OutputStreamDataSink.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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 com.android.apksigner.core.internal.util; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; + +import com.android.apksigner.core.util.DataSink; + +/** + * {@link DataSink} which outputs received data into the associated {@link OutputStream}. + */ +public class OutputStreamDataSink implements DataSink { + + private static final int MAX_READ_CHUNK_SIZE = 65536; + + private final OutputStream mOut; + + /** + * Constructs a new {@code OutputStreamDataSink} which outputs received data into the provided + * {@link OutputStream}. + */ + public OutputStreamDataSink(OutputStream out) { + if (out == null) { + throw new NullPointerException("out == null"); + } + mOut = out; + } + + /** + * Returns {@link OutputStream} into which this data sink outputs received data. + */ + public OutputStream getOutputStream() { + return mOut; + } + + @Override + public void consume(byte[] buf, int offset, int length) throws IOException { + mOut.write(buf, offset, length); + } + + @Override + public void consume(ByteBuffer buf) throws IOException { + if (!buf.hasRemaining()) { + return; + } + + if (buf.hasArray()) { + mOut.write( + buf.array(), + buf.arrayOffset() + buf.position(), + buf.remaining()); + buf.position(buf.limit()); + } else { + byte[] tmp = new byte[Math.min(buf.remaining(), MAX_READ_CHUNK_SIZE)]; + while (buf.hasRemaining()) { + int chunkSize = Math.min(buf.remaining(), tmp.length); + buf.get(tmp, 0, chunkSize); + mOut.write(tmp, 0, chunkSize); + } + } + } +} diff --git a/tools/apksigner/core/src/com/android/apksigner/core/util/DataSinks.java b/tools/apksigner/core/src/com/android/apksigner/core/util/DataSinks.java new file mode 100644 index 000000000..8ee1f1388 --- /dev/null +++ b/tools/apksigner/core/src/com/android/apksigner/core/util/DataSinks.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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 com.android.apksigner.core.util; + +import java.io.OutputStream; + +import com.android.apksigner.core.internal.util.OutputStreamDataSink; + +/** + * Utility methods for working with {@link DataSink} abstraction. + */ +public abstract class DataSinks { + private DataSinks() {} + + /** + * Returns a {@link DataSink} which outputs received data into the provided + * {@link OutputStream}. + */ + public static DataSink asDataSink(OutputStream out) { + return new OutputStreamDataSink(out); + } +}