View Javadoc

1   /*
2    * Grapht, an open source dependency injector.
3    * Copyright 2014-2015 various contributors (see CONTRIBUTORS.txt)
4    * Copyright 2010-2014 Regents of the University of Minnesota
5    *
6    * This program is free software; you can redistribute it and/or modify
7    * it under the terms of the GNU Lesser General Public License as
8    * published by the Free Software Foundation; either version 2.1 of the
9    * License, or (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14   * details.
15   *
16   * You should have received a copy of the GNU General Public License along with
17   * this program; if not, write to the Free Software Foundation, Inc., 51
18   * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19   */
20  package org.grouplens.grapht.util;
21  
22  import javax.annotation.Nullable;
23  import java.io.InvalidObjectException;
24  import java.io.ObjectStreamException;
25  import java.io.Serializable;
26  
27  /**
28   * InstanceProvider is a simple Provider that always provides the same instance.
29   * 
30   * @author <a href="http://grouplens.org">GroupLens Research</a>
31   * @param <T>
32   */
33  public class InstanceProvider<T> implements TypedProvider<T>, Serializable {
34      private static final long serialVersionUID = -1L;
35  
36      private final Class<?> providedType;
37      private final transient T instance; // transient because serialization proxy takes care of it
38  
39      /**
40       * Construct a new instance provider.
41       * @param instance The instance.
42       * @deprecated Use {@link Providers#of(Object)} instead.
43       */
44      @SuppressWarnings("unused")
45      @Deprecated
46      public InstanceProvider(T instance) {
47          this(instance, instance == null ? Object.class : instance.getClass());
48      }
49  
50      InstanceProvider(@Nullable T instance, Class<?> type) {
51          if (instance != null && !type.isInstance(instance)) {
52              throw new IllegalArgumentException("instance not of specified type");
53          }
54          this.instance = instance;
55          providedType = type;
56      }
57  
58      @Override
59      public Class<?> getProvidedType() {
60          return providedType;
61      }
62  
63      @Override
64      public T get() {
65          return instance;
66      }
67  
68      @Override
69      public String toString() {
70          if (instance == null) {
71              return "InstanceProvider{null<" + providedType.getName() + ">}";
72          } else {
73              return "InstanceProvider{" + instance + "}";
74          }
75      }
76  
77      private Object writeReplace() {
78          return new SerialProxy(providedType,  instance);
79      }
80  
81      @SuppressWarnings("unused")
82      private Object readObject() throws ObjectStreamException {
83          throw new InvalidObjectException("must use serialization proxy");
84      }
85  
86      private static class SerialProxy implements Serializable {
87          private static final long serialVersionUID = 1L;
88          private ClassProxy type;
89          @SuppressWarnings("squid:S1948") // serializable warning; node is serializable iff its label type is
90          private Object instance;
91  
92          public SerialProxy(Class<?> t, Object i) {
93              type = ClassProxy.of(t);
94              instance = i;
95          }
96  
97          @SuppressWarnings("unchecked")
98          private Object readResolve() throws ObjectStreamException {
99              Class<?> cls;
100             try {
101                 cls = type.resolve();
102             } catch (ClassNotFoundException e) {
103                 InvalidObjectException ex = new InvalidObjectException("class not found");
104                 ex.initCause(e);
105                 throw ex;
106             }
107             if (instance != null && !cls.isInstance(instance)) {
108                 throw new InvalidObjectException("instance is not of expected type");
109             }
110             return new InstanceProvider(instance, cls);
111         }
112     }
113 }