1 /******************************************************************************* 2 * Copyright (c) 2003, 2016 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.service.resolver.*; 19 import org.osgi.framework.Constants; 20 import org.osgi.framework.wiring.BundleRevision; 21 22 public class BundleSpecificationImpl extends VersionConstraintImpl implements BundleSpecification { 23 private boolean exported; 24 private boolean optional; 25 private Map<String, Object> attributes; 26 private Map<String, String> arbitraryDirectives; 27 setExported(boolean exported)28 protected void setExported(boolean exported) { 29 synchronized (this.monitor) { 30 this.exported = exported; 31 } 32 } 33 setOptional(boolean optional)34 protected void setOptional(boolean optional) { 35 synchronized (this.monitor) { 36 this.optional = optional; 37 } 38 } 39 isExported()40 public boolean isExported() { 41 synchronized (this.monitor) { 42 return exported; 43 } 44 } 45 isOptional()46 public boolean isOptional() { 47 synchronized (this.monitor) { 48 return optional; 49 } 50 } 51 getAttributes()52 Map<String, Object> getAttributes() { 53 synchronized (this.monitor) { 54 return attributes; 55 } 56 } 57 58 @SuppressWarnings("unchecked") setAttributes(Map<String, ?> attributes)59 void setAttributes(Map<String, ?> attributes) { 60 synchronized (this.monitor) { 61 this.attributes = (Map<String, Object>) attributes; 62 } 63 } 64 getArbitraryDirectives()65 Map<String, String> getArbitraryDirectives() { 66 synchronized (this.monitor) { 67 return arbitraryDirectives; 68 } 69 } 70 71 @SuppressWarnings("unchecked") setArbitraryDirectives(Map<String, ?> directives)72 void setArbitraryDirectives(Map<String, ?> directives) { 73 synchronized (this.monitor) { 74 this.arbitraryDirectives = (Map<String, String>) directives; 75 } 76 } 77 78 @Override isSatisfiedBy(BaseDescription supplier)79 public boolean isSatisfiedBy(BaseDescription supplier) { 80 if (!(supplier instanceof BundleDescriptionImpl)) 81 return false; 82 BundleDescriptionImpl candidate = (BundleDescriptionImpl) supplier; 83 if (candidate.getHost() != null) 84 return false; 85 Map<String, ?> requiredAttrs = getAttributes(); 86 if (requiredAttrs != null) { 87 Map<String, ?> prividerAttrs = candidate.getAttributes(); 88 if (prividerAttrs == null) 89 return false; 90 for (String key : requiredAttrs.keySet()) { 91 Object requiredValue = requiredAttrs.get(key); 92 Object prividedValue = prividerAttrs.get(key); 93 if (prividedValue == null || !requiredValue.equals(prividedValue)) 94 return false; 95 } 96 } 97 String[] mandatory = (String[]) candidate.getDirective(Constants.MANDATORY_DIRECTIVE); 98 if (!hasMandatoryAttributes(mandatory)) 99 return false; 100 if (getName() != null && getName().equals(candidate.getSymbolicName()) && (getVersionRange() == null || getVersionRange().isIncluded(candidate.getVersion()))) 101 return true; 102 return false; 103 } 104 105 @Override hasMandatoryAttributes(String[] mandatory)106 protected boolean hasMandatoryAttributes(String[] mandatory) { 107 if (mandatory != null) { 108 Map<String, ?> requiredAttrs = getAttributes(); 109 for (String key : mandatory) { 110 if (Constants.BUNDLE_VERSION_ATTRIBUTE.equals(key)) 111 continue; // has a default value of 0.0.0 112 if (requiredAttrs == null || requiredAttrs.get(key) == null) 113 return false; 114 } 115 } 116 return true; 117 } 118 119 @Override toString()120 public String toString() { 121 return "Require-Bundle: " + getName() + "; bundle-version=\"" + getVersionRange() + "\""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 122 } 123 124 @Override getInternalDirectives()125 protected Map<String, String> getInternalDirectives() { 126 Map<String, String> result = new HashMap<>(2); 127 synchronized (this.monitor) { 128 if (arbitraryDirectives != null) 129 result.putAll(arbitraryDirectives); 130 if (exported) 131 result.put(Constants.VISIBILITY_DIRECTIVE, Constants.VISIBILITY_REEXPORT); 132 if (optional) 133 result.put(Constants.RESOLUTION_DIRECTIVE, Constants.RESOLUTION_OPTIONAL); 134 result.put(Constants.FILTER_DIRECTIVE, createFilterDirective()); 135 return result; 136 } 137 } 138 createFilterDirective()139 private String createFilterDirective() { 140 StringBuilder filter = new StringBuilder(); 141 filter.append("(&"); //$NON-NLS-1$ 142 synchronized (this.monitor) { 143 addFilterAttribute(filter, BundleRevision.BUNDLE_NAMESPACE, getName()); 144 VersionRange range = getVersionRange(); 145 if (range != null && range != VersionRange.emptyRange) 146 addFilterAttribute(filter, Constants.BUNDLE_VERSION_ATTRIBUTE, range); 147 if (attributes != null) 148 addFilterAttributes(filter, attributes); 149 } 150 filter.append(')'); 151 return filter.toString(); 152 } 153 154 @Override getInteralAttributes()155 protected Map<String, Object> getInteralAttributes() { 156 return Collections.<String, Object> emptyMap(); 157 } 158 159 @Override getInternalNameSpace()160 protected String getInternalNameSpace() { 161 return BundleRevision.BUNDLE_NAMESPACE; 162 } 163 } 164