1 /******************************************************************************* 2 * Copyright (c) 2007, 2019 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.equinox.internal.frameworkadmin.utils; 15 16 import java.io.File; 17 import java.io.IOException; 18 import java.net.URI; 19 import java.util.*; 20 import org.eclipse.equinox.frameworkadmin.BundleInfo; 21 import org.eclipse.equinox.internal.provisional.frameworkadmin.*; 22 import org.osgi.framework.Constants; 23 24 /** 25 * This implementation of BundlesState doesn't support any of - resolving 26 * bundles, - retrieving fw persistent data. 27 * 28 * This implementation can be used for those cases. 29 */ 30 public class SimpleBundlesState implements BundlesState { 31 public static final BundleInfo[] NULL_BUNDLEINFOS = new BundleInfo[0]; 32 33 /** 34 * Check if the specified FrameworkAdmin is available. 35 * 36 * @param fwAdmin 37 * @throws FrameworkAdminRuntimeException 38 */ checkAvailability(FrameworkAdmin fwAdmin)39 public static void checkAvailability(FrameworkAdmin fwAdmin) throws FrameworkAdminRuntimeException { 40 if (!fwAdmin.isActive()) 41 throw new FrameworkAdminRuntimeException("FrameworkAdmin creates this object is no more available.", //$NON-NLS-1$ 42 FrameworkAdminRuntimeException.FRAMEWORKADMIN_UNAVAILABLE); 43 } 44 45 /** 46 * 47 * @param launcherData 48 * @return File of fwJar to be used. 49 * @throws IOException 50 */ getFwJar(LauncherData launcherData)51 static File getFwJar(LauncherData launcherData) { 52 if (launcherData.getFwJar() != null) 53 return launcherData.getFwJar(); 54 return null; 55 } 56 57 private final String systemBundleSymbolicName; 58 59 private final String systemBundleName; 60 61 private final String systemBundleVendor; 62 List<BundleInfo> bundleInfosList = new LinkedList<>(); 63 64 FrameworkAdmin fwAdmin = null; 65 66 Manipulator manipulator = null; 67 68 /** 69 * If the manifest of the target fw implementation has 70 * Constants.BUNDLE_SYMBOLICNAME header, this constructor should be used. 71 * 72 * @param ManipulatorAdmin 73 * @param Manipulator 74 * @param systemBundleSymbolicName 75 */ SimpleBundlesState(FrameworkAdmin ManipulatorAdmin, Manipulator Manipulator, String systemBundleSymbolicName)76 public SimpleBundlesState(FrameworkAdmin ManipulatorAdmin, Manipulator Manipulator, 77 String systemBundleSymbolicName) { 78 super(); 79 this.fwAdmin = ManipulatorAdmin; 80 // copy Manipulator object for avoiding modifying the parameters of the 81 // Manipulator. 82 this.manipulator = ManipulatorAdmin.getManipulator(); 83 this.manipulator.setConfigData(Manipulator.getConfigData()); 84 this.manipulator.setLauncherData(Manipulator.getLauncherData()); 85 this.systemBundleSymbolicName = systemBundleSymbolicName; 86 this.systemBundleName = null; 87 this.systemBundleVendor = null; 88 initialize(); 89 } 90 91 /** 92 * If the manifest of the target fw implementation has not 93 * Constants.BUNDLE_SYMBOLICNAME header but , Constants.BUNDLE_NAME and 94 * BUNDLE_VERSION, this constructor should be used. 95 * 96 * @param ManipulatorAdmin 97 * @param Manipulator 98 * @param systemBundleName 99 * @param systemBundleVender 100 */ SimpleBundlesState(FrameworkAdmin ManipulatorAdmin, Manipulator Manipulator, String systemBundleName, String systemBundleVender)101 public SimpleBundlesState(FrameworkAdmin ManipulatorAdmin, Manipulator Manipulator, String systemBundleName, 102 String systemBundleVender) { 103 super(); 104 this.fwAdmin = ManipulatorAdmin; 105 // copy Manipulator object for avoiding modifying the parameters of the 106 // Manipulator. 107 this.manipulator = ManipulatorAdmin.getManipulator(); 108 this.manipulator.setConfigData(Manipulator.getConfigData()); 109 this.manipulator.setLauncherData(Manipulator.getLauncherData()); 110 this.systemBundleSymbolicName = null; 111 this.systemBundleName = systemBundleName; 112 this.systemBundleVendor = systemBundleVender; 113 initialize(); 114 } 115 116 @Override getExpectedState()117 public BundleInfo[] getExpectedState() throws FrameworkAdminRuntimeException { 118 if (!fwAdmin.isActive()) 119 throw new FrameworkAdminRuntimeException("FrameworkAdmin creates this object is no more available.", //$NON-NLS-1$ 120 FrameworkAdminRuntimeException.FRAMEWORKADMIN_UNAVAILABLE); 121 return Utils.getBundleInfosFromList(this.bundleInfosList); 122 } 123 124 /* 125 * Just return required bundles. 126 * 127 * @see org.eclipse.equinox.internal.provisional.frameworkadmin.BundlesState# 128 * getPrerequisteBundles(org.eclipse.equinox.internal.provisional.frameworkadmin 129 * .BundleInfo) 130 */ 131 @Override getPrerequisteBundles(BundleInfo bInfo)132 public BundleInfo[] getPrerequisteBundles(BundleInfo bInfo) { 133 URI location = bInfo.getLocation(); 134 final String requiredBundles = Utils.getManifestMainAttributes(location, Constants.REQUIRE_BUNDLE); 135 if (requiredBundles == null) 136 return new BundleInfo[] { this.getSystemBundle() }; 137 138 String[] clauses = Utils.getClauses(requiredBundles); 139 List<String> list = new LinkedList<>(); 140 for (String clause : clauses) 141 list.add(Utils.getPathFromClause(clause)); 142 143 List<BundleInfo> ret = new LinkedList<>(); 144 ret.add(this.getSystemBundle()); 145 for (BundleInfo currentBInfo : this.bundleInfosList) { 146 URI currentLocation = currentBInfo.getLocation(); 147 String currentSymbolicName = Utils.getManifestMainAttributes(currentLocation, 148 Constants.BUNDLE_SYMBOLICNAME); 149 if (currentSymbolicName == null) 150 continue; 151 currentSymbolicName = Utils.getPathFromClause(currentSymbolicName); 152 for (String symbolicName : list) { 153 if (symbolicName.equals(currentSymbolicName)) { 154 ret.add(currentBInfo); 155 break; 156 } 157 } 158 } 159 return Utils.getBundleInfosFromList(ret); 160 } 161 162 @Override getSystemBundle()163 public BundleInfo getSystemBundle() { 164 if (this.systemBundleSymbolicName == null) { 165 for (BundleInfo bInfo : this.bundleInfosList) { 166 // if (bInfo.getStartLevel() != 1) 167 // return null;; 168 URI location = bInfo.getLocation(); 169 String bundleName = Utils.getManifestMainAttributes(location, Constants.BUNDLE_NAME); 170 if (systemBundleName.equals(bundleName)) { 171 String bundleVendor = Utils.getManifestMainAttributes(location, Constants.BUNDLE_VENDOR); 172 if (systemBundleVendor.equals(bundleVendor)) 173 return bInfo; 174 } 175 } 176 return null; 177 } 178 for (BundleInfo bInfo : this.bundleInfosList) { 179 URI location = bInfo.getLocation(); 180 String symbolicName = Utils.getManifestMainAttributes(location, Constants.BUNDLE_SYMBOLICNAME); 181 symbolicName = Utils.getPathFromClause(symbolicName); 182 if (this.systemBundleSymbolicName.equals(symbolicName)) 183 return bInfo; 184 } 185 return null; 186 } 187 188 @Override 189 @SuppressWarnings("unchecked") getSystemFragmentedBundles()190 public BundleInfo[] getSystemFragmentedBundles() { 191 BundleInfo systemBInfo = this.getSystemBundle(); 192 if (systemBInfo == null) 193 return NULL_BUNDLEINFOS; 194 195 @SuppressWarnings("rawtypes") 196 List list = new LinkedList(); 197 for (BundleInfo bInfo : this.bundleInfosList) { 198 URI location = bInfo.getLocation(); 199 String manifestVersion = Utils.getManifestMainAttributes(location, Constants.BUNDLE_MANIFESTVERSION); 200 if (manifestVersion == null) 201 continue; 202 if (manifestVersion.equals("1") || manifestVersion.equals("1.0")) //$NON-NLS-1$//$NON-NLS-2$ 203 continue; 204 205 String fragmentHost = Utils.getManifestMainAttributes(location, Constants.FRAGMENT_HOST); 206 if (fragmentHost == null) 207 continue; 208 int index = fragmentHost.indexOf(";"); //$NON-NLS-1$ 209 if (index == -1) 210 continue; 211 String symbolicName = fragmentHost.substring(0, index).trim(); 212 String parameter = fragmentHost.substring(index + 1).trim(); 213 // TODO What to do ,in case of alias name of system bundle is not used ? 214 if (symbolicName.equals(Constants.SYSTEM_BUNDLE_SYMBOLICNAME)) 215 if (parameter.equals(Constants.EXTENSION_DIRECTIVE + ":=" + Constants.EXTENSION_FRAMEWORK)) { //$NON-NLS-1$ 216 list.add(location); 217 break; 218 } 219 } 220 return Utils.getBundleInfosFromList(list); 221 } 222 223 @Override getUnsatisfiedConstraints(BundleInfo bInfo)224 public String[] getUnsatisfiedConstraints(BundleInfo bInfo) throws FrameworkAdminRuntimeException { 225 throw new FrameworkAdminRuntimeException( 226 "getUnsatisfiedConstraints(BundleInfo bInfo) is not supported in this implementation", //$NON-NLS-1$ 227 FrameworkAdminRuntimeException.UNSUPPORTED_OPERATION); 228 } 229 initialize()230 private void initialize() { 231 this.bundleInfosList.clear(); 232 LauncherData launcherData = manipulator.getLauncherData(); 233 ConfigData configData = manipulator.getConfigData(); 234 File fwJar = getFwJar(launcherData); 235 236 if (fwJar == null) 237 throw new IllegalStateException("launcherData.getLauncherConfigFile() == null && fwJar is not set."); //$NON-NLS-1$ 238 // No fw persistent data location is taken into consideration. 239 240 BundleInfo[] bInfos = configData.getBundles(); 241 for (BundleInfo bInfo : bInfos) 242 this.installBundle(bInfo); 243 244 if (getSystemBundle() == null) { 245 BundleInfo sysBInfo = new BundleInfo(launcherData.getFwJar().toURI(), 0, true); 246 sysBInfo.setBundleId(0); 247 this.installBundle(sysBInfo); 248 } 249 } 250 251 @Override installBundle(BundleInfo bInfo)252 public void installBundle(BundleInfo bInfo) throws FrameworkAdminRuntimeException { 253 254 URI newLocation = bInfo.getLocation(); 255 Dictionary<String, String> newManifest = Utils.getOSGiManifest(newLocation); 256 if (newManifest == null) { 257 // TODO log something here 258 return; 259 } 260 String newSymbolicName = newManifest.get(Constants.BUNDLE_SYMBOLICNAME); 261 String newVersion = newManifest.get(Constants.BUNDLE_VERSION); 262 // System.out.println("> currentInstalledBundles.length=" + 263 // currentInstalledBundles.length); 264 boolean found = false; 265 for (BundleInfo currentBInfo : this.bundleInfosList) { 266 URI location = currentBInfo.getLocation(); 267 if (newLocation.equals(location)) { 268 found = true; 269 break; 270 } 271 Dictionary<String, String> manifest = Utils.getOSGiManifest(location); 272 String symbolicName = manifest.get(Constants.BUNDLE_SYMBOLICNAME); 273 String version = manifest.get(Constants.BUNDLE_VERSION); 274 if (newSymbolicName != null && newVersion != null) 275 if (newSymbolicName.equals(symbolicName) && newVersion.equals(version)) { 276 found = true; 277 break; 278 } 279 } 280 if (!found) { 281 this.bundleInfosList.add(bInfo); 282 } 283 } 284 285 // public String toString() { 286 // if (state == null) 287 // return null; 288 // StringBuffer sb = new StringBuffer(); 289 // BundleDescription[] bundleDescriptions = state.getBundles(); 290 // for (int i = 0; i < bundleDescriptions.length; i++) { 291 // sb.append(bundleDescriptions[i].getBundleId() + ":"); 292 // sb.append(bundleDescriptions[i].toString() + "("); 293 // sb.append(bundleDescriptions[i].isResolved() + ")"); 294 // String[] ees = bundleDescriptions[i].getExecutionEnvironments(); 295 // for (int j = 0; j < ees.length; j++) 296 // sb.append(ees[j] + " "); 297 // sb.append("\n"); 298 // } 299 // sb.append("PlatformProperties:\n"); 300 // Dictionary[] dics = state.getPlatformProperties(); 301 // for (int i = 0; i < dics.length; i++) { 302 // for (Enumeration enum = dics[i].keys(); enum.hasMoreElements();) { 303 // String key = (String) enum.nextElement(); 304 // String value = (String) dics[i].get(key); 305 // sb.append(" (" + key + "," + value + ")\n"); 306 // } 307 // } 308 // sb.append("\n"); 309 // return sb.toString(); 310 // } 311 312 @Override isFullySupported()313 public boolean isFullySupported() { 314 return false; 315 } 316 317 @Override isResolved()318 public boolean isResolved() throws FrameworkAdminRuntimeException { 319 throw new FrameworkAdminRuntimeException("isResolved() is not supported in this implementation", //$NON-NLS-1$ 320 FrameworkAdminRuntimeException.UNSUPPORTED_OPERATION); 321 } 322 323 @Override isResolved(BundleInfo bInfo)324 public boolean isResolved(BundleInfo bInfo) throws FrameworkAdminRuntimeException { 325 throw new FrameworkAdminRuntimeException("isResolved(BundleInfo bInfo) is not supported in this implementation", //$NON-NLS-1$ 326 FrameworkAdminRuntimeException.UNSUPPORTED_OPERATION); 327 } 328 329 @Override resolve(boolean increment)330 public void resolve(boolean increment) throws FrameworkAdminRuntimeException { 331 throw new FrameworkAdminRuntimeException("resolve(boolean increment) is not supported in this implementation", //$NON-NLS-1$ 332 FrameworkAdminRuntimeException.UNSUPPORTED_OPERATION); 333 } 334 335 @Override uninstallBundle(BundleInfo bInfo)336 public void uninstallBundle(BundleInfo bInfo) throws FrameworkAdminRuntimeException { 337 URI targetLocation = bInfo.getLocation(); 338 int index = -1; 339 for (BundleInfo currentBInfo : this.bundleInfosList) { 340 index++; 341 URI location = currentBInfo.getLocation(); 342 if (targetLocation.equals(location)) { 343 break; 344 } 345 } 346 if (index != -1) 347 this.bundleInfosList.remove(index); 348 } 349 350 } 351