1 /* 2 * Copyright 2021 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 * https://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.enterprise.connectedapps.processor.containers; 17 18 import com.google.android.enterprise.connectedapps.annotations.UncaughtExceptionsPolicy; 19 import com.google.android.enterprise.connectedapps.processor.SupportedTypes; 20 import com.google.auto.value.AutoValue; 21 import com.squareup.javapoet.ClassName; 22 import java.util.Optional; 23 import java.util.function.Function; 24 import javax.lang.model.element.TypeElement; 25 26 /** Wrapper of the connectors specified for a connected app. */ 27 @AutoValue 28 public abstract class ConnectorInfo { 29 30 private static final String CROSS_PROFILE_CONNECTOR_QUALIFIED_NAME = 31 "com.google.android.enterprise.connectedapps.CrossProfileConnector"; 32 private static final String CROSS_USER_CONNECTOR_QUALIFIED_NAME = 33 "com.google.android.enterprise.connectedapps.CrossUserConnector"; 34 private static final String PROFILE_CONNECTOR_QUALIFIED_NAME = 35 "com.google.android.enterprise.connectedapps.ProfileConnector"; 36 private static final String USER_CONNECTOR_QUALIFIED_NAME = 37 "com.google.android.enterprise.connectedapps.UserConnector"; 38 isProfileConnector(Context context, TypeElement connectorElement)39 public static boolean isProfileConnector(Context context, TypeElement connectorElement) { 40 return isConnectorOfType(context, connectorElement, PROFILE_CONNECTOR_QUALIFIED_NAME); 41 } 42 isUserConnector(Context context, TypeElement connectorElement)43 public static boolean isUserConnector(Context context, TypeElement connectorElement) { 44 return isConnectorOfType(context, connectorElement, USER_CONNECTOR_QUALIFIED_NAME); 45 } 46 isConnectorOfType( Context context, TypeElement connectorElement, String requiredType)47 private static boolean isConnectorOfType( 48 Context context, TypeElement connectorElement, String requiredType) { 49 return context 50 .types() 51 .isAssignable( 52 connectorElement.asType(), context.elements().getTypeElement(requiredType).asType()); 53 } 54 hasCrossProfileConnector()55 public boolean hasCrossProfileConnector() { 56 return profileConnector().isPresent(); 57 } 58 hasCrossUserConnector()59 public boolean hasCrossUserConnector() { 60 return userConnector().isPresent(); 61 } 62 profileConnector()63 public abstract Optional<ProfileConnectorInfo> profileConnector(); 64 userConnector()65 public abstract Optional<UserConnectorInfo> userConnector(); 66 connectorElement()67 public TypeElement connectorElement() { 68 return getElement(ProfileConnectorInfo::connectorElement, UserConnectorInfo::connectorElement); 69 } 70 connectorClassName()71 public ClassName connectorClassName() { 72 return getElement( 73 ProfileConnectorInfo::connectorClassName, UserConnectorInfo::connectorClassName); 74 } 75 serviceName()76 public ClassName serviceName() { 77 return getElement(ProfileConnectorInfo::serviceName, UserConnectorInfo::serviceName); 78 } 79 supportedTypes()80 public SupportedTypes supportedTypes() { 81 return getElement(ProfileConnectorInfo::supportedTypes, UserConnectorInfo::supportedTypes); 82 } 83 uncaughtExceptionsPolicy()84 public UncaughtExceptionsPolicy uncaughtExceptionsPolicy() { 85 return profileConnector() 86 .map(ProfileConnectorInfo::uncaughtExceptionsPolicy) 87 .orElse(UncaughtExceptionsPolicy.NOTIFY_RETHROW); 88 } 89 90 /** 91 * Tries to get an element from {@link #profileConnector()} if present, or from {@link 92 * #userConnector()} otherwise. 93 * 94 * <p>Throws an exception if no connectors are specified, but this should not be possible (now and 95 * in the future). 96 */ getElement( Function<ProfileConnectorInfo, T> getFromProfileConnector, Function<UserConnectorInfo, T> getFromUserConnector)97 private <T> T getElement( 98 Function<ProfileConnectorInfo, T> getFromProfileConnector, 99 Function<UserConnectorInfo, T> getFromUserConnector) { 100 return profileConnector() 101 .map(getFromProfileConnector) 102 .orElseGet( 103 () -> 104 userConnector() 105 .map(getFromUserConnector) 106 .orElseThrow( 107 () -> new UnsupportedOperationException("No connectors specified"))); 108 } 109 invalid( Context context, TypeElement connector, SupportedTypes globalSupportedTypes)110 public static ConnectorInfo invalid( 111 Context context, TypeElement connector, SupportedTypes globalSupportedTypes) { 112 return noSpecificConnector(context, globalSupportedTypes, connector, connector); 113 } 114 unspecified(Context context, SupportedTypes globalSupportedTypes)115 public static ConnectorInfo unspecified(Context context, SupportedTypes globalSupportedTypes) { 116 return noSpecificConnector( 117 context, 118 globalSupportedTypes, 119 context.elements().getTypeElement(CROSS_PROFILE_CONNECTOR_QUALIFIED_NAME), 120 context.elements().getTypeElement(CROSS_USER_CONNECTOR_QUALIFIED_NAME)); 121 } 122 noSpecificConnector( Context context, SupportedTypes globalSupportedTypes, TypeElement profileConnector, TypeElement userConnector)123 private static ConnectorInfo noSpecificConnector( 124 Context context, 125 SupportedTypes globalSupportedTypes, 126 TypeElement profileConnector, 127 TypeElement userConnector) { 128 return new AutoValue_ConnectorInfo( 129 Optional.of(ProfileConnectorInfo.create(context, profileConnector, globalSupportedTypes)), 130 Optional.of(UserConnectorInfo.create(context, userConnector, globalSupportedTypes))); 131 } 132 forProfileConnector( Context context, TypeElement connectorElement, SupportedTypes globalSupportedTypes)133 public static ConnectorInfo forProfileConnector( 134 Context context, TypeElement connectorElement, SupportedTypes globalSupportedTypes) { 135 return new AutoValue_ConnectorInfo( 136 Optional.of(ProfileConnectorInfo.create(context, connectorElement, globalSupportedTypes)), 137 Optional.empty()); 138 } 139 forUserConnector( Context context, TypeElement connectorElement, SupportedTypes globalSupportedTypes)140 public static ConnectorInfo forUserConnector( 141 Context context, TypeElement connectorElement, SupportedTypes globalSupportedTypes) { 142 return new AutoValue_ConnectorInfo( 143 Optional.empty(), 144 Optional.of(UserConnectorInfo.create(context, connectorElement, globalSupportedTypes))); 145 } 146 } 147