All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.tidalwave.netbeans.util.test.MockLookup Maven / Gradle / Ivy

There is a newer version: 1.0.62
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common
 * Development and Distribution License("CDDL") (collectively, the
 * "License"). You may not use this file except in compliance with the
 * License. You can obtain a copy of the License at
 * http://www.netbeans.org/cddl-gplv2.html
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 * specific language governing permissions and limitations under the
 * License.  When distributing the software, include this License Header
 * Notice in each file and include the License file at
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the GPL Version 2 section of the License file that
 * accompanied this code. If applicable, add the following below the
 * License Header, with the fields enclosed by brackets [] replaced by
 * your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Contributor(s):
 *
 * The Original Software is NetBeans. The Initial Developer of the Original
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
 * Microsystems, Inc. All Rights Reserved.
 *
 * If you wish your version of this file to be governed by only the CDDL
 * or only the GPL Version 2, indicate your decision by adding
 * "[Contributor] elects to include this software in this distribution
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 * single choice of license, a recipient has the option to distribute
 * your version of this file under either the CDDL, the GPL Version 2 or
 * to extend the choice of license to its licensees as provided above.
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 * Version 2 license, then the option applies only if the new code is
 * made subject to such option by the copyright holder.
 */

package it.tidalwave.netbeans.util.test;

import javax.annotation.Nonnull;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.openide.util.Lookup;
import org.openide.util.LookupListener;
import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ProxyLookup;
import static org.junit.Assert.*;

/**
 * Mock implementation of system default lookup suitable for use in unit tests.
 * The initial value just contains classpath services.
 */
public class MockLookup extends ProxyLookup
  {
    private static MockLookup DEFAULT;
    private static boolean making = false;

    private static Set BANNED_OBJECTS = new HashSet();

    private static Lookup METAINF_LOOKUP = Lookup.EMPTY;
    
    private static final Lookup FILTERED_METAINF_LOOKUP = new Lookup()
      {
        @Override
        public  T lookup (final @Nonnull Class clazz)
          {
            final Collection allInstances = lookup(new Template(clazz)).allInstances();
            return (allInstances.isEmpty()) ? null : allInstances.iterator().next();
          }

        @Override
        public  Result lookup (final @Nonnull Template template)
          {
            final Result result = METAINF_LOOKUP.lookup(template);
            return new Result()
              {
                @Override
                public void addLookupListener (final LookupListener listener)
                  {
                    result.addLookupListener(listener);
                  }

                @Override
                public void removeLookupListener (final LookupListener listener)
                  {
                    result.removeLookupListener(listener);
                  }

                @Override
                public Collection allInstances()
                  {
                    final Collection allInstances = new ArrayList(result.allInstances());
                    allInstances.removeAll(BANNED_OBJECTS);
                    return allInstances;
                  }
              };
          }
      };

    static
      {
        making = true;

        try
          {
            System.setProperty("org.openide.util.Lookup", MockLookup.class.getName());

            if (Lookup.getDefault().getClass() != MockLookup.class)
              {
                // Someone else initialized lookup first. Try to force our way.
                Field defaultLookup = Lookup.class.getDeclaredField("defaultLookup");
                defaultLookup.setAccessible(true);
                defaultLookup.set(null, null);
              }
            
            assertEquals(MockLookup.class, Lookup.getDefault().getClass());
          }
        catch (Exception x)
          {
            throw new ExceptionInInitializerError(x);
          }
        finally
          {
            making = false;
          }
      }

    /** Do not call this directly! */
    public MockLookup()
      {
        assertTrue(making);
        assertNull(DEFAULT);
        DEFAULT = this;
        setInstances();
      }

    /**
     * Just ensures that this lookup is default lookup, but does not actually change its content.
     * Useful mainly if you have some test utility method which calls foreign code which might use default lookup,
     * and you want to ensure that any users of mock lookup will see the correct default lookup right away,
     * even if they have not yet called {@link #setLookup} or {@link #setInstances}.
     */
    public static void init() 
      {
      }

    public static void reset()
      {
        BANNED_OBJECTS.clear();
        setInstances();
      }

    /**
     * Sets the global default lookup with zero or more delegate lookups.
     * Caution: if you don't include Lookups.metaInfServices, you may have trouble,
     * e.g. {@link #makeScratchDir} will not work.
     * Most of the time you should use {@link #setInstances} instead.
     */
    public static void setLookup (final @Nonnull Lookup... lookups)
      {
        DEFAULT.setLookups(lookups);
      }

    /**
     * Sets the global default lookup with some fixed instances.
     * Will also include (at a lower priority) a {@link ClassLoader},
     * and services found from META-INF/services/* in the classpath.
     */
    public static void setInstances (final @Nonnull Object... instances)
      {
        final ClassLoader l = MockLookup.class.getClassLoader();
        METAINF_LOOKUP = Lookups.metaInfServices(l);
        setLookup(Lookups.fixed(instances), FILTERED_METAINF_LOOKUP, Lookups.singleton(l));
      }

    public static void addBannedObject (final @Nonnull Object bannedObject)
      {
        BANNED_OBJECTS.add(bannedObject);
      }
  }