1 /*******************************************************************************
2  * Copyright (c) 2004, 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 java.util.Map.Entry;
19 import org.eclipse.osgi.service.resolver.BaseDescription;
20 import org.osgi.framework.Version;
21 import org.osgi.framework.wiring.BundleCapability;
22 import org.osgi.framework.wiring.BundleRevision;
23 
24 public abstract class BaseDescriptionImpl implements BaseDescription {
25 
26 	protected final Object monitor = new Object();
27 
28 	private volatile String name;
29 
30 	private volatile Version version;
31 
32 	private volatile Object userObject;
33 
getName()34 	public String getName() {
35 		return name;
36 	}
37 
getVersion()38 	public Version getVersion() {
39 		synchronized (this.monitor) {
40 			if (version == null)
41 				return Version.emptyVersion;
42 			return version;
43 		}
44 	}
45 
setName(String name)46 	protected void setName(String name) {
47 		this.name = name;
48 	}
49 
setVersion(Version version)50 	protected void setVersion(Version version) {
51 		this.version = version;
52 	}
53 
toString(Map<String, V> map, boolean directives)54 	static <V> String toString(Map<String, V> map, boolean directives) {
55 		if (map.size() == 0)
56 			return ""; //$NON-NLS-1$
57 		String assignment = directives ? ":=" : "="; //$NON-NLS-1$//$NON-NLS-2$
58 		Set<Entry<String, V>> set = map.entrySet();
59 		StringBuilder sb = new StringBuilder();
60 		for (Entry<String, V> entry : set) {
61 			sb.append("; "); //$NON-NLS-1$
62 			String key = entry.getKey();
63 			Object value = entry.getValue();
64 			if (value instanceof List) {
65 				@SuppressWarnings("unchecked")
66 				List<Object> list = (List<Object>) value;
67 				if (list.size() == 0)
68 					continue;
69 				Object component = list.get(0);
70 				String className = component.getClass().getName();
71 				String type = className.substring(className.lastIndexOf('.') + 1);
72 				sb.append(key).append(':').append("List<").append(type).append(">").append(assignment).append('"'); //$NON-NLS-1$ //$NON-NLS-2$
73 				for (Object object : list)
74 					sb.append(object).append(',');
75 				sb.setLength(sb.length() - 1);
76 				sb.append('"');
77 			} else {
78 				String type = ""; //$NON-NLS-1$
79 				if (!(value instanceof String)) {
80 					String className = value.getClass().getName();
81 					type = ":" + className.substring(className.lastIndexOf('.') + 1); //$NON-NLS-1$
82 				}
83 				sb.append(key).append(type).append(assignment).append('"').append(value).append('"');
84 			}
85 		}
86 		return sb.toString();
87 	}
88 
getInternalNameSpace()89 	String getInternalNameSpace() {
90 		return null;
91 	}
92 
getFragmentDeclaration()93 	public BaseDescription getFragmentDeclaration() {
94 		return null;
95 	}
96 
getCapability()97 	public BundleCapability getCapability() {
98 		return getCapability(null);
99 	}
100 
getCapability(String namespace)101 	BundleCapability getCapability(String namespace) {
102 		BaseDescriptionImpl fragmentDeclaration = (BaseDescriptionImpl) getFragmentDeclaration();
103 		if (fragmentDeclaration != null)
104 			return fragmentDeclaration.getCapability(namespace);
105 		if (namespace == null)
106 			namespace = getInternalNameSpace();
107 		if (namespace == null)
108 			return null;
109 		return new BaseCapability(namespace);
110 	}
111 
getUserObject()112 	public Object getUserObject() {
113 		return userObject;
114 	}
115 
setUserObject(Object userObject)116 	public void setUserObject(Object userObject) {
117 		this.userObject = userObject;
118 	}
119 
120 	public class BaseCapability implements BundleCapability {
121 		private final String namespace;
122 
BaseCapability(String namespace)123 		public BaseCapability(String namespace) {
124 			super();
125 			this.namespace = namespace;
126 		}
127 
getRevision()128 		public BundleRevision getRevision() {
129 			return getSupplier();
130 		}
131 
getNamespace()132 		public String getNamespace() {
133 			return namespace;
134 		}
135 
getDirectives()136 		public Map<String, String> getDirectives() {
137 			return getDeclaredDirectives();
138 		}
139 
getAttributes()140 		public Map<String, Object> getAttributes() {
141 			Map<String, Object> attrs = getDeclaredAttributes();
142 			String internalName = BaseDescriptionImpl.this.getInternalNameSpace();
143 			if (namespace.equals(internalName))
144 				return attrs;
145 			// we are doing an alias, must remove internal Name and add alias
146 			attrs = new HashMap<>(attrs);
147 			Object nameValue = attrs.remove(internalName);
148 			if (nameValue != null)
149 				attrs.put(namespace, nameValue);
150 			return Collections.unmodifiableMap(attrs);
151 		}
152 
153 		@Override
hashCode()154 		public int hashCode() {
155 			return System.identityHashCode(BaseDescriptionImpl.this);
156 		}
157 
getBaseDescription()158 		public BaseDescriptionImpl getBaseDescription() {
159 			return BaseDescriptionImpl.this;
160 		}
161 
162 		@Override
equals(Object obj)163 		public boolean equals(Object obj) {
164 			if (this == obj)
165 				return true;
166 			if (!(obj instanceof BaseCapability))
167 				return false;
168 			return (((BaseCapability) obj).getBaseDescription() == BaseDescriptionImpl.this) && namespace.equals(((BaseCapability) obj).getNamespace());
169 		}
170 
171 		@Override
toString()172 		public String toString() {
173 			return getNamespace() + BaseDescriptionImpl.toString(getAttributes(), false) + BaseDescriptionImpl.toString(getDirectives(), true);
174 		}
175 
getResource()176 		public BundleRevision getResource() {
177 			return getRevision();
178 		}
179 	}
180 }
181