| /******************************************************************************* |
| * Copyright (c) 2008, 2019 IBM Corporation and others. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License 2.0 which accompanies this distribution, |
| * and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: IBM - Initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.pde.internal.build.site; |
| |
| import java.io.*; |
| import java.net.URL; |
| import java.util.*; |
| import java.util.zip.ZipEntry; |
| import java.util.zip.ZipFile; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.osgi.util.ManifestElement; |
| import org.eclipse.pde.internal.build.IPDEBuildConstants; |
| import org.eclipse.pde.internal.build.Utils; |
| import org.osgi.framework.Bundle; |
| |
| public class ProfileManager { |
| public static final String PROFILE_EXTENSION = ".profile"; //$NON-NLS-1$ |
| public static final String SYSTEM_PACKAGES = "org.osgi.framework.system.packages"; //$NON-NLS-1$ |
| public static final String PROFILE_NAME = "osgi.java.profile.name"; //$NON-NLS-1$ |
| public static final String PROFILE_LIST = "profile.list"; //$NON-NLS-1$ |
| public static final String JAVA_PROFILES = "java.profiles"; //$NON-NLS-1$ |
| public static final String PROFILE_JAVAC_SOURCE = "org.eclipse.jdt.core.compiler.source"; //$NON-NLS-1$ |
| public static final String PROFILE_JAVAC_TARGET = "org.eclipse.jdt.core.compiler.codegen.targetPlatform"; //$NON-NLS-1$ |
| |
| private final HashMap<String, Properties> profileMap = new HashMap<>(); |
| private String[] profileSources = null; |
| |
| public ProfileManager() { |
| loadProfiles(true); |
| } |
| |
| public ProfileManager(String[] profileSources) { |
| this.profileSources = profileSources; |
| loadProfiles(false); |
| } |
| |
| public ProfileManager(String[] profileSources, boolean includeRuntime) { |
| this.profileSources = profileSources; |
| loadProfiles(includeRuntime); |
| } |
| |
| public Properties getProfileProperties(String profileName) { |
| return profileMap.get(profileName); |
| } |
| |
| public void copyEEProfileProperties(Dictionary<String, Object> source, Properties target) { |
| String[] profiles = getJavaProfiles(); |
| for (int i = 0; i < profiles.length; i++) { |
| Object value = source.get(profiles[i]); |
| if (value != null && value instanceof String) { |
| target.put(profiles[i], value); |
| } |
| } |
| } |
| |
| /** |
| * Return the javacSource to use when compiling for the given execution environment |
| * @param environment |
| * @return javacSource or null |
| */ |
| public String getJavacSource(String environment) { |
| if (profileMap.containsKey(environment)) { |
| Properties properties = profileMap.get(environment); |
| return properties.getProperty(PROFILE_JAVAC_SOURCE); |
| } |
| if (environment.startsWith("JavaSE-")) { //$NON-NLS-1$ |
| return environment.replace("JavaSE-", ""); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| return null; |
| } |
| |
| /** |
| * Return the javacTarget to use when compiling for the given execution environment |
| * @param environment |
| * @return javacTarget or null |
| */ |
| public String getJavacTarget(String environment) { |
| if (profileMap.containsKey(environment)) { |
| Properties properties = profileMap.get(environment); |
| return properties.getProperty(PROFILE_JAVAC_TARGET); |
| } |
| return null; |
| } |
| |
| public String[] getJavaProfiles() { |
| Set<String> keys = profileMap.keySet(); |
| return sortProfiles(keys.toArray(new String[keys.size()])); |
| } |
| |
| protected String[] sortProfiles(String[] profiles) { |
| Arrays.sort(profiles, new Comparator<String>() { |
| @Override |
| public int compare(String profile1, String profile2) { |
| // need to make sure JavaSE, J2SE profiles are sorted ahead of all other profiles |
| String p1 = profile1; |
| String p2 = profile2; |
| if (p1.startsWith("JavaSE-") && !p2.startsWith("JavaSE-")) //$NON-NLS-1$ //$NON-NLS-2$ |
| return -1; |
| if (!p1.startsWith("JavaSE-") && p2.startsWith("JavaSE-")) //$NON-NLS-1$ //$NON-NLS-2$ |
| return 1; |
| if (p1.startsWith("J2SE-") && !p2.startsWith("J2SE-")) //$NON-NLS-1$ //$NON-NLS-2$ |
| return -1; |
| if (!p1.startsWith("J2SE-") && p2.startsWith("J2SE-")) //$NON-NLS-1$ //$NON-NLS-2$ |
| return 1; |
| if (p1.startsWith("JavaSE/compact") && !p2.startsWith("JavaSE/compact")) //$NON-NLS-1$ //$NON-NLS-2$ |
| return -1; |
| if (!p1.startsWith("JavaSE/compact") && p2.startsWith("JavaSE/compact")) //$NON-NLS-1$ //$NON-NLS-2$ |
| return 1; |
| return -p1.compareTo(p2); |
| } |
| }); |
| return profiles; |
| } |
| |
| protected void loadProfiles(boolean includeRuntime) { |
| if (includeRuntime || profileSources == null) { |
| loadRuntimeJavaProfiles(); |
| } |
| if (profileSources != null) { |
| for (int i = 0; i < profileSources.length; i++) { |
| File source = new File(profileSources[i]); |
| if (source.isDirectory()) { |
| loadJavaProfiles(source); |
| } else { |
| loadJarJavaProfiles(source); |
| } |
| } |
| } |
| } |
| |
| protected void loadJarJavaProfiles(File bundleLocation) { |
| ZipFile zipFile = null; |
| try { |
| zipFile = new ZipFile(bundleLocation, ZipFile.OPEN_READ); |
| loadJavaProfiles(zipFile); |
| } catch (IOException e) { |
| // boo |
| } finally { |
| Utils.close(zipFile); |
| } |
| } |
| |
| protected void loadRuntimeJavaProfiles() { |
| Bundle systemBundle = Platform.getBundle(IPDEBuildConstants.BUNDLE_OSGI); |
| if (systemBundle != null) |
| loadJavaProfiles(systemBundle); |
| } |
| |
| /* |
| * Return an input stream on the profile.list entry in the given container. |
| */ |
| private InputStream getProfileListInputStream(Object container) { |
| if (container instanceof File) { |
| // try the profile list first |
| File listFile = new File((File) container, PROFILE_LIST); |
| if (listFile.exists()) |
| try { |
| return new BufferedInputStream(new FileInputStream(listFile)); |
| } catch (FileNotFoundException e) { |
| return null; |
| } |
| } else if (container instanceof ZipFile) { |
| ZipFile zipFile = (ZipFile) container; |
| ZipEntry listEntry = ((ZipFile) container).getEntry(PROFILE_LIST); |
| if (listEntry != null) |
| try { |
| return new BufferedInputStream(zipFile.getInputStream(listEntry)); |
| } catch (IOException e) { |
| return null; |
| } |
| } else if (container instanceof Bundle) { |
| Bundle systemBundle = (Bundle) container; |
| URL url = systemBundle.getEntry(PROFILE_LIST); |
| if (url != null) { |
| try { |
| return new BufferedInputStream(url.openStream()); |
| } catch (IOException e) { |
| return null; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /* |
| * Return an Enumeration containing all the profile entries in the container |
| * If profiles is null then: |
| * A ZipFile container returns all ZipEntries from the jar |
| * All other containers return the *.profile entries from the root |
| */ |
| @SuppressWarnings("rawtypes") |
| private Enumeration getProfilesEnum(Object container, String[] profiles) { |
| if (profiles != null) { |
| return Utils.getArrayEnumerator(profiles); |
| } else if (container instanceof File) { |
| File[] files = ((File) container).listFiles(new FilenameFilter() { |
| @Override |
| public boolean accept(File dir, String name) { |
| return name.endsWith(PROFILE_EXTENSION); |
| } |
| }); |
| return Utils.getArrayEnumerator(files); |
| } else if (container instanceof ZipFile) { |
| return ((ZipFile) container).entries(); |
| } else if (container instanceof Bundle) { |
| return ((Bundle) container).findEntries("/", "*" + PROFILE_EXTENSION, false); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| return null; |
| } |
| |
| private InputStream getEntryInputStream(Object container, Object entry) { |
| try { |
| if (entry instanceof String) { |
| if (container instanceof File) |
| entry = new File((File) container, (String) entry); |
| else if (container instanceof ZipFile) |
| entry = ((ZipFile) container).getEntry((String) entry); |
| else if (container instanceof Bundle) |
| entry = ((Bundle) container).getEntry((String) entry); |
| } |
| |
| if (entry instanceof File) |
| return new BufferedInputStream(new FileInputStream((File) entry)); |
| else if (entry instanceof ZipEntry) |
| return new BufferedInputStream(((ZipFile) container).getInputStream((ZipEntry) entry)); |
| else if (entry instanceof URL) |
| return new BufferedInputStream(((URL) entry).openStream()); |
| } catch (IOException e) { |
| // boo |
| } |
| return null; |
| } |
| |
| /* |
| * ZipFile conainers aren't able to filter the entry enumeration, must filter here. |
| */ |
| private boolean isProfileEntry(Object entry) { |
| if (entry instanceof String || entry instanceof URL || entry instanceof File) |
| return true; |
| else if (entry instanceof ZipEntry) { |
| String entryName = ((ZipEntry) entry).getName(); |
| return entryName.indexOf('/') < 0 && entryName.endsWith(PROFILE_EXTENSION); |
| } |
| return false; |
| } |
| |
| /** |
| * Load the Java Profiles from the given container. A container is one of: |
| * File - a directory shaped bundle on disk |
| * ZipFile - a jar shaped bundle on disk |
| * Bundle - a Bundle object from the current runtime. |
| * @param container : The container to load java profiles from. |
| */ |
| private void loadJavaProfiles(Object container) { |
| InputStream is = getProfileListInputStream(container); |
| String[] profiles = getJavaProfiles(is); |
| Utils.close(is); |
| |
| Enumeration<?> entries = getProfilesEnum(container, profiles); |
| while (entries != null && entries.hasMoreElements()) { |
| Object item = entries.nextElement(); |
| if (!isProfileEntry(item)) |
| continue; |
| |
| is = getEntryInputStream(container, item); |
| if (is != null) { |
| Properties props = new Properties(); |
| try { |
| props.load(is); |
| if (props.containsKey(PROFILE_NAME)) |
| profileMap.put((String) props.get(PROFILE_NAME), props); |
| } catch (IOException e) { |
| //boo |
| } finally { |
| Utils.close(is); |
| } |
| } |
| } |
| } |
| |
| private String[] getJavaProfiles(InputStream is) { |
| if (is == null) |
| return null; |
| Properties props = new Properties(); |
| try { |
| props.load(is); |
| } catch (IOException e) { |
| return null; |
| } |
| return ManifestElement.getArrayFromList(props.getProperty(JAVA_PROFILES), ","); //$NON-NLS-1$ |
| } |
| |
| } |