summaryrefslogtreecommitdiff
path: root/src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/packaging/sign/ManifestDigester.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/packaging/sign/ManifestDigester.java')
-rw-r--r--src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/packaging/sign/ManifestDigester.java185
1 files changed, 185 insertions, 0 deletions
diff --git a/src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/packaging/sign/ManifestDigester.java b/src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/packaging/sign/ManifestDigester.java
new file mode 100644
index 0000000..9ebcee6
--- /dev/null
+++ b/src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/packaging/sign/ManifestDigester.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2012 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.motorolamobility.studio.android.certmanager.packaging.sign;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+import com.motorola.studio.android.common.log.StudioLogger;
+
+/**
+ * This class is a Manifest digester.
+ * It generates digested hashes for each entry in the manifest file.
+ */
+public class ManifestDigester
+{
+ private final Manifest manifest;
+
+ private HashMap<String, ManifestEntry> entries = null;
+
+ /**
+ * Create a new manifest digester with the given manifest
+ * @param manifest
+ */
+ public ManifestDigester(final Manifest manifest)
+ {
+ this.manifest = manifest;
+ initialize();
+ }
+
+ /**
+ * Initialize the digester creating internal entries for each manifest entry
+ */
+ private void initialize()
+ {
+ Map<String, Attributes> manifestEntries = manifest.getEntries();
+
+ // initialize internal entries list
+ entries = new HashMap<String, ManifestEntry>(manifestEntries.size());
+ for (String entryName : manifestEntries.keySet())
+ {
+ entries.put(entryName, new ManifestEntry(entryName, manifestEntries.get(entryName)));
+ }
+ }
+
+ /**
+ * Get this Manifest file digested
+ * @throws IOException if some error occurs during entries encoding
+ */
+ public String getDigestedString() throws IOException
+ {
+ StringBuilder builder = new StringBuilder();
+ for (ManifestEntry entry : entries.values())
+ {
+ builder.append(entry.toDigestedManifestEntry());
+ builder.append(ManifestEntry.MANIFEST_NEW_LINE);
+ }
+ return builder.toString();
+ }
+
+ public HashMap<String, ManifestEntry> getEntries()
+ {
+ return entries;
+ }
+
+ /**
+ * Computes the digest for the main manifest attributes
+ *
+ * @return the digest of the main manifest attributes or null otherwise
+ * @throws SignException
+ * if a processing error occurs when computing the digest
+ */
+ public byte[] getDigestedManifestMainAttributes() throws SignException
+ {
+ // create an auxiliary manifest that contain only the main attributes
+ // of the original manifest
+ Manifest auxManifest = new Manifest();
+ byte[] result;
+ Attributes auxMainAttributes = auxManifest.getMainAttributes();
+ Attributes mainAttributes = manifest.getMainAttributes();
+ for (Object attributeKey : mainAttributes.keySet())
+ {
+ String name = attributeKey.toString();
+ String value = mainAttributes.getValue(name);
+ auxMainAttributes.putValue(name, value);
+ }
+
+ result = getDigestedManifest(auxManifest);
+
+ StudioLogger.info(SignatureFile.class, "Created digest for main manifest attributes");
+
+ return result;
+ }
+
+ /**
+ * Get this Manifest digested
+ * @return
+ * @throws SignException
+ */
+ public byte[] getDigestedManifest() throws SignException
+ {
+ return getDigestedManifest(manifest);
+ }
+
+ /**
+ * Computes the digest for the manifest
+ *
+ * @param manifest
+ * the manifest to be digested
+ * @return the digest of the entire manifest or null otherwise
+ * @throws SignException
+ * if a processing error occurs when computing the digest
+ */
+ public static byte[] getDigestedManifest(Manifest manifest) throws SignException
+ {
+ byte[] digestedManifestBytes = null;
+ ByteArrayOutputStream baos = null;
+ try
+ {
+ MessageDigest messageDigest = MessageDigest.getInstance(ISignConstants.SHA1);
+ baos = new ByteArrayOutputStream();
+ manifest.write(baos);
+
+ messageDigest.reset();
+ digestedManifestBytes = messageDigest.digest(baos.toByteArray());
+ }
+ catch (IOException e)
+ {
+ StudioLogger.error(SignatureFile.class,
+ "I/O error encoding manifest digest: " + e.getMessage());
+
+ throw new SignException("I/O error encoding manifest digest", e);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ StudioLogger.error(SignatureFile.class, "Error getting message digester");
+
+ throw new SignException("Could digest the manifest");
+ }
+ finally
+ {
+ try
+ {
+ if (baos != null)
+ {
+ baos.close();
+ }
+ }
+ catch (IOException e)
+ {
+ //do nothing
+ }
+ }
+
+ if (digestedManifestBytes == null)
+ {
+ StudioLogger.error(SignatureFile.class, "Error encoding manifest digest");
+
+ throw new SignException("Could not encode manifest digest");
+ }
+
+ StudioLogger.info(SignatureFile.class, "Created manifest digest");
+
+ return digestedManifestBytes;
+ }
+} \ No newline at end of file