org.eclipse.e4.core.di.extensions_0.11.100.v20121024-182359

16:42:56.376 INFO  jd.cli.Main - Decompiling org.eclipse.e4.core.di.extensions_0.11.100.v20121024-182359.jar
package org.eclipse.e4.core.di.extensions;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;

@Qualifier
@Documented
@Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface EventTopic
{
  String value() default "";
}

/* Location:
 * Qualified Name:     org.eclipse.e4.core.di.extensions.EventTopic
 * Java Class Version: 5 (49.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.e4.core.di.extensions;

import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Map;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;

public final class EventUtils
{
  public static final String DATA = "org.eclipse.e4.data";
  
  public static boolean send(EventAdmin eventAdmin, String topic, Object data)
  {
    Event event = constructEvent(topic, data);
    eventAdmin.sendEvent(event);
    return true;
  }
  
  public static boolean post(EventAdmin eventAdmin, String topic, Object data)
  {
    Event event = constructEvent(topic, data);
    eventAdmin.postEvent(event);
    return true;
  }
  
  public static Event constructEvent(String topic, Object data)
  {
    Event event;
    Event event;
    if ((data instanceof Dictionary))
    {
      event = new Event(topic, (Dictionary)data);
    }
    else
    {
      Event event;
      if ((data instanceof Map))
      {
        event = new Event(topic, (Map)data);
      }
      else
      {
        Dictionary<String, Object> d = new Hashtable(2);
        d.put("event.topics", topic);
        if (data != null) {
          d.put("org.eclipse.e4.data", data);
        }
        event = new Event(topic, d);
      }
    }
    return event;
  }
}

/* Location:
 * Qualified Name:     org.eclipse.e4.core.di.extensions.EventUtils
 * Java Class Version: 5 (49.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.e4.core.di.extensions;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;

@Qualifier
@Documented
@Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Preference
{
  String value() default "";
  
  String nodePath() default "";
}

/* Location:
 * Qualified Name:     org.eclipse.e4.core.di.extensions.Preference
 * Java Class Version: 5 (49.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.e4.core.di.internal.extensions;

import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.service.event.EventAdmin;
import org.osgi.util.tracker.ServiceTracker;

public class DIEActivator
  implements BundleActivator
{
  private static DIEActivator defaultInstance;
  private BundleContext bundleContext;
  private ServiceTracker preferencesTracker;
  private ServiceTracker eventAdminTracker;
  private Set<PreferencesObjectSupplier> preferenceSuppliers = new HashSet();
  
  public DIEActivator()
  {
    defaultInstance = this;
  }
  
  public static DIEActivator getDefault()
  {
    return defaultInstance;
  }
  
  public void start(BundleContext context)
    throws Exception
  {
    bundleContext = context;
  }
  
  public void stop(BundleContext context)
    throws Exception
  {
    for (PreferencesObjectSupplier supplier : preferenceSuppliers) {
      supplier.removeAllListeners();
    }
    preferenceSuppliers.clear();
    if (preferencesTracker != null)
    {
      preferencesTracker.close();
      preferencesTracker = null;
    }
    if (eventAdminTracker != null)
    {
      eventAdminTracker.close();
      eventAdminTracker = null;
    }
    bundleContext = null;
  }
  
  public BundleContext getBundleContext()
  {
    return bundleContext;
  }
  
  public IPreferencesService getPreferencesService()
  {
    if (preferencesTracker == null)
    {
      if (bundleContext == null) {
        return null;
      }
      preferencesTracker = new ServiceTracker(bundleContext, IPreferencesService.class.getName(), null);
      preferencesTracker.open();
    }
    return (IPreferencesService)preferencesTracker.getService();
  }
  
  public EventAdmin getEventAdmin()
  {
    if (eventAdminTracker == null)
    {
      if (bundleContext == null) {
        return null;
      }
      eventAdminTracker = new ServiceTracker(bundleContext, EventAdmin.class.getName(), null);
      eventAdminTracker.open();
    }
    return (EventAdmin)eventAdminTracker.getService();
  }
  
  public void registerPreferencesSupplier(PreferencesObjectSupplier supplier)
  {
    preferenceSuppliers.add(supplier);
  }
}

/* Location:
 * Qualified Name:     org.eclipse.e4.core.di.internal.extensions.DIEActivator
 * Java Class Version: 5 (49.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.e4.core.di.internal.extensions;

import org.eclipse.e4.core.di.suppliers.IRequestor;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;

class EventObjectSupplier$DIEventHandler
  implements EventHandler
{
  private final IRequestor requestor;
  private final String topic;
  
  public EventObjectSupplier$DIEventHandler(EventObjectSupplier paramEventObjectSupplier, String topic, IRequestor requestor)
  {
    this.topic = topic;
    this.requestor = requestor;
  }
  
  public void handleEvent(Event event)
  {
    if (!requestor.isValid())
    {
      this$0.unsubscribe(requestor);
      return;
    }
    this$0.addCurrentEvent(topic, event);
    requestor.resolveArguments(false);
    this$0.removeCurrentEvent(topic);
    
    requestor.execute();
  }
}

/* Location:
 * Qualified Name:     org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier.DIEventHandler
 * Java Class Version: 5 (49.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.e4.core.di.internal.extensions;

import org.eclipse.e4.core.di.suppliers.IRequestor;

class EventObjectSupplier$Subscriber
{
  private IRequestor requestor;
  private String topic;
  
  public EventObjectSupplier$Subscriber(IRequestor requestor, String topic)
  {
    this.requestor = requestor;
    this.topic = topic;
  }
  
  public int hashCode()
  {
    int result = 1;
    result = 31 * result + (requestor == null ? 0 : requestor.hashCode());
    result = 31 * result + (topic == null ? 0 : topic.hashCode());
    return result;
  }
  
  public IRequestor getRequestor()
  {
    return requestor;
  }
  
  public boolean equals(Object obj)
  {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    Subscriber other = (Subscriber)obj;
    if (requestor == null)
    {
      if (requestor != null) {
        return false;
      }
    }
    else if (!requestor.equals(requestor)) {
      return false;
    }
    if (topic == null)
    {
      if (topic != null) {
        return false;
      }
    }
    else if (!topic.equals(topic)) {
      return false;
    }
    return true;
  }
}

/* Location:
 * Qualified Name:     org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier.Subscriber
 * Java Class Version: 5 (49.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.e4.core.di.internal.extensions;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.PreDestroy;
import org.eclipse.e4.core.di.IInjector;
import org.eclipse.e4.core.di.InjectionException;
import org.eclipse.e4.core.di.extensions.EventTopic;
import org.eclipse.e4.core.di.suppliers.ExtendedObjectSupplier;
import org.eclipse.e4.core.di.suppliers.IObjectDescriptor;
import org.eclipse.e4.core.di.suppliers.IRequestor;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventHandler;

public class EventObjectSupplier
  extends ExtendedObjectSupplier
{
  static
  {
    if (getEventAdmin() == null)
    {
      Bundle[] bundles = DIEActivator.getDefault().getBundleContext().getBundles();
      Bundle[] arrayOfBundle1 = bundles;int j = bundles.length;
      for (int i = 0; i < j; i++)
      {
        Bundle bundle = arrayOfBundle1[i];
        if ("org.eclipse.equinox.event".equals(bundle.getSymbolicName())) {
          try
          {
            bundle.start(1);
          }
          catch (BundleException e)
          {
            e.printStackTrace();
          }
        }
      }
    }
  }
  
  protected Map<String, Event> currentEvents = new HashMap();
  
  class DIEventHandler
    implements EventHandler
  {
    private final IRequestor requestor;
    private final String topic;
    
    public DIEventHandler(String topic, IRequestor requestor)
    {
      this.topic = topic;
      this.requestor = requestor;
    }
    
    public void handleEvent(Event event)
    {
      if (!requestor.isValid())
      {
        unsubscribe(requestor);
        return;
      }
      addCurrentEvent(topic, event);
      requestor.resolveArguments(false);
      removeCurrentEvent(topic);
      
      requestor.execute();
    }
  }
  
  private static class Subscriber
  {
    private IRequestor requestor;
    private String topic;
    
    public Subscriber(IRequestor requestor, String topic)
    {
      this.requestor = requestor;
      this.topic = topic;
    }
    
    public int hashCode()
    {
      int result = 1;
      result = 31 * result + (requestor == null ? 0 : requestor.hashCode());
      result = 31 * result + (topic == null ? 0 : topic.hashCode());
      return result;
    }
    
    public IRequestor getRequestor()
    {
      return requestor;
    }
    
    public boolean equals(Object obj)
    {
      if (this == obj) {
        return true;
      }
      if (obj == null) {
        return false;
      }
      if (getClass() != obj.getClass()) {
        return false;
      }
      Subscriber other = (Subscriber)obj;
      if (requestor == null)
      {
        if (requestor != null) {
          return false;
        }
      }
      else if (!requestor.equals(requestor)) {
        return false;
      }
      if (topic == null)
      {
        if (topic != null) {
          return false;
        }
      }
      else if (!topic.equals(topic)) {
        return false;
      }
      return true;
    }
  }
  
  private Map<Subscriber, ServiceRegistration> registrations = new HashMap();
  
  protected void addCurrentEvent(String topic, Event event)
  {
    synchronized (currentEvents)
    {
      currentEvents.put(topic, event);
    }
  }
  
  protected void removeCurrentEvent(String topic)
  {
    synchronized (currentEvents)
    {
      currentEvents.remove(topic);
    }
  }
  
  public Object get(IObjectDescriptor descriptor, IRequestor requestor, boolean track, boolean group)
  {
    if (descriptor == null) {
      return null;
    }
    String topic = getTopic(descriptor);
    EventAdmin eventAdmin = getEventAdmin();
    if ((topic == null) || (eventAdmin == null) || (topic.length() == 0)) {
      return IInjector.NOT_A_VALUE;
    }
    if (track) {
      subscribe(topic, eventAdmin, requestor);
    } else {
      unsubscribe(requestor);
    }
    if (!currentEvents.containsKey(topic)) {
      return IInjector.NOT_A_VALUE;
    }
    Class<?> descriptorsClass = getDesiredClass(descriptor.getDesiredType());
    if (descriptorsClass.equals(Event.class)) {
      return currentEvents.get(topic);
    }
    return ((Event)currentEvents.get(topic)).getProperty("org.eclipse.e4.data");
  }
  
  private void subscribe(String topic, EventAdmin eventAdmin, IRequestor requestor)
  {
    Subscriber subscriber = new Subscriber(requestor, topic);
    synchronized (registrations)
    {
      if (registrations.containsKey(subscriber)) {
        return;
      }
    }
    BundleContext bundleContext = DIEActivator.getDefault().getBundleContext();
    if (bundleContext == null) {
      throw new InjectionException("Unable to subscribe to events: org.eclipse.e4.core.di.extensions bundle is not activated");
    }
    String[] topics = { topic };
    Dictionary<String, Object> d = new Hashtable();
    d.put("event.topics", topics);
    EventHandler wrappedHandler = makeHandler(topic, requestor);
    ServiceRegistration registration = bundleContext.registerService(EventHandler.class.getName(), wrappedHandler, d);
    synchronized (registrations)
    {
      registrations.put(subscriber, registration);
    }
  }
  
  protected EventHandler makeHandler(String topic, IRequestor requestor)
  {
    return new DIEventHandler(topic, requestor);
  }
  
  protected String getTopic(IObjectDescriptor descriptor)
  {
    if (descriptor == null) {
      return null;
    }
    EventTopic qualifier = (EventTopic)descriptor.getQualifier(EventTopic.class);
    return qualifier.value();
  }
  
  private static EventAdmin getEventAdmin()
  {
    return DIEActivator.getDefault().getEventAdmin();
  }
  
  protected void unsubscribe(IRequestor requestor)
  {
    if (requestor == null) {
      return;
    }
    synchronized (registrations)
    {
      Iterator<Map.Entry<Subscriber, ServiceRegistration>> i = registrations.entrySet().iterator();
      while (i.hasNext())
      {
        Map.Entry<Subscriber, ServiceRegistration> entry = (Map.Entry)i.next();
        Subscriber key = (Subscriber)entry.getKey();
        if (requestor.equals(key.getRequestor()))
        {
          ServiceRegistration registration = (ServiceRegistration)entry.getValue();
          registration.unregister();
          i.remove();
        }
      }
    }
  }
  
  @PreDestroy
  public void dispose()
  {
    synchronized (registrations)
    {
      Collection<ServiceRegistration> values = registrations.values();
      ServiceRegistration[] array = (ServiceRegistration[])values.toArray(new ServiceRegistration[values.size()]);
      registrations.clear();
    }
    ServiceRegistration[] array;
    for (int i = 0; i < array.length; i++) {
      array[i].unregister();
    }
  }
  
  private Class<?> getDesiredClass(Type desiredType)
  {
    if ((desiredType instanceof Class)) {
      return (Class)desiredType;
    }
    if ((desiredType instanceof ParameterizedType))
    {
      Type rawType = ((ParameterizedType)desiredType).getRawType();
      if ((rawType instanceof Class)) {
        return (Class)rawType;
      }
    }
    return null;
  }
}

/* Location:
 * Qualified Name:     org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier
 * Java Class Version: 5 (49.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.e4.core.di.internal.extensions;

import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.e4.core.di.suppliers.IRequestor;

class PreferencesObjectSupplier$PrefInjectionListener
  implements IEclipsePreferences.IPreferenceChangeListener
{
  private final IRequestor requestor;
  private final IEclipsePreferences node;
  
  public PreferencesObjectSupplier$PrefInjectionListener(IEclipsePreferences node, IRequestor requestor)
  {
    this.node = node;
    this.requestor = requestor;
  }
  
  public void preferenceChange(IEclipsePreferences.PreferenceChangeEvent event)
  {
    if (!requestor.isValid())
    {
      node.removePreferenceChangeListener(this);
      return;
    }
    requestor.resolveArguments(false);
    requestor.execute();
  }
  
  public IRequestor getRequestor()
  {
    return requestor;
  }
  
  public void stopListening()
  {
    node.removePreferenceChangeListener(this);
  }
}

/* Location:
 * Qualified Name:     org.eclipse.e4.core.di.internal.extensions.PreferencesObjectSupplier.PrefInjectionListener
 * Java Class Version: 5 (49.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.e4.core.di.internal.extensions;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.e4.core.di.IInjector;
import org.eclipse.e4.core.di.extensions.Preference;
import org.eclipse.e4.core.di.suppliers.ExtendedObjectSupplier;
import org.eclipse.e4.core.di.suppliers.IObjectDescriptor;
import org.eclipse.e4.core.di.suppliers.IRequestor;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;

public class PreferencesObjectSupplier
  extends ExtendedObjectSupplier
{
  private static class PrefInjectionListener
    implements IEclipsePreferences.IPreferenceChangeListener
  {
    private final IRequestor requestor;
    private final IEclipsePreferences node;
    
    public PrefInjectionListener(IEclipsePreferences node, IRequestor requestor)
    {
      this.node = node;
      this.requestor = requestor;
    }
    
    public void preferenceChange(IEclipsePreferences.PreferenceChangeEvent event)
    {
      if (!requestor.isValid())
      {
        node.removePreferenceChangeListener(this);
        return;
      }
      requestor.resolveArguments(false);
      requestor.execute();
    }
    
    public IRequestor getRequestor()
    {
      return requestor;
    }
    
    public void stopListening()
    {
      node.removePreferenceChangeListener(this);
    }
  }
  
  private Map<String, List<PrefInjectionListener>> listenerCache = new HashMap();
  
  public PreferencesObjectSupplier()
  {
    DIEActivator.getDefault().registerPreferencesSupplier(this);
  }
  
  public Object get(IObjectDescriptor descriptor, IRequestor requestor, boolean track, boolean group)
  {
    if (descriptor == null) {
      return null;
    }
    Class<?> descriptorsClass = getDesiredClass(descriptor.getDesiredType());
    String nodePath = getNodePath(descriptor, requestor.getRequestingObjectClass());
    if (IEclipsePreferences.class.equals(descriptorsClass)) {
      return InstanceScope.INSTANCE.getNode(nodePath);
    }
    String key = getKey(descriptor);
    if ((key == null) || (nodePath == null) || (key.length() == 0) || (nodePath.length() == 0)) {
      return IInjector.NOT_A_VALUE;
    }
    if (track) {
      addListener(nodePath, requestor);
    }
    if (descriptorsClass.isPrimitive())
    {
      if (descriptorsClass.equals(Boolean.TYPE)) {
        return Boolean.valueOf(getPreferencesService().getBoolean(nodePath, key, false, null));
      }
      if (descriptorsClass.equals(Integer.TYPE)) {
        return Integer.valueOf(getPreferencesService().getInt(nodePath, key, 0, null));
      }
      if (descriptorsClass.equals(Double.TYPE)) {
        return Double.valueOf(getPreferencesService().getDouble(nodePath, key, 0.0D, null));
      }
      if (descriptorsClass.equals(Float.TYPE)) {
        return Float.valueOf(getPreferencesService().getFloat(nodePath, key, 0.0F, null));
      }
      if (descriptorsClass.equals(Long.TYPE)) {
        return Long.valueOf(getPreferencesService().getLong(nodePath, key, 0L, null));
      }
    }
    if (String.class.equals(descriptorsClass)) {
      return getPreferencesService().getString(nodePath, key, null, null);
    }
    if (Boolean.class.equals(descriptorsClass)) {
      return Boolean.valueOf(getPreferencesService().getBoolean(nodePath, key, false, null));
    }
    if (Boolean.class.equals(descriptorsClass)) {
      return Boolean.valueOf(getPreferencesService().getBoolean(nodePath, key, false, null));
    }
    if (Integer.class.equals(descriptorsClass)) {
      return Integer.valueOf(getPreferencesService().getInt(nodePath, key, 0, null));
    }
    if (Double.class.equals(descriptorsClass)) {
      return Double.valueOf(getPreferencesService().getDouble(nodePath, key, 0.0D, null));
    }
    if (Float.class.equals(descriptorsClass)) {
      return Float.valueOf(getPreferencesService().getFloat(nodePath, key, 0.0F, null));
    }
    if (Long.class.equals(descriptorsClass)) {
      return Long.valueOf(getPreferencesService().getLong(nodePath, key, 0L, null));
    }
    return getPreferencesService().getString(nodePath, key, null, null);
  }
  
  private Class<?> getDesiredClass(Type desiredType)
  {
    if ((desiredType instanceof Class)) {
      return (Class)desiredType;
    }
    if ((desiredType instanceof ParameterizedType))
    {
      Type rawType = ((ParameterizedType)desiredType).getRawType();
      if ((rawType instanceof Class)) {
        return (Class)rawType;
      }
    }
    return null;
  }
  
  private String getKey(IObjectDescriptor descriptor)
  {
    if (descriptor == null) {
      return null;
    }
    Preference qualifier = (Preference)descriptor.getQualifier(Preference.class);
    return qualifier.value();
  }
  
  private String getNodePath(IObjectDescriptor descriptor, Class<?> requestingObject)
  {
    if (descriptor == null) {
      return null;
    }
    Preference qualifier = (Preference)descriptor.getQualifier(Preference.class);
    String nodePath = qualifier.nodePath();
    if ((nodePath == null) || (nodePath.length() == 0))
    {
      if (requestingObject == null) {
        return null;
      }
      nodePath = FrameworkUtil.getBundle(requestingObject).getSymbolicName();
    }
    return nodePath;
  }
  
  private IPreferencesService getPreferencesService()
  {
    return DIEActivator.getDefault().getPreferencesService();
  }
  
  private void addListener(String nodePath, IRequestor requestor)
  {
    if (requestor == null) {
      return;
    }
    synchronized (listenerCache)
    {
      if (listenerCache.containsKey(nodePath)) {
        for (PrefInjectionListener listener : (List)listenerCache.get(nodePath))
        {
          IRequestor previousRequestor = listener.getRequestor();
          if (previousRequestor.equals(requestor)) {
            return;
          }
        }
      }
    }
    IEclipsePreferences node = InstanceScope.INSTANCE.getNode(nodePath);
    PrefInjectionListener listener = new PrefInjectionListener(node, requestor);
    node.addPreferenceChangeListener(listener);
    synchronized (listenerCache)
    {
      if (listenerCache.containsKey(nodePath))
      {
        ((List)listenerCache.get(nodePath)).add(listener);
      }
      else
      {
        List<PrefInjectionListener> listeningRequestors = new ArrayList();
        listeningRequestors.add(listener);
        listenerCache.put(nodePath, listeningRequestors);
      }
    }
  }
  
  public void removeAllListeners()
  {
    synchronized (listenerCache)
    {
      for (List<PrefInjectionListener> listeners : listenerCache.values()) {
        if (listeners != null) {
          for (PrefInjectionListener listener : listeners) {
            listener.stopListening();
          }
        }
      }
      listenerCache.clear();
    }
  }
}

/* Location:
 * Qualified Name:     org.eclipse.e4.core.di.internal.extensions.PreferencesObjectSupplier
 * Java Class Version: 5 (49.0)
 * JD-Core Version:    0.7.1
 */
1

Further reading...

For more information on Java 1.5 Tiger, you may find Java 1.5 Tiger, A developer's Notebook by D. Flanagan and B. McLaughlin from O'Reilly of interest.

New!JAR listings


Copyright 2006-2017. Infinite Loop Ltd