/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.frontend.js.loader.modules.extender.internal; import aQute.bnd.osgi.Constants; import com.liferay.portal.kernel.util.ArrayUtil; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.util.Validator; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.net.URL; import java.util.Dictionary; import java.util.List; import java.util.Map; import org.json.JSONArray; import org.json.JSONObject; import org.json.JSONTokener; import org.osgi.framework.Bundle; import org.osgi.framework.Version; import org.osgi.framework.wiring.BundleCapability; import org.osgi.framework.wiring.BundleWire; import org.osgi.framework.wiring.BundleWiring; /** * @author Carlos Sierra Andrés */ public class JSLoaderModule { public JSLoaderModule( boolean applyVersioning, Bundle bundle, String contextPath) { _applyVersioning = applyVersioning; _bundle = bundle; _contextPath = contextPath; Version version = _bundle.getVersion(); _version = version.toString(); BundleWiring bundleWiring = _bundle.adapt(BundleWiring.class); List<BundleCapability> bundleCapabilities = bundleWiring.getCapabilities(Details.OSGI_WEBRESOURCE); if (bundleCapabilities.isEmpty()) { _name = _bundle.getSymbolicName(); return; } BundleCapability bundleCapability = bundleCapabilities.get(0); Map<String, Object> attributes = bundleCapability.getAttributes(); _name = (String)attributes.get(Details.OSGI_WEBRESOURCE); URL url = _bundle.getEntry(Details.CONFIG_JSON); urlToConfiguration(url, bundleWiring); } public String getContextPath() { return _contextPath; } public String getName() { return _name; } public String getUnversionedConfiguration() { return _unversionedConfiguration; } public String getUnversionedMapsConfiguration() { return _unversionedMapsConfiguration; } public String getVersion() { return _version; } public String getVersionedConfiguration() { return _versionedConfiguration; } protected String generateConfiguration( JSONObject jsonObject, BundleWiring bundleWiring, boolean versionedModuleName) { if (!_applyVersioning) { if (versionedModuleName) { return ""; } return jsonObject.toString(); } List<BundleWire> bundleWires = bundleWiring.getRequiredWires( Details.OSGI_WEBRESOURCE); JSONArray namesJSONArray = jsonObject.names(); if (namesJSONArray == null) { return jsonObject.toString(); } for (int i = 0; i < namesJSONArray.length(); i++) { String name = (String)namesJSONArray.get(i); int x = name.indexOf('/'); if (x == -1) { continue; } String moduleName = name.substring(0, x); if (!moduleName.equals(getName())) { continue; } String modulePath = name.substring(x); moduleName = getName() + "@" + getVersion() + modulePath; JSONObject nameJSONObject = jsonObject.getJSONObject(name); JSONArray dependenciesJSONArray = nameJSONObject.getJSONArray( "dependencies"); for (int j = 0; j < dependenciesJSONArray.length(); j++) { String dependency = dependenciesJSONArray.getString(j); int y = dependency.indexOf('/'); if (y == -1) { continue; } String dependencyName = dependency.substring(0, y); String dependencyPath = dependency.substring(y); if (dependencyName.equals(getName())) { dependencyName = getName() + "@" + getVersion() + dependencyPath; dependenciesJSONArray.put(j, dependencyName); } else { normalizeDependencies( dependencyName, dependencyPath, dependenciesJSONArray, j, bundleWires); } } if (versionedModuleName) { jsonObject.remove(name); jsonObject.put(moduleName, nameJSONObject); } else { jsonObject.put(name, nameJSONObject); } } return jsonObject.toString(); } protected String generateMapsConfiguration( String configuration, String[] exportJSSubmodules) { boolean exportAll = ArrayUtil.contains( exportJSSubmodules, StringPool.STAR); JSONObject mapsConfigurationJSONObject = new JSONObject(); JSONObject configurationJSONObject = new JSONObject( "{" + configuration + "}"); JSONArray namesJSONArray = configurationJSONObject.names(); for (int i = 0; i < namesJSONArray.length(); i++) { String name = (String)namesJSONArray.get(i); int x = name.indexOf('/'); String moduleRootPath = name.substring(0, x + 1); String submodulePath = name.substring(x + 1); int y = submodulePath.indexOf('/'); if (y == -1) { continue; } String submoduleName = submodulePath.substring(0, y); if (exportAll || ArrayUtil.contains(exportJSSubmodules, submoduleName)) { mapsConfigurationJSONObject.put( submoduleName, moduleRootPath.concat(submoduleName)); } } return mapsConfigurationJSONObject.toString(); } protected String normalize(String jsonString) { if (jsonString.startsWith("{") && jsonString.endsWith("}")) { jsonString = jsonString.substring(1, jsonString.length() - 1); } return jsonString; } protected void normalizeDependencies( String dependencyName, String dependencyPath, JSONArray jsonArray, int index, List<BundleWire> bundleWires) { for (BundleWire bundleWire : bundleWires) { BundleCapability bundleCapability = bundleWire.getCapability(); Map<String, Object> attributes = bundleCapability.getAttributes(); String attributesDependencyName = (String)attributes.get( Details.OSGI_WEBRESOURCE); if (!attributesDependencyName.equals(dependencyName)) { continue; } Version version = (Version)attributes.get( Constants.VERSION_ATTRIBUTE); dependencyName = dependencyName + "@" + version.toString() + dependencyPath; jsonArray.put(index, dependencyName); return; } } protected void urlToConfiguration(URL url, BundleWiring bundleWiring) { if (url == null) { return; } try (Reader reader = new InputStreamReader(url.openStream())) { JSONTokener jsonTokener = new JSONTokener(reader); JSONObject jsonObject = new JSONObject(jsonTokener); _unversionedConfiguration = normalize( generateConfiguration(jsonObject, bundleWiring, false)); _versionedConfiguration = normalize( generateConfiguration(jsonObject, bundleWiring, true)); Dictionary<String, String> headers = _bundle.getHeaders(); String exportJSSubmodules = GetterUtil.getString( headers.get("Liferay-Export-JS-Submodules")); if (Validator.isNotNull(exportJSSubmodules)) { _unversionedMapsConfiguration = normalize( generateMapsConfiguration( _unversionedConfiguration, StringUtil.split(exportJSSubmodules))); } } catch (IOException ioe) { throw new RuntimeException(ioe); } } private final boolean _applyVersioning; private final Bundle _bundle; private final String _contextPath; private final String _name; private String _unversionedConfiguration = ""; private String _unversionedMapsConfiguration = ""; private final String _version; private String _versionedConfiguration = ""; }