1 11 package org.eclipse.ui.internal.components.framework; 12 13 import java.util.ArrayList ; 14 import java.util.Collection ; 15 import java.util.Collections ; 16 import java.util.Iterator ; 17 import java.util.LinkedList ; 18 19 import org.eclipse.osgi.util.NLS; 20 import org.eclipse.ui.internal.WorkbenchPlugin; 21 import org.eclipse.ui.internal.components.Assert; 22 import org.eclipse.ui.internal.components.ComponentMessages; 23 24 94 public final class Container implements IDisposable, IServiceProvider { 95 96 97 private static class SingleFactoryContext extends ServiceFactory { 98 private ComponentFactory factory; 99 100 public SingleFactoryContext(ComponentFactory factory) { 101 this.factory = factory; 102 } 103 104 public ComponentHandle createHandle(Object componentKey, IServiceProvider container) throws ComponentException { 105 return factory.createHandle(container); 106 } 107 108 public Collection getMissingDependencies() { 109 return Collections.EMPTY_SET; 110 } 111 112 public boolean hasService(Object componentKey) { 113 return true; 114 } 115 116 } 117 118 private static final class ComponentInfo { 119 IDisposable disposable; 120 Object component; 121 Object key; 122 123 132 public ComponentInfo(Object key, Object component, IDisposable disposable) { 133 this.key = key; 134 this.component = component; 135 this.disposable = disposable; 136 } 137 138 public Object getKey() { 139 return key; 140 } 141 142 public Object getInstance() { 143 return component; 144 } 145 146 public void dispose() { 147 if (disposable != null) { 148 disposable.dispose(); 149 } 150 } 151 152 } 153 154 private ArrayList services = new ArrayList (); 156 private LinkedList inProgress = null; 157 158 private ServiceFactory defaultContext; 159 160 164 private boolean verified = false; 165 166 171 public Container(ServiceFactory context) { 172 Assert.isNotNull(context); 173 Collection deps = context.getMissingDependencies(); 174 if (deps.size() != 0) { 175 Assert.isTrue(false, ComponentMessages.Container_missing_dependency + deps.toArray()[0].toString()); 176 } 177 178 this.defaultContext = context; 179 } 180 181 184 public void dispose() { 185 if (isDisposed()) { 186 return; 187 } 188 deallocateComponents(0); 189 190 services = null; 191 } 192 193 200 private void deallocateComponents(int index) { 201 ComponentInfo[] servicesArray = (ComponentInfo[]) services.toArray(new ComponentInfo[services.size()]); 202 for (int i = servicesArray.length - 1; i >= index; i--) { 203 ComponentInfo info = servicesArray[i]; 204 205 try { 206 info.dispose(); 207 } catch (Exception e) { 208 WorkbenchPlugin.log(e); 209 } 210 } 211 212 services = new ArrayList (); 213 for (int i = 0; i < index; i++) { 214 ComponentInfo info = servicesArray[i]; 215 216 services.add(info); 217 } 218 } 219 220 private final Object getComponent(Object key, ServiceFactory context, IServiceProvider dependencies) throws ComponentException { 221 222 Object existingInstance = getExistingComponent(key, context); 223 224 if (existingInstance != null) { 225 return existingInstance; 226 } 227 228 230 if (inProgress != null) { 233 for (Iterator iter = inProgress.iterator(); iter.hasNext();) { 234 Object next = iter.next(); 236 237 if (next.equals(key)) { 238 throw new ComponentException(key, NLS.bind( 239 ComponentMessages.Container_cycle_detected, 240 key.toString()), null); 241 } 242 } 243 } else { 244 inProgress = new LinkedList (); 245 } 246 247 inProgress.add(key); 248 249 int start = services.size(); 250 251 boolean success = false; 252 253 try { 254 ComponentHandle handle = context.createHandle(key, dependencies); 255 if (handle != null) { 256 if (handle.requiresDisposal()) { 257 services.add(new ComponentInfo(key, handle.getInstance(), handle.getDisposable())); 258 } 259 Object result = handle.getInstance(); 260 success = true; 261 return result; 262 } 263 } finally { 264 if (!success) { 265 deallocateComponents(start); 268 } 269 inProgress.removeLast(); 270 if (inProgress.isEmpty()) { 271 inProgress = null; 272 } 273 } 274 275 return null; 276 } 277 278 private final Object getExistingComponent(Object key, ServiceFactory context) { 279 for (Iterator iter = services.iterator(); iter.hasNext();) { 281 ComponentInfo info = (ComponentInfo) iter.next(); 282 283 if (info.getKey().equals(key)) { 284 return info.getInstance(); 285 } 286 } 287 288 return null; 289 } 290 291 296 public boolean isDisposed() { 297 return services == null; 298 } 299 300 303 public Object getService(Object key) throws ComponentException { 304 try { 305 return getComponent(key, defaultContext, this); 306 } catch (ComponentException e) { 307 throw new ComponentException(key, e); 308 } 309 } 310 311 private Object getComponentFromFactory(ComponentFactory factory) throws ComponentException { 312 return getComponent(factory, new SingleFactoryContext(factory), this); 313 } 314 315 318 public boolean hasService(Object key) { 319 return defaultContext.hasService(key); 320 } 321 322 } 323 | Popular Tags |