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.reflect.internal;
21  
22  import org.apache.commons.lang3.builder.EqualsBuilder;
23  import org.apache.commons.lang3.builder.HashCodeBuilder;
24  import org.grouplens.grapht.reflect.Desires;
25  import org.grouplens.grapht.reflect.InjectionPoint;
26  import org.grouplens.grapht.util.ClassProxy;
27  import org.grouplens.grapht.util.Preconditions;
28  
29  import javax.annotation.Nonnull;
30  import javax.annotation.Nullable;
31  import java.io.InvalidObjectException;
32  import java.io.ObjectInputStream;
33  import java.io.ObjectStreamException;
34  import java.io.Serializable;
35  import java.lang.annotation.Annotation;
36  import java.lang.reflect.Member;
37  import java.util.Collection;
38  import java.util.Collections;
39  
40  /**
41   * Synthetic injection point used for {@link Desires#create(java.lang.annotation.Annotation, Class, boolean)}.
42   *
43   * @author <a href="http://grouplens.org">GroupLens Research</a>
44   */
45  
46  public final class SimpleInjectionPoint implements InjectionPoint, Serializable {
47      private static final long serialVersionUID = -1L;
48      // fields marked as transient since direct serialization is disabled
49      private final transient Annotation qualifier;
50      private final transient Class<?> type;
51      private final transient boolean nullable;
52  
53      public SimpleInjectionPoint(@Nullable Annotation qualifier, Class<?> type, boolean nullable) {
54          Preconditions.notNull("type", type);
55          if (qualifier != null) {
56              Preconditions.isQualifier(qualifier.annotationType());
57          }
58          this.qualifier = qualifier;
59          this.type = type;
60          this.nullable = nullable;
61      }
62  
63      @Override
64      public Class<?> getErasedType() {
65          return type;
66      }
67  
68      @Override
69      public Member getMember() {
70          return null;
71      }
72  
73      @Override
74      public boolean isNullable() {
75          return nullable;
76      }
77  
78      @Override
79      public Class<?> getType() {
80          return type;
81      }
82  
83      @Nullable
84      @Override
85      public Annotation getQualifier() {
86          return qualifier;
87      }
88  
89      @Nullable
90      @Override
91      public <A extends Annotation> A getAttribute(Class<A> atype) {
92          return null;
93      }
94  
95      @Nonnull
96      @Override
97      public Collection<Annotation> getAttributes() {
98          return Collections.emptyList();
99      }
100 
101     @Override
102     public int hashCode() {
103         return new HashCodeBuilder().append(type).append(qualifier).toHashCode();
104     }
105 
106     @Override
107     public boolean equals(Object o) {
108         if (!(o instanceof SimpleInjectionPoint)) {
109             return false;
110         }
111         SimpleInjectionPoint p = (SimpleInjectionPoint) o;
112         EqualsBuilder eqb = new EqualsBuilder();
113         return eqb.append(type, p.type)
114                   .append(qualifier, p.qualifier)
115                   .append(nullable, p.nullable)
116                   .isEquals();
117     }
118 
119     @Override
120     public String toString() {
121         StringBuilder sb = new StringBuilder();
122         sb.append("synthetic ");
123         if (qualifier != null) {
124             sb.append(qualifier)
125               .append(" ");
126         }
127         return sb.append(type.getName()).toString();
128     }
129 
130     private Object writeReplace() {
131         return new SerialProxy(type, nullable, qualifier);
132     }
133 
134     private void readObject(ObjectInputStream stream) throws InvalidObjectException {
135         throw new InvalidObjectException("Serialization proxy required");
136     }
137 
138     /**
139      * Serialization proxy for the Serialization Proxy Pattern.
140      */
141     private static class SerialProxy implements Serializable {
142         private static final long serialVersionUID = 1L;
143         private ClassProxy type;
144         private boolean nullable;
145         @Nullable
146         @SuppressWarnings("squid:S1948") // serializable - annotations are serializable
147         private Annotation qualifier;
148 
149         private SerialProxy(Class<?> t, boolean isNullable, @Nullable Annotation qual) {
150             type = ClassProxy.of(t);
151             nullable = isNullable;
152             qualifier = qual;
153         }
154 
155         public Object readResolve() throws ObjectStreamException {
156             try {
157                 return Desires.createInjectionPoint(qualifier, type.resolve(), nullable);
158             } catch (ClassNotFoundException e) {
159                 InvalidObjectException ex =
160                         new InvalidObjectException("cannot resolve class " + type.getClassName());
161                 ex.initCause(e);
162                 throw ex;
163             }
164         }
165     }
166 }