/** * Returns the {@link ResourceFile} matching the given name, {@link ResourceType} and * configuration. * * <p>This only works with files generating one resource named after the file (for instance, * layouts, bitmap based drawable, xml, anims). * * @param name the resource name or file name * @param type the folder type search for * @param config the folder configuration to match for * @return the matching file or <code>null</code> if no match was found. */ @Nullable public ResourceFile getMatchingFile( @NonNull String name, @NonNull ResourceType type, @NonNull FolderConfiguration config) { ensureInitialized(); String resourceName = name; int dot = resourceName.indexOf('.'); if (dot != -1) { resourceName = resourceName.substring(0, dot); } Map<String, ResourceItem> items = mResourceMap.get(type); if (items != null) { ResourceItem item = items.get(resourceName); if (item != null) { List<ResourceFile> files = item.getSourceFileList(); if (files != null) { if (files.size() > 1) { ResourceValue value = item.getResourceValue(type, config, isFrameworkRepository()); if (value != null) { String v = value.getValue(); if (v != null) { ResourceUrl url = ResourceUrl.parse(v); if (url != null) { return getMatchingFile(url.name, url.type, config); } else { // Looks like the resource value is pointing to a file // It's most likely one of the source files for this // resource item, so check those first for (ResourceFile f : files) { if (v.equals(f.getFile().getOsLocation())) { // Found the file return f; } } // No; look up the resource file from the full path File file = new File(v); if (file.exists()) { ResourceFile f = findResourceFile(file); if (f != null) { return f; } } } } } } else if (files.size() == 1) { // Single file: see if it matches ResourceFile matchingFile = files.get(0); if (matchingFile.getFolder().getConfiguration().isMatchFor(config)) { return matchingFile; } } } } } return null; }
private ResourceValue resolveResValue(ResourceValue resValue, int depth) { if (resValue == null) { return null; } // if the resource value is null, we simply return it. String value = resValue.getValue(); if (value == null) { return resValue; } // else attempt to find another ResourceValue referenced by this one. ResourceValue resolvedResValue = findResValue(value, resValue.isFramework()); // if the value did not reference anything, then we simply return the input value if (resolvedResValue == null) { return resValue; } // detect potential loop due to mishandled namespace in attributes if (resValue == resolvedResValue || depth >= MAX_RESOURCE_INDIRECTION) { if (mLogger != null) { mLogger.error( LayoutLog.TAG_BROKEN, String.format( "Potential stack overflow trying to resolve '%s': cyclic resource definitions? Render may not be accurate.", value), null); } return resValue; } // otherwise, we attempt to resolve this new value as well return resolveResValue(resolvedResValue, depth + 1); }
@Override public ILayoutPullParser getParser(ResourceValue layoutResource) { boolean token = RenderSecurityManager.enterSafeRegion(mCredential); try { return getParser(layoutResource.getName(), new File(layoutResource.getValue())); } finally { RenderSecurityManager.exitSafeRegion(token); } }
@Override public ResourceValue findResValue(String reference, boolean forceFrameworkOnly) { if (!mLookupChain.isEmpty() && reference.startsWith(PREFIX_RESOURCE_REF)) { ResourceValue prev = mLookupChain.get(mLookupChain.size() - 1); if (!reference.equals(prev.getValue())) { ResourceValue next = new ResourceValue(prev.getResourceType(), prev.getName(), prev.isFramework()); next.setValue(reference); mLookupChain.add(next); } } ResourceValue resValue = super.findResValue(reference, forceFrameworkOnly); if (resValue != null) { mLookupChain.add(resValue); } return resValue; }