// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:path/path.dart' as path; import 'package:yaml/yaml.dart'; import 'dart/package_map.dart'; import 'globals.dart'; const String _kFlutterManifestPath = 'flutter.yaml'; const String _kFlutterServicesManifestPath = 'flutter_services.yaml'; dynamic _loadYamlFile(String path) { printTrace("Looking for YAML at '$path'"); if (!FileSystemEntity.isFileSync(path)) return null; String manifestString = new File(path).readAsStringSync(); return loadYaml(manifestString); } /// Loads all services specified in `flutter.yaml`. Parses each service config file, /// storing meta data in [services] and the list of jar files in [jars]. Future parseServiceConfigs( List> services, { List jars } ) async { Map packageMap; try { packageMap = PackageMap.instance.map; } on FormatException catch(e) { printTrace('Invalid ".packages" file while parsing service configs:\n$e'); return; } dynamic manifest = _loadYamlFile(_kFlutterManifestPath); if (manifest == null || manifest['services'] == null) { printTrace('No services specified in the manifest'); return; } for (String service in manifest['services']) { String serviceRoot = packageMap[service].path; dynamic serviceConfig = _loadYamlFile('$serviceRoot/$_kFlutterServicesManifestPath'); if (serviceConfig == null) { printStatus('No $_kFlutterServicesManifestPath found for service "$serviceRoot"; skipping.'); continue; } for (Map service in serviceConfig['services']) { services.add({ 'root': serviceRoot, 'name': service['name'], 'android-class': service['android-class'], 'ios-framework': service['ios-framework'] }); } if (jars != null && serviceConfig['jars'] is Iterable) { for (String jar in serviceConfig['jars']) jars.add(new File(await getServiceFromUrl(jar, serviceRoot, service, unzip: false))); } } } Future getServiceFromUrl( String url, String rootDir, String serviceName, { bool unzip: false } ) async { if (url.startsWith("android-sdk:") && androidSdk != null) { // It's something shipped in the standard android SDK. return url.replaceAll('android-sdk:', '${androidSdk.directory}/'); } else if (url.startsWith("http")) { // It's a regular file to download. return await cache.getThirdPartyFile(url, serviceName, unzip: unzip); } else { // Assume url is a path relative to the service's root dir. return path.join(rootDir, url); } } /// Outputs a services.json file for the flutter engine to read. Format: /// { /// services: [ /// { name: string, framework: string }, /// ... /// ] /// } File generateServiceDefinitions( String dir, List> servicesIn ) { List> services = servicesIn.map((Map service) => { 'name': service['name'], 'class': service['android-class'] }).toList(); Map json = { 'services': services }; File servicesFile = new File(path.join(dir, 'services.json')); servicesFile.writeAsStringSync(JSON.encode(json), mode: FileMode.WRITE, flush: true); return servicesFile; }