1 /******************************************************************************* 2 * Copyright (c) 2008, 2017 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.pde.internal.build.site; 15 16 import java.io.*; 17 import java.net.*; 18 import java.util.*; 19 import org.eclipse.equinox.frameworkadmin.BundleInfo; 20 import org.eclipse.equinox.internal.p2.publisher.eclipse.ProductFile; 21 import org.eclipse.equinox.simpleconfigurator.manipulator.SimpleConfiguratorManipulator; 22 import org.eclipse.osgi.service.resolver.BundleDescription; 23 import org.eclipse.pde.internal.build.*; 24 25 /** 26 * Temporary utilities until P2 and FrameworkAdmin are graduated into the SDK. 27 * 28 * @since 3.4 29 */ 30 public class P2Utils { 31 32 /** 33 * Returns bundles defined by the 'bundles.info' file in the 34 * specified location, or <code>null</code> if none. The "bundles.info" file 35 * is assumed to be at a fixed relative location to the specified file. This 36 * method will also look for a "source.info". If available, any source 37 * bundles found will also be added to the returned list. 38 * 39 * @param platformHome absolute path in the local file system to an installation 40 * @return URLs of all bundles in the installation or <code>null</code> if not able 41 * to locate a bundles.info 42 */ readBundlesTxt(String platformHome)43 public static URL[] readBundlesTxt(String platformHome) { 44 SimpleConfiguratorManipulator manipulator = BundleHelper.getDefault().acquireService(SimpleConfiguratorManipulator.class); 45 46 File root = new File(platformHome); 47 File bundlesTxt = new File(root, "configuration/" + SimpleConfiguratorManipulator.BUNDLES_INFO_PATH); //$NON-NLS-1$ 48 File sourceTxt = new File(root, "configuration/" + SimpleConfiguratorManipulator.SOURCE_INFO_PATH); //$NON-NLS-1$ 49 50 List<BundleInfo> infos = new ArrayList<>(); 51 try { 52 //streams are closed for us 53 if (bundlesTxt.exists()) 54 infos.addAll(Arrays.asList(manipulator.loadConfiguration(new FileInputStream(bundlesTxt), root.toURI()))); 55 if (sourceTxt.exists()) 56 infos.addAll(Arrays.asList(manipulator.loadConfiguration(new FileInputStream(sourceTxt), root.toURI()))); 57 } catch (MalformedURLException e) { 58 // TODO Auto-generated catch block 59 e.printStackTrace(); 60 } catch (IOException e) { 61 // TODO Auto-generated catch block 62 e.printStackTrace(); 63 } 64 65 URL[] bundles = null; 66 if (infos.size() > 0) { 67 bundles = new URL[infos.size()]; 68 for (int i = 0; i < bundles.length; i++) { 69 try { 70 bundles[i] = new File(infos.get(i).getLocation()).toURL(); 71 } catch (MalformedURLException e) { 72 // TODO Auto-generated catch block 73 e.printStackTrace(); 74 } 75 } 76 } else { 77 bundles = new URL[0]; 78 } 79 return bundles; 80 } 81 82 /** 83 * Creates a bundles.info file in the given directory containing the name, 84 * version, location, start level and expected state of every bundle in the 85 * given collection. Will also create a source.info file containing 86 * a lsit of all source bundles found in the given collection. Uses special 87 * defaults for the start level and auto start settings. Returns the URL 88 * location of the bundle.txt or <code>null</code> if there was a problem 89 * creating it. 90 * 91 * @param bundles collection of IPluginModelBase objects to write into the bundles.info/source.info 92 * @param directory directory to create the bundles.info and source.info files in 93 * @return URL location of the bundles.info or <code>null</code> 94 */ writeBundlesTxt(Collection<BundleDescription> bundles, File directory, ProductFile productFile, boolean refactoredRuntime)95 public static File writeBundlesTxt(Collection<BundleDescription> bundles, File directory, ProductFile productFile, boolean refactoredRuntime) { 96 List<BundleInfo> bundleInfos = new ArrayList<>(bundles.size()); 97 List<BundleInfo> sourceInfos = new ArrayList<>(bundles.size()); 98 ShapeAdvisor advisor = new ShapeAdvisor(); 99 100 int defaultStartLevel = 4; 101 Properties props = productFile != null ? productFile.getConfigProperties() : null; 102 if (props != null && props.containsKey("osgi.bundles.defaultStartLevel")) { //$NON-NLS-1$ 103 try { 104 defaultStartLevel = Integer.parseInt(props.getProperty("osgi.bundles.defaultStartLevel")); //$NON-NLS-1$ 105 } catch (NumberFormatException e) { 106 //ignore and keep 4 107 } 108 } 109 110 Map<String, BundleInfo> userInfos = productFile != null ? productFile.getConfigurationInfo() : null; 111 112 for (Iterator<BundleDescription> iterator = bundles.iterator(); iterator.hasNext();) { 113 BundleDescription desc = iterator.next(); 114 if (desc != null) { 115 String modelName = desc.getSymbolicName(); 116 117 URI location = null; 118 try { 119 location = new URI("plugins/" + (String) advisor.getFinalShape(desc)[0]); //$NON-NLS-1$ 120 } catch (URISyntaxException e) { 121 continue; 122 } 123 BundleInfo info = new BundleInfo(); 124 info.setLocation(location); 125 info.setSymbolicName(modelName); 126 info.setVersion(desc.getVersion().toString()); 127 if (userInfos != null && userInfos.size() > 0) { 128 if (userInfos.containsKey(modelName)) { 129 BundleInfo userInfo = userInfos.get(modelName); 130 int start = userInfo.getStartLevel(); 131 if (start <= 0) 132 start = defaultStartLevel; 133 info.setStartLevel(start); 134 info.setMarkedAsStarted(userInfo.isMarkedAsStarted()); 135 } else { 136 info.setStartLevel(defaultStartLevel); 137 info.setMarkedAsStarted(false); 138 } 139 } else { 140 if (IPDEBuildConstants.BUNDLE_SIMPLE_CONFIGURATOR.equals(modelName)) { 141 info.setStartLevel(1); 142 info.setMarkedAsStarted(true); 143 } else if (IPDEBuildConstants.BUNDLE_EQUINOX_COMMON.equals(modelName)) { 144 info.setStartLevel(2); 145 info.setMarkedAsStarted(true); 146 } else if (IPDEBuildConstants.BUNDLE_OSGI.equals(modelName)) { 147 info.setStartLevel(-1); 148 info.setMarkedAsStarted(true); 149 } else if (IPDEBuildConstants.BUNDLE_CORE_RUNTIME.equals(modelName)) { 150 info.setStartLevel(refactoredRuntime ? 4 : 2); 151 info.setMarkedAsStarted(true); 152 } else if (IPDEBuildConstants.BUNDLE_DS.equals(modelName)) { 153 info.setStartLevel(2); 154 info.setMarkedAsStarted(true); 155 } else { 156 info.setStartLevel(defaultStartLevel); 157 info.setMarkedAsStarted(false); 158 } 159 } 160 if (Utils.isSourceBundle(desc)) 161 sourceInfos.add(info); 162 else 163 bundleInfos.add(info); 164 } 165 } 166 167 File bundlesTxt = new File(directory, SimpleConfiguratorManipulator.BUNDLES_INFO_PATH); 168 File srcBundlesTxt = new File(directory, SimpleConfiguratorManipulator.SOURCE_INFO_PATH); 169 File base = directory.getParentFile(); 170 171 BundleInfo[] infos = bundleInfos.toArray(new BundleInfo[bundleInfos.size()]); 172 BundleInfo[] sources = sourceInfos.toArray(new BundleInfo[sourceInfos.size()]); 173 174 SimpleConfiguratorManipulator manipulator = BundleHelper.getDefault().acquireService(SimpleConfiguratorManipulator.class); 175 try { 176 manipulator.saveConfiguration(infos, bundlesTxt, base.toURI()); 177 manipulator.saveConfiguration(sources, srcBundlesTxt, base.toURI()); 178 } catch (IOException e) { 179 return null; 180 } 181 182 return bundlesTxt; 183 } 184 } 185