• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Google LLC
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.android.libraries.mobiledatadownload.file.common.internal;
17 
18 import android.net.Uri;
19 import android.text.TextUtils;
20 import com.google.common.base.Joiner;
21 import com.google.common.base.Splitter;
22 import com.google.common.collect.ImmutableList;
23 import java.util.List;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
26 import javax.annotation.Nullable;
27 
28 /**
29  * The fragment parser, unfortunately, is rather large in code size. This class provides some
30  * lighter utilities for accessing and manipulating the transform fragment param. It provides a
31  * strict subset of the functionality in {@link Fragment}.
32  *
33  * <p>In particular, it does not support
34  *
35  * <ul>
36  *   <li>Encoded transform names.
37  *   <li>Parsing transform params.
38  * </ul>
39  */
40 public final class LiteTransformFragments {
41 
42   private static final Pattern XFORM_NAME_PATTERN = Pattern.compile("(\\w+).*");
43   private static final String XFORM_FRAGMENT_PREFIX = "transform=";
44 
45   /**
46    * Parses URI fragment, returning the names of the transforms that are enabled. Has the following
47    * limitations:
48    *
49    * <ul>
50    *   <li>Ignores subparams. To access those, use {@link Fragment} from your transform.
51    *   <li>Requires the fragment start with "transform=".
52    *   <li>Requires encoded transform name to contain only word chars (ie, \w).
53    * </ul>
54    */
parseTransformNames(Uri uri)55   public static ImmutableList<String> parseTransformNames(Uri uri) {
56     ImmutableList.Builder<String> builder = ImmutableList.builder();
57     for (String spec : parseTransformSpecs(uri)) {
58       builder.add(parseSpecName(spec));
59     }
60     return builder.build();
61   }
62 
63   /**
64    * Parses URI fragment, returning the transforms specs found. Has the following limitations:
65    *
66    * <ul>
67    *   <li>Requires the fragment start with "transform=".
68    * </ul>
69    *
70    * @return List of encoded transform specs - eg "integrity(sha256=abc123)"
71    */
parseTransformSpecs(Uri uri)72   public static ImmutableList<String> parseTransformSpecs(Uri uri) {
73     String fragment = uri.getEncodedFragment();
74     if (TextUtils.isEmpty(fragment) || !fragment.startsWith(XFORM_FRAGMENT_PREFIX)) {
75       return ImmutableList.of();
76     }
77     String specs = fragment.substring(XFORM_FRAGMENT_PREFIX.length());
78     return ImmutableList.copyOf(Splitter.on("+").omitEmptyStrings().split(specs));
79   }
80 
81   /**
82    * Parse the name from an encoded transform spec. For example, "integrity(sha256=abc123)" would
83    * return "integrity". Has the following limitations:
84    *
85    * <ul>
86    *   <li>Ignores subparams. To access those, use {@link Fragment} from your transform.
87    *   <li>Requires encoded transform name to contain only word chars (ie, \w).
88    * </ul>
89    */
parseSpecName(String encodedSpec)90   public static String parseSpecName(String encodedSpec) {
91     Matcher matcher = XFORM_NAME_PATTERN.matcher(encodedSpec);
92     if (!matcher.matches()) {
93       throw new IllegalArgumentException("Invalid fragment spec: " + encodedSpec);
94     }
95     return matcher.group(1);
96   }
97 
98   /**
99    * Joins the encoded transform specs to produce an encoded transform fragment suitable for adding
100    * to a Uri with {@link Uri.Builder#encodedFragment}.
101    */
102   @Nullable
joinTransformSpecs(List<String> encodedSpecs)103   public static String joinTransformSpecs(List<String> encodedSpecs) {
104     if (encodedSpecs.isEmpty()) {
105       return null;
106     }
107     return XFORM_FRAGMENT_PREFIX + Joiner.on("+").join(encodedSpecs);
108   }
109 
LiteTransformFragments()110   private LiteTransformFragments() {}
111 }
112