View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    * 
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   * 
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package net.jini.core.lookup;
19  
20  import java.io.IOException;
21  import java.io.ObjectOutputStream;
22  import net.jini.core.entry.CloneableEntry;
23  import net.jini.core.entry.Entry;
24  import org.apache.river.api.io.AtomicSerial;
25  import org.apache.river.api.io.AtomicSerial.GetArg;
26  
27  /**
28   * Items in the lookup service are matched using instance of this class.
29   * A service item (item) matches a service template (tmpl) if:
30   * item.serviceID equals tmpl.serviceID (or if tmpl.serviceID is null);
31   * and item.service is an instance of every type in tmpl.serviceTypes; and
32   * item.attributeSets contains at least one matching entry for each entry
33   * template in tmpl.attributeSetTemplates.
34   * <p>
35   * An entry matches
36   * an entry template if the class of the template is the same as, or a
37   * superclass of, the class of the entry, and every non-null field in the
38   * template equals the corresponding field of the entry.  Every entry can be
39   * used to match more than one template.  Note that in a service template,
40   * for serviceTypes and attributeSetTemplates, a null field is equivalent to
41   * an empty array; both represent a wildcard.
42   *
43   * @author Sun Microsystems, Inc.
44   *
45   * @since 1.0
46   */
47  @AtomicSerial
48  public class ServiceTemplate implements java.io.Serializable, Cloneable {
49  
50      private static final long serialVersionUID = 7854483807886483216L;
51  
52      /**
53       * Service ID to match, or <tt>null</tt>.
54       *
55       * @serial
56       */
57      public ServiceID serviceID;
58      /**
59       * Service types to match, or <tt>null</tt>.
60       *
61       * @serial
62       */
63      public Class[] serviceTypes;
64      /**
65       * Attribute set templates to match, or <tt>null</tt>.
66       *
67       * @serial
68       */
69      public Entry[] attributeSetTemplates;
70      
71      /**
72       * Constructor for @AtomicSerial, note that any instances of this
73       * should be cloned in a secure stream to prevent an attacker retaining 
74       * a reference to mutable state.
75       * 
76       * @param arg atomic deserialization parameter 
77       * @throws IOException if there are I/O errors while reading from GetArg's
78       *         underlying <code>InputStream</code>
79       */
80      public ServiceTemplate(GetArg arg) throws IOException {
81  	/* Any class cast exceptions will be occur before Object's default
82  	 * constructor is called, in that case an instance of this object
83  	 * will not be created.
84  	 * null check for org/apache/river/test/spec/lookupservice/ToStringTest.td
85  	 */
86  	this(arg == null ? null: arg.get("serviceID", null, ServiceID.class),
87  	    arg == null? null: arg.get("serviceTypes", null, Class[].class),
88  	    arg == null? null: arg.get("attributeSetTemplates", null, Entry[].class)
89  	);
90      }
91      
92  
93      /**
94       * Simple constructor.
95       *
96       * @param serviceID service ID to match, or null
97       * @param serviceTypes service types to match, or null
98       * @param attrSetTemplates attribute set templates to match, or null
99       */
100     public ServiceTemplate(ServiceID serviceID,
101 			   Class[] serviceTypes,
102 			   Entry[] attrSetTemplates) 
103     {
104 	this.serviceID = serviceID;
105 	this.serviceTypes = serviceTypes;
106 	this.attributeSetTemplates = attrSetTemplates;
107     }
108     
109     /**
110      * Clone has been implemented to allow utilities such as
111      * <code> net.jini.lookup.ServiceDiscoveryManager </code> to avoid sharing 
112      * internally stored instances with client code.
113      * 
114      * @return a clone of the original ServiceTemplate
115      */
116     @Override
117     public ServiceTemplate clone() 
118     {
119         try {
120             ServiceTemplate clone = (ServiceTemplate) super.clone();
121 	    if (clone.serviceTypes != null){
122 		clone.serviceTypes = clone.serviceTypes.clone();
123 	    }
124 	    if (clone.attributeSetTemplates != null){
125 		clone.attributeSetTemplates = clone.attributeSetTemplates.clone();
126 		for (int i = 0, l = clone.attributeSetTemplates.length; i < l; i++){
127 		    Entry e = clone.attributeSetTemplates[i];
128 		    if (e instanceof CloneableEntry){
129 			clone.attributeSetTemplates[i] = ((CloneableEntry) e).clone();
130 		    }
131 		}
132 	    }
133             return clone;
134         } catch (CloneNotSupportedException ex) {
135             throw new AssertionError();
136         }
137     }
138     
139     /**
140      * Returns a <code>String</code> representation of this 
141      * <code>ServiceTemplate</code>.
142      * @return <code>String</code> representation of this 
143      * <code>ServiceTemplate</code>
144      */
145     public String toString() {
146 	StringBuilder sBuffer = new StringBuilder();
147 	sBuffer.append(
148 	       getClass().getName()).append(
149 	       "[serviceID=").append(
150 	       serviceID).append(
151 	       ", serviceTypes=");
152 	if (serviceTypes != null) {
153             sBuffer.append("[");
154             if (serviceTypes.length > 0) {
155                 for (int i = 0; i < serviceTypes.length - 1; i++)
156                     sBuffer.append(serviceTypes[i]).append(" ");
157                 sBuffer.append(serviceTypes[serviceTypes.length - 1]);
158             }
159             sBuffer.append("]");
160 	} else {
161 	    sBuffer.append((Object)null);
162 	}
163 	sBuffer.append(", attributeSetTemplates=");
164 	if (attributeSetTemplates != null) {
165             sBuffer.append("[");
166             if (attributeSetTemplates.length > 0) {
167                 for (int i = 0; i < attributeSetTemplates.length - 1; i++)
168                     sBuffer.append(attributeSetTemplates[i]).append(" ");
169                 sBuffer.append(
170                     attributeSetTemplates[attributeSetTemplates.length - 1]);
171             }
172             sBuffer.append("]");
173 	} else {
174 	    sBuffer.append((Object)null);
175 	}
176 	return sBuffer.append("]").toString();
177     }
178             
179     private void writeObject(ObjectOutputStream out) throws IOException {
180 	out.defaultWriteObject();
181 }
182 }