|
1 /** |
|
2 * Copyright (c) 2010 Symbian Foundation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Symbian Foundation - initial contribution. |
|
11 * Contributors: |
|
12 * Description: |
|
13 * Overview: |
|
14 * Details: |
|
15 * Platforms/Drives/Compatibility: |
|
16 * Assumptions/Requirement/Pre-requisites: |
|
17 * Failures and causes: |
|
18 */ |
|
19 package org.symbian.tools.tmw.core.internal.runtimes; |
|
20 |
|
21 import java.util.Arrays; |
|
22 import java.util.Collection; |
|
23 import java.util.Collections; |
|
24 import java.util.HashMap; |
|
25 import java.util.HashSet; |
|
26 import java.util.LinkedList; |
|
27 import java.util.Map; |
|
28 import java.util.Set; |
|
29 |
|
30 import org.eclipse.core.runtime.CoreException; |
|
31 import org.eclipse.core.runtime.IConfigurationElement; |
|
32 import org.eclipse.core.runtime.Platform; |
|
33 import org.eclipse.wst.common.project.facet.core.IFacetedProject; |
|
34 import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion; |
|
35 import org.eclipse.wst.common.project.facet.core.IVersion; |
|
36 import org.eclipse.wst.common.project.facet.core.IVersionExpr; |
|
37 import org.eclipse.wst.common.project.facet.core.util.internal.VersionExpr; |
|
38 import org.eclipse.wst.common.project.facet.core.util.internal.Versionable; |
|
39 import org.eclipse.wst.jsdt.core.IIncludePathEntry; |
|
40 import org.symbian.tools.tmw.core.TMWCore; |
|
41 import org.symbian.tools.tmw.core.internal.projects.LazyIncludePathProvider; |
|
42 import org.symbian.tools.tmw.core.internal.projects.StaticIncludePathProvider; |
|
43 import org.symbian.tools.tmw.core.projects.IFacetIncludePathProvider; |
|
44 import org.symbian.tools.tmw.core.projects.IMTWProject; |
|
45 import org.symbian.tools.tmw.core.runtimes.IMobileWebRuntime; |
|
46 |
|
47 @SuppressWarnings("restriction") |
|
48 public class RuntimeClasspathManager { |
|
49 private static final class VersionedEntry<T> { |
|
50 protected final IVersionExpr versionExpression; |
|
51 protected final T entry; |
|
52 |
|
53 public VersionedEntry(String versionExpression, T entry) { |
|
54 if (versionExpression == null) { |
|
55 this.versionExpression = null; |
|
56 } else { |
|
57 IVersionExpr expr; |
|
58 try { |
|
59 expr = new VersionExpr<Version>(new VersionableObject(), versionExpression, null); |
|
60 } catch (CoreException e) { |
|
61 expr = null; |
|
62 TMWCore.log(null, e); |
|
63 } |
|
64 this.versionExpression = expr; |
|
65 } |
|
66 this.entry = entry; |
|
67 } |
|
68 |
|
69 public boolean matches(String version) { |
|
70 if (versionExpression == null) { // Any version |
|
71 return true; |
|
72 } |
|
73 if (version == null) { // Unspecified |
|
74 return false; |
|
75 } |
|
76 return versionExpression.check(new Version(version)); |
|
77 } |
|
78 } |
|
79 |
|
80 private static final class VersionableObject extends Versionable<Version> { |
|
81 @Override |
|
82 public String getPluginId() { |
|
83 return TMWCore.PLUGIN_ID; |
|
84 } |
|
85 |
|
86 @Override |
|
87 public String createVersionNotFoundErrMsg(String verstr) { |
|
88 return "Version not found"; |
|
89 } |
|
90 } |
|
91 |
|
92 private static final class Version implements IVersion { |
|
93 private final String version; |
|
94 |
|
95 public Version(String version) { |
|
96 this.version = version; |
|
97 } |
|
98 |
|
99 public int compareTo(Object o) { |
|
100 return version.compareTo(((IVersion) o).getVersionString()); |
|
101 } |
|
102 |
|
103 public String getVersionString() { |
|
104 return version; |
|
105 } |
|
106 } |
|
107 |
|
108 private final Map<String, Collection<VersionedEntry<Map<String, Collection<VersionedEntry<IFacetIncludePathProvider[]>>>>>> providers = new HashMap<String, Collection<VersionedEntry<Map<String, Collection<VersionedEntry<IFacetIncludePathProvider[]>>>>>>(); |
|
109 private final boolean ready = false; |
|
110 |
|
111 public IIncludePathEntry[] getProjectClasspathEntries(IFacetedProject project) { |
|
112 collectProviders(); |
|
113 final IMTWProject p = TMWCore.getDefault().create(project.getProject()); |
|
114 if (p != null) { |
|
115 final IMobileWebRuntime runtime = p.getTargetRuntime(); |
|
116 final Map<String, Collection<VersionedEntry<IFacetIncludePathProvider[]>>> facetToEntry; |
|
117 if (runtime != null) { |
|
118 facetToEntry = join(getMatchingEntries(runtime.getId(), runtime.getVersion(), providers)); |
|
119 } else { |
|
120 facetToEntry = join(getMatchingEntries(null, null, providers)); |
|
121 } |
|
122 final Collection<IFacetIncludePathProvider[]> entries = getMatchingEntries(null, null, facetToEntry); |
|
123 final Set<IProjectFacetVersion> facets = project.getProjectFacets(); |
|
124 for (IProjectFacetVersion facet : facets) { |
|
125 entries.addAll(getMatchingEntries(facet.getProjectFacet().getId(), facet.getVersionString(), |
|
126 facetToEntry)); |
|
127 } |
|
128 final Collection<IIncludePathEntry> pathEntries = new HashSet<IIncludePathEntry>(); |
|
129 for (IFacetIncludePathProvider[] providers : entries) { |
|
130 for (IFacetIncludePathProvider provider : providers) { |
|
131 pathEntries.addAll(Arrays.asList(provider.getEntries(p))); |
|
132 } |
|
133 } |
|
134 return pathEntries.toArray(new IIncludePathEntry[pathEntries.size()]); |
|
135 } |
|
136 return new IIncludePathEntry[0]; |
|
137 } |
|
138 |
|
139 @SuppressWarnings({ "rawtypes", "unchecked" }) |
|
140 private synchronized void collectProviders() { |
|
141 if (!ready) { |
|
142 final IConfigurationElement[] elements = Platform.getExtensionRegistry().getConfigurationElementsFor( |
|
143 TMWCore.PLUGIN_ID, "runtimeIncludePath"); |
|
144 final Map<String, Collection<VersionedEntry<IFacetIncludePathProvider[]>>> entries = collectFaceletEntries(elements); |
|
145 final VersionedEntry<Map<String, Collection<VersionedEntry<IFacetIncludePathProvider[]>>>> entry = new VersionedEntry( |
|
146 null, entries); |
|
147 providers.put(null, Collections.singleton(entry)); |
|
148 for (IConfigurationElement element : elements) { |
|
149 if ("runtime-include-path".equals(element.getName())) { |
|
150 final String id = element.getAttribute("id"); |
|
151 Collection<VersionedEntry<Map<String, Collection<VersionedEntry<IFacetIncludePathProvider[]>>>>> versions = providers |
|
152 .get(id); |
|
153 if (versions == null) { |
|
154 versions = new LinkedList<RuntimeClasspathManager.VersionedEntry<Map<String, Collection<VersionedEntry<IFacetIncludePathProvider[]>>>>>(); |
|
155 providers.put(id, versions); |
|
156 } |
|
157 final Map<String, Collection<VersionedEntry<IFacetIncludePathProvider[]>>> facetProviders = new HashMap<String, Collection<VersionedEntry<IFacetIncludePathProvider[]>>>(); |
|
158 final IFacetIncludePathProvider[] collection = collectProviders(element.getChildren()); |
|
159 final VersionedEntry<IFacetIncludePathProvider[]> ent = new VersionedEntry(null, collection); |
|
160 facetProviders.put(null, Collections.singleton(ent)); |
|
161 facetProviders.putAll(collectFaceletEntries(element.getChildren())); |
|
162 final VersionedEntry<Map<String, Collection<VersionedEntry<IFacetIncludePathProvider[]>>>> ver = new VersionedEntry<Map<String, Collection<VersionedEntry<IFacetIncludePathProvider[]>>>>( |
|
163 element.getAttribute("version"), facetProviders); |
|
164 versions.add(ver); |
|
165 } |
|
166 } |
|
167 } |
|
168 } |
|
169 |
|
170 private IFacetIncludePathProvider[] collectProviders(IConfigurationElement[] children) { |
|
171 final Collection<IFacetIncludePathProvider> providers = new LinkedList<IFacetIncludePathProvider>(); |
|
172 for (IConfigurationElement element : children) { |
|
173 if ("include-path-entry".equals(element.getName())) { |
|
174 providers.add(new StaticIncludePathProvider(element)); |
|
175 } else if ("include-path-provider".equals(element.getName())) { |
|
176 providers.add(new LazyIncludePathProvider(element)); |
|
177 } |
|
178 } |
|
179 return providers.toArray(new IFacetIncludePathProvider[providers.size()]); |
|
180 } |
|
181 |
|
182 public Map<String, Collection<VersionedEntry<IFacetIncludePathProvider[]>>> collectFaceletEntries( |
|
183 IConfigurationElement[] elements) { |
|
184 final Map<String, Collection<VersionedEntry<IFacetIncludePathProvider[]>>> faceletsToProviders = new HashMap<String, Collection<VersionedEntry<IFacetIncludePathProvider[]>>>(); |
|
185 for (IConfigurationElement element : elements) { |
|
186 if ("facet-include-path".equals(element.getName())) { |
|
187 final IFacetIncludePathProvider[] providers = collectProviders(element.getChildren()); |
|
188 final VersionedEntry<IFacetIncludePathProvider[]> versionedEntry = new VersionedEntry<IFacetIncludePathProvider[]>( |
|
189 element.getAttribute("version"), providers); |
|
190 final String id = element.getAttribute("facelet-id"); |
|
191 Collection<VersionedEntry<IFacetIncludePathProvider[]>> provs = faceletsToProviders.get(id); |
|
192 if (provs == null) { |
|
193 provs = new LinkedList<RuntimeClasspathManager.VersionedEntry<IFacetIncludePathProvider[]>>(); |
|
194 faceletsToProviders.put(id, provs); |
|
195 } |
|
196 provs.add(versionedEntry); |
|
197 } |
|
198 } |
|
199 return faceletsToProviders; |
|
200 } |
|
201 |
|
202 private <T, V> Map<T, Collection<V>> join(Collection<Map<T, Collection<V>>> maps) { |
|
203 final Map<T, Collection<V>> res = new HashMap<T, Collection<V>>(); |
|
204 for (Map<T, Collection<V>> map : maps) { |
|
205 for (Map.Entry<T, Collection<V>> entry : map.entrySet()) { |
|
206 if (res.containsKey(entry.getKey())) { |
|
207 res.get(entry.getKey()).addAll(entry.getValue()); |
|
208 } else { |
|
209 res.put(entry.getKey(), new LinkedList<V>(entry.getValue())); |
|
210 } |
|
211 } |
|
212 } |
|
213 return res; |
|
214 } |
|
215 |
|
216 private <T> Collection<T> getMatchingEntries(String id, String version, |
|
217 Map<String, Collection<VersionedEntry<T>>> map) { |
|
218 final Collection<VersionedEntry<T>> entries = new LinkedList<VersionedEntry<T>>(); |
|
219 Collection<VersionedEntry<T>> versionedEntries = map.get(null); |
|
220 if (versionedEntries != null) { |
|
221 entries.addAll(versionedEntries); |
|
222 } |
|
223 if (id != null) { |
|
224 versionedEntries = map.get(id); |
|
225 if (versionedEntries != null) { |
|
226 entries.addAll(versionedEntries); |
|
227 } |
|
228 } |
|
229 final Collection<T> res = new LinkedList<T>(); |
|
230 for (VersionedEntry<T> versionedEntry : entries) { |
|
231 if (versionedEntry.matches(version)) { |
|
232 res.add(versionedEntry.entry); |
|
233 } |
|
234 } |
|
235 return res; |
|
236 } |
|
237 } |