1
0
mirror of https://github.com/bia-technologies/bsl-parser.git synced 2024-11-24 08:12:17 +02:00
bsl-parser/package-loader.os
aleksey.koryakin df39d1f593 #ONECICD-148
Исправлена ошибка использования библиотеки из пакета
2019-06-17 12:04:42 +03:00

277 lines
16 KiB
Plaintext

// Пояснения по переменным даны в конце модуля
Перем ПоказатьСообщенияЗагрузки;
Перем ВыдаватьОшибкуПриЗагрузкеУжеСуществующихКлассовМодулей;
Перем КэшМодулей;
Процедура ПриЗагрузкеБиблиотеки(Путь, СтандартнаяОбработка, Отказ)
Вывести("
|ПриЗагрузкеБиблиотеки " + Путь);
ФайлМанифеста = Новый Файл(ОбъединитьПути(Путь, "lib.config"));
Если ФайлМанифеста.Существует() Тогда
Вывести("Обрабатываем по манифесту");
СтандартнаяОбработка = Ложь;
ОбработатьМанифест(ФайлМанифеста.ПолноеИмя, Путь, Отказ);
Иначе
Вывести("Обрабатываем структуру каталогов по произвольному алгоритму");
ЗагрузитьМодулиБиблиотеки(ОбъединитьПути(Путь, "src"), СтандартнаяОбработка, Отказ);
КонецЕсли;
КонецПроцедуры
Процедура ОбработатьМанифест(Знач Файл, Знач Путь, Отказ)
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(Файл);
Чтение.ПерейтиКСодержимому();
Если Чтение.ЛокальноеИмя <> "package-def" Тогда
Отказ = Истина;
Чтение.Закрыть();
Возврат;
КонецЕсли;
Пока Чтение.Прочитать() Цикл
Если Чтение.ТипУзла = ТипУзлаXML.Комментарий Тогда
Продолжить;
КонецЕсли;
Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
Если Чтение.ЛокальноеИмя = "class" Тогда
ФайлКласса = Новый Файл(Путь + "/" + Чтение.ЗначениеАтрибута("file"));
Если ФайлКласса.Существует() и ФайлКласса.ЭтоФайл() Тогда
Идентификатор = Чтение.ЗначениеАтрибута("name");
Если Не ПустаяСтрока(Идентификатор) Тогда
Вывести(СтрШаблон(" класс %1, файл %2", Идентификатор, ФайлКласса.ПолноеИмя));
// ДобавитьКласс(ФайлКласса.ПолноеИмя, Идентификатор);
ДобавитьКлассЕслиРанееНеДобавляли(ФайлКласса.ПолноеИмя, Идентификатор);
КонецЕсли;
Иначе
ВызватьИсключение "Не найден файл " + ФайлКласса.ПолноеИмя + ", указанный в манифесте";
КонецЕсли;
Чтение.Прочитать(); // в конец элемента
КонецЕсли;
Если Чтение.ЛокальноеИмя = "module" Тогда
ФайлКласса = Новый Файл(Путь + "/" + Чтение.ЗначениеАтрибута("file"));
Если ФайлКласса.Существует() и ФайлКласса.ЭтоФайл() Тогда
Идентификатор = Чтение.ЗначениеАтрибута("name");
Если Не ПустаяСтрока(Идентификатор) Тогда
Вывести(СтрШаблон(" модуль %1, файл %2", Идентификатор, ФайлКласса.ПолноеИмя));
Попытка
ДобавитьМодульЕслиРанееНеДобавляли(ФайлКласса.ПолноеИмя, Идентификатор);
Исключение
Если ВыдаватьОшибкуПриЗагрузкеУжеСуществующихКлассовМодулей Тогда
ВызватьИсключение;
КонецЕсли;
Вывести("Предупреждение:
| " + ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецЕсли;
Иначе
ВызватьИсключение "Не найден файл " + ФайлКласса.ПолноеИмя + ", указанный в манифесте";
КонецЕсли;
Чтение.Прочитать(); // в конец элемента
КонецЕсли;
КонецЕсли;
КонецЦикла;
Чтение.Закрыть();
КонецПроцедуры
Процедура ЗагрузитьМодулиБиблиотеки(КорневойКаталог, СтандартнаяОбработка, Отказ)
// Загрузим служебные глобальные модули
ДобавитьМодульЕслиРанееНеДобавляли(ОбъединитьПути(КорневойКаталог, "Модули", "ПараметрыПродукта.os"), "ПараметрыПродукта");
КаталогПеречисления = ОбъединитьПути(КорневойКаталог, "Перечисления");
КаталогРеализации = ОбъединитьПути(КорневойКаталог, "Внутренние");
// Загрузим общие служебные модули
ОбработатьСтруктуруКаталоговПоСоглашению(ОбъединитьПути(КаталогРеализации, "Служебные"), СтандартнаяОбработка, Отказ);
// Загрузим перечисления
ОбработатьСтруктуруКаталоговПоСоглашению(КаталогПеречисления, СтандартнаяОбработка, Отказ);
// Загрузим внутренние модули реализации
Для Каждого Файл Из НайтиФайлы(КаталогРеализации, "*", Ложь) Цикл
Если Файл.ЭтоКаталог() Тогда
ОбработатьСтруктуруКаталоговПоСоглашению(Файл.ПолноеИмя, СтандартнаяОбработка, Отказ);
КонецЕсли;
КонецЦикла;
// Загрузим модули API
ОбработатьСтруктуруКаталоговПоСоглашению(КорневойКаталог, СтандартнаяОбработка, Отказ);
КонецПроцедуры
Процедура ОбработатьСтруктуруКаталоговПоСоглашению(Путь, СтандартнаяОбработка, Отказ)
КаталогиКлассов = Новый Массив;
КаталогиКлассов.Добавить(ОбъединитьПути(Путь, "Классы"));
КаталогиКлассов.Добавить(ОбъединитьПути(Путь, "Classes"));
КаталогиКлассов.Добавить(ОбъединитьПути(Путь, "src", "Классы"));
КаталогиКлассов.Добавить(ОбъединитьПути(Путь, "src", "Classes"));
КаталогиМодулей = Новый Массив;
КаталогиМодулей.Добавить(ОбъединитьПути(Путь, "Модули"));
КаталогиМодулей.Добавить(ОбъединитьПути(Путь, "Modules"));
КаталогиМодулей.Добавить(ОбъединитьПути(Путь, "src", "Модули"));
КаталогиМодулей.Добавить(ОбъединитьПути(Путь, "src", "Modules"));
Для Каждого мКаталог Из КаталогиКлассов Цикл
ОбработатьКаталогКлассов(мКаталог, СтандартнаяОбработка, Отказ);
КонецЦикла;
Для Каждого мКаталог Из КаталогиМодулей Цикл
ОбработатьКаталогМодулей(мКаталог, СтандартнаяОбработка, Отказ);
КонецЦикла;
КонецПроцедуры
Процедура ОбработатьКаталогКлассов(Знач Путь, СтандартнаяОбработка, Отказ)
КаталогКлассов = Новый Файл(Путь);
Если КаталогКлассов.Существует() Тогда
Файлы = НайтиФайлы(КаталогКлассов.ПолноеИмя, "*.os");
Для Каждого Файл Из Файлы Цикл
Вывести(СтрШаблон(" класс (по соглашению) %1, файл %2", Файл.ИмяБезРасширения, Файл.ПолноеИмя));
СтандартнаяОбработка = Ложь;
// ДобавитьКласс(Файл.ПолноеИмя, Файл.ИмяБезРасширения);
ДобавитьКлассЕслиРанееНеДобавляли(Файл.ПолноеИмя, Файл.ИмяБезРасширения);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Процедура ОбработатьКаталогМодулей(Знач Путь, СтандартнаяОбработка, Отказ)
КаталогМодулей = Новый Файл(Путь);
Если КаталогМодулей.Существует() Тогда
Файлы = НайтиФайлы(КаталогМодулей.ПолноеИмя, "*.os");
Для Каждого Файл Из Файлы Цикл
Вывести(СтрШаблон(" модуль (по соглашению) %1, файл %2", Файл.ИмяБезРасширения, Файл.ПолноеИмя));
СтандартнаяОбработка = Ложь;
Попытка
ДобавитьМодульЕслиРанееНеДобавляли(Файл.ПолноеИмя, Файл.ИмяБезРасширения);
Исключение
Если ВыдаватьОшибкуПриЗагрузкеУжеСуществующихКлассовМодулей Тогда
ВызватьИсключение;
КонецЕсли;
СтандартнаяОбработка = Истина;
Вывести("Предупреждение:
|" + ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Процедура ДобавитьКлассЕслиРанееНеДобавляли(ПутьФайла, ИмяКласса)
Вывести("Добавляю класс, если ранее не добавляли " + ИмяКласса);
Если ВыдаватьОшибкуПриЗагрузкеУжеСуществующихКлассовМодулей Тогда
Вывести("Добавляю класс " + ИмяКласса);
ДобавитьКласс(ПутьФайла, ИмяКласса);
Возврат;
КонецЕсли;
КлассУжеЕсть = Ложь;
Попытка
Объект = Новый(ИмяКласса);
КлассУжеЕсть = Истина;
Исключение
СообщениеОшибки = ОписаниеОшибки();
ИскомаяОшибка = СтрШаблон("Конструктор не найден (%1)", ИмяКласса);
КлассУжеЕсть = СтрНайти(СообщениеОшибки, ИскомаяОшибка) = 0;
КонецПопытки;
Если Не КлассУжеЕсть Тогда
Вывести("Добавляю класс, т.к. он не найден - " + ИмяКласса);
ДобавитьКласс(ПутьФайла, ИмяКласса);
Иначе
Вывести("Пропускаю загрузку класса " + ИмяКласса);
КонецЕсли;
КонецПроцедуры
Процедура ДобавитьМодульЕслиРанееНеДобавляли(ПутьФайла, ИмяМодуля)
Вывести("Добавляю модуль, если ранее не добавляли " + ИмяМодуля);
МодульУжеЕсть = КэшМодулей.Найти(ИмяМодуля) <> Неопределено;
Если Не МодульУжеЕсть Тогда
Вывести("Добавляю модуль, т.к. он не найден - " + ИмяМодуля);
ДобавитьМодуль(ПутьФайла, ИмяМодуля);
КэшМодулей.Добавить(ИмяМодуля);
Иначе
Вывести("Пропускаю загрузку модуля " + ИмяМодуля);
КонецЕсли;
КонецПроцедуры
Процедура Вывести(Знач Сообщение)
Если ПоказатьСообщенияЗагрузки Тогда
Сообщить(Сообщение);
КонецЕсли;
КонецПроцедуры
Функция ПолучитьБулевоИзПеременнойСреды(Знач ИмяПеременнойСреды, Знач ЗначениеПоУмолчанию)
Рез = ЗначениеПоУмолчанию;
РезИзСреды = ПолучитьПеременнуюСреды(ИмяПеременнойСреды);
Если ЗначениеЗаполнено(РезИзСреды) Тогда
РезИзСреды = СокрЛП(РезИзСреды);
Попытка
Рез = Число(РезИзСреды) <> 0 ;
Исключение
Рез = ЗначениеПоУмолчанию;
Сообщить(СтрШаблон("Неверный формат переменной среды %1. Ожидали 1 или 0, а получили %2", ИмяПеременнойСреды, РезИзСреды));
КонецПопытки;
КонецЕсли;
Возврат Рез;
КонецФункции
// Если Истина, то выдаются подробные сообщения о порядке загрузке пакетов, классов, модулей, что помогает при анализе проблем
// очень полезно при анализе ошибок загрузки
// Переменная среды может принимать значение 0 (выключено) или 1 (включено)
// Значение флага по умолчанию - Ложь
ПоказатьСообщенияЗагрузки = ПолучитьБулевоИзПеременнойСреды(
"OSLIB_LOADER_TRACE", Ложь);
// Если Ложь, то пропускаются ошибки повторной загрузки классов/модулей,
//что важно при разработке/тестировании стандартных библиотек
// Если Истина, то выдается ошибка при повторной загрузке классов библиотек из движка
// Переменная среды может принимать значение 0 (выключено) или 1 (включено)
// Значение флага по умолчанию - Истина
ВыдаватьОшибкуПриЗагрузкеУжеСуществующихКлассовМодулей = ПолучитьБулевоИзПеременнойСреды(
"OSLIB_LOADER_DUPLICATES", Ложь);
// для установки других значений переменных среды и запуска скриптов можно юзать следующую командную строку
// (set OSLIB_LOADER_TRACE=1) && (oscript .\tasks\test.os)
КэшМодулей = Новый Массив;