1 /* 2 * Copyright (C) 2018 The Android Open Source Project 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 17 package com.android.layout.remote.api; 18 19 import com.android.ide.common.rendering.api.ResourceNamespace.Resolver; 20 import com.android.ide.common.rendering.api.ResourceValue; 21 import com.android.layout.remote.util.RemoteResolverAdapter; 22 import com.android.tools.layoutlib.annotations.NotNull; 23 import com.android.tools.layoutlib.annotations.Nullable; 24 25 import java.io.Serializable; 26 import java.rmi.RemoteException; 27 28 /** 29 * Wrapper for {@link ResourceValue} that can be transferred to a different VM. 30 * 31 * @param <T> the ResourceValue instance type 32 */ 33 public class RemoteResourceValue<T extends ResourceValue> implements Serializable { 34 private static final RemoteResourceValue<ResourceValue> NULL_INSTANCE = 35 new RemoteResourceValue<>(null, null); 36 37 private final T mResourceValue; 38 private final RemoteNamespaceResolver mRemoteResolver; 39 RemoteResourceValue(@ullable T resourceValue, @Nullable RemoteNamespaceResolver remoteResolver)40 private RemoteResourceValue(@Nullable T resourceValue, 41 @Nullable RemoteNamespaceResolver remoteResolver) { 42 mResourceValue = resourceValue; 43 mRemoteResolver = remoteResolver; 44 } 45 46 /** 47 * Returns a RemoteResourceValue that wraps the given {@link ResourceValue} instance. The passed 48 * resource value can be null. 49 */ 50 @NotNull fromResourceValue( T resourceValue)51 public static <T extends ResourceValue> RemoteResourceValue<T> fromResourceValue( 52 T resourceValue) { 53 if (resourceValue == null) { 54 //noinspection unchecked 55 return (RemoteResourceValue<T>) NULL_INSTANCE; 56 } 57 try { 58 return new RemoteResourceValue<>(resourceValue, 59 RemoteResolverAdapter.create(resourceValue.getNamespaceResolver())); 60 61 } catch (RemoteException e) { 62 throw new RuntimeException(e); 63 } 64 } 65 66 /** 67 * Returns the {@link ResourceValue} wrapped by a remote wrapper 68 */ 69 @NotNull toResourceValue( @otNull RemoteResourceValue<T> remoteResourceValue)70 private static <T extends ResourceValue> T toResourceValue( 71 @NotNull RemoteResourceValue<T> remoteResourceValue) { 72 T remoteValue = remoteResourceValue.mResourceValue; 73 if (remoteValue == null) { 74 return null; 75 } 76 77 // The Resolver is not transferred in the ResourceValue (it's transient) so we use the 78 // information in the wrapper to reconstruct it. 79 RemoteNamespaceResolver remoteResolver = remoteResourceValue.mRemoteResolver; 80 81 // TODO: Rethink this as setNamespaceResolver is not available in prebuilts any more 82 // if (remoteResolver != null) { 83 // remoteValue.setNamespaceResolver(new Resolver() { 84 // @Override 85 // public String prefixToUri(String namespacePrefix) { 86 // try { 87 // return remoteResolver.remotePrefixToUri(namespacePrefix); 88 // } catch (RemoteException e) { 89 // throw new RuntimeException(e); 90 // } 91 // } 92 // 93 // @Override 94 // public String uriToPrefix(String namespaceUri) { 95 // try { 96 // return remoteResolver.remoteUriToPrefix(namespaceUri); 97 // } catch (RemoteException e) { 98 // throw new RuntimeException(e); 99 // } 100 // } 101 // }); 102 // } 103 // else { 104 // remoteValue.setNamespaceResolver(Resolver.EMPTY_RESOLVER); 105 // } 106 107 return remoteValue; 108 } 109 110 /** 111 * Returns the {@link ResourceValue} wrapped by this remote wrapper 112 */ 113 @NotNull toResourceValue()114 public T toResourceValue() { 115 return RemoteResourceValue.toResourceValue(this); 116 } 117 } 118