1 /*******************************************************************************
2  * Copyright (c) 2007, 2014 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  *     Rob Harrop - SpringSource Inc. (bug 247522)
14  *******************************************************************************/
15 package org.eclipse.osgi.internal.resolver;
16 
17 import java.util.*;
18 import org.eclipse.osgi.internal.framework.AliasMapper;
19 import org.eclipse.osgi.service.resolver.*;
20 import org.eclipse.osgi.service.resolver.VersionRange;
21 import org.osgi.framework.*;
22 
23 public class NativeCodeSpecificationImpl extends VersionConstraintImpl implements NativeCodeSpecification {
24 	private static final NativeCodeDescription[] EMPTY_NATIVECODEDESCRIPTIONS = new NativeCodeDescription[0];
25 	private static AliasMapper aliasMapper = new AliasMapper();
26 	private NativeCodeDescription[] possibleSuppliers;
27 	private boolean optional;
28 
getPossibleSuppliers()29 	public NativeCodeDescription[] getPossibleSuppliers() {
30 		synchronized (this.monitor) {
31 			if (possibleSuppliers == null)
32 				return EMPTY_NATIVECODEDESCRIPTIONS;
33 			return possibleSuppliers;
34 		}
35 	}
36 
setPossibleSuppliers(NativeCodeDescription[] possibleSuppliers)37 	void setPossibleSuppliers(NativeCodeDescription[] possibleSuppliers) {
38 		synchronized (this.monitor) {
39 			this.possibleSuppliers = possibleSuppliers;
40 		}
41 	}
42 
isOptional()43 	public boolean isOptional() {
44 		synchronized (this.monitor) {
45 			return optional;
46 		}
47 	}
48 
setOptional(boolean optional)49 	void setOptional(boolean optional) {
50 		synchronized (this.monitor) {
51 			this.optional = optional;
52 		}
53 	}
54 
55 	@SuppressWarnings("unchecked")
56 	@Override
isSatisfiedBy(BaseDescription supplier)57 	public boolean isSatisfiedBy(BaseDescription supplier) {
58 		if (!(supplier instanceof NativeCodeDescription))
59 			return false;
60 		State containingState = getBundle().getContainingState();
61 		if (containingState == null)
62 			return false;
63 		Dictionary<Object, Object>[] platformProps = containingState.getPlatformProperties();
64 		NativeCodeDescription nativeSupplier = (NativeCodeDescription) supplier;
65 		Filter filter = nativeSupplier.getFilter();
66 		boolean match = false;
67 		for (int i = 0; i < platformProps.length && !match; i++) {
68 			@SuppressWarnings("rawtypes")
69 			Dictionary props = platformProps[i];
70 			if (filter != null && !filter.matchCase(props))
71 				continue;
72 			String[] osNames = nativeSupplier.getOSNames();
73 			if (osNames.length == 0)
74 				match = true;
75 			else {
76 				Collection<?> platformOSAliases;
77 				Object platformOS = platformProps[i].get(Constants.FRAMEWORK_OS_NAME);
78 				if (platformOS instanceof Collection) {
79 					platformOSAliases = (Collection<?>) platformOS;
80 				} else if (platformOS instanceof String) {
81 					platformOS = aliasMapper.getCanonicalOSName((String) platformOS);
82 					platformOSAliases = aliasMapper.getOSNameAliases((String) platformOS);
83 				} else {
84 					platformOSAliases = platformOS == null ? Collections.emptyList() : Collections.singleton(platformOS);
85 				}
86 				osNamesLoop: for (String osName : osNames) {
87 					String canonicalOSName = aliasMapper.getCanonicalOSName(osName);
88 					for (Object osAlias : platformOSAliases) {
89 						if (osAlias instanceof String) {
90 							match = (((String) osAlias).equalsIgnoreCase(canonicalOSName));
91 						} else {
92 							match = osAlias.equals(canonicalOSName);
93 						}
94 						if (match) {
95 							break osNamesLoop;
96 						}
97 					}
98 				}
99 			}
100 			if (!match)
101 				continue;
102 			match = false;
103 
104 			String[] processors = nativeSupplier.getProcessors();
105 			if (processors.length == 0)
106 				match = true;
107 			else {
108 				Collection<?> platformProcessorAliases;
109 				Object platformProcessor = platformProps[i].get(Constants.FRAMEWORK_PROCESSOR);
110 				if (platformProcessor instanceof Collection) {
111 					platformProcessorAliases = (Collection<?>) platformProcessor;
112 				} else if (platformProcessor instanceof String) {
113 					platformProcessor = aliasMapper.getCanonicalProcessor((String) platformProcessor);
114 					platformProcessorAliases = aliasMapper.getProcessorAliases((String) platformProcessor);
115 				} else {
116 					platformProcessorAliases = platformProcessor == null ? Collections.emptyList() : Collections.singleton(platformProcessor);
117 				}
118 				processorLoop: for (String processor : processors) {
119 					String canonicalProcessor = aliasMapper.getCanonicalProcessor(processor);
120 					for (Object processorAlias : platformProcessorAliases) {
121 						if (processorAlias instanceof String) {
122 							match = ((String) processorAlias).equalsIgnoreCase(canonicalProcessor);
123 						} else {
124 							match = processorAlias.equals(canonicalProcessor);
125 						}
126 						if (match) {
127 							break processorLoop;
128 						}
129 					}
130 				}
131 			}
132 			if (!match)
133 				continue;
134 			match = false;
135 
136 			String[] languages = nativeSupplier.getLanguages();
137 			if (languages.length == 0)
138 				match = true;
139 			else {
140 				Object platformLanguage = platformProps[i].get(Constants.FRAMEWORK_LANGUAGE);
141 				if (platformLanguage != null)
142 					for (int j = 0; j < languages.length && !match; j++) {
143 						if ((platformLanguage instanceof String) ? ((String) platformLanguage).equalsIgnoreCase(languages[j]) : platformLanguage.equals(languages[j]))
144 							match = true;
145 					}
146 			}
147 			if (!match)
148 				continue;
149 			match = false;
150 
151 			VersionRange[] osVersions = nativeSupplier.getOSVersions();
152 			if (osVersions.length == 0 || platformProps[i].get(Constants.FRAMEWORK_OS_VERSION) == null)
153 				match = true;
154 			else {
155 				Version osversion;
156 				try {
157 					osversion = Version.parseVersion((String) platformProps[i].get(Constants.FRAMEWORK_OS_VERSION));
158 				} catch (Exception e) {
159 					osversion = Version.emptyVersion;
160 				}
161 				for (int j = 0; j < osVersions.length && !match; j++) {
162 					if (osVersions[j].isIncluded(osversion))
163 						match = true;
164 				}
165 			}
166 		}
167 		return match;
168 	}
169 
170 	@Override
hasMandatoryAttributes(String[] mandatory)171 	protected boolean hasMandatoryAttributes(String[] mandatory) {
172 		return true;
173 	}
174 
175 	@Override
toString()176 	public String toString() {
177 		StringBuilder sb = new StringBuilder();
178 		NativeCodeDescription[] suppliers = getPossibleSuppliers();
179 		for (int i = 0; i < suppliers.length; i++) {
180 			if (i > 0)
181 				sb.append(", "); //$NON-NLS-1$
182 			sb.append(suppliers[i].toString());
183 		}
184 
185 		return sb.toString();
186 	}
187 
188 	@Override
getInternalDirectives()189 	protected Map<String, String> getInternalDirectives() {
190 		return Collections.<String, String> emptyMap();
191 	}
192 
193 	@Override
getInteralAttributes()194 	protected Map<String, Object> getInteralAttributes() {
195 		return Collections.<String, Object> emptyMap();
196 	}
197 
198 	@Override
getInternalNameSpace()199 	protected String getInternalNameSpace() {
200 		return null;
201 	}
202 }
203