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       * @throws java.lang.ClassNotFoundException
80       */
81      public ServiceTemplate(GetArg arg) throws IOException, ClassNotFoundException {
82  	/* Any class cast exceptions will be occur before Object's default
83  	 * constructor is called, in that case an instance of this object
84  	 * will not be created.
85  	 * null check for org/apache/river/test/spec/lookupservice/ToStringTest.td
86  	 */
87  	this(arg == null ? null: arg.get("serviceID", null, ServiceID.class),
88  	    arg == null? null: arg.get("serviceTypes", null, Class[].class),
89  	    arg == null? null: arg.get("attributeSetTemplates", null, Entry[].class)
90  	);
91      }
92      
93  
94      /**
95       * Simple constructor.
96       *
97       * @param serviceID service ID to match, or null
98       * @param serviceTypes service types to match, or null
99       * @param attrSetTemplates attribute set templates to match, or null
100      */
101     public ServiceTemplate(ServiceID serviceID,
102 			   Class[] serviceTypes,
103 			   Entry[] attrSetTemplates) 
104     {
105 	this.serviceID = serviceID;
106 	this.serviceTypes = serviceTypes;
107 	this.attributeSetTemplates = attrSetTemplates;
108     }
109     
110     /**
111      * Clone has been implemented to allow utilities such as
112      * <code> net.jini.lookup.ServiceDiscoveryManager </code> to avoid sharing 
113      * internally stored instances with client code.
114      * 
115      * @return a clone of the original ServiceTemplate
116      */
117     @Override
118     public ServiceTemplate clone() 
119     {
120         try {
121             ServiceTemplate clone = (ServiceTemplate) super.clone();
122 	    if (clone.serviceTypes != null){
123 		clone.serviceTypes = clone.serviceTypes.clone();
124 	    }
125 	    if (clone.attributeSetTemplates != null){
126 		clone.attributeSetTemplates = clone.attributeSetTemplates.clone();
127 		for (int i = 0, l = clone.attributeSetTemplates.length; i < l; i++){
128 		    Entry e = clone.attributeSetTemplates[i];
129 		    if (e instanceof CloneableEntry){
130 			clone.attributeSetTemplates[i] = ((CloneableEntry) e).clone();
131 		    }
132 		}
133 	    }
134             return clone;
135         } catch (CloneNotSupportedException ex) {
136             throw new AssertionError();
137         }
138     }
139     
140     /**
141      * Returns a <code>String</code> representation of this 
142      * <code>ServiceTemplate</code>.
143      * @return <code>String</code> representation of this 
144      * <code>ServiceTemplate</code>
145      */
146     public String toString() {
147 	StringBuilder sBuffer = new StringBuilder();
148 	sBuffer.append(
149 	       getClass().getName()).append(
150 	       "[serviceID=").append(
151 	       serviceID).append(
152 	       ", serviceTypes=");
153 	if (serviceTypes != null) {
154             sBuffer.append("[");
155             if (serviceTypes.length > 0) {
156                 for (int i = 0; i < serviceTypes.length - 1; i++)
157                     sBuffer.append(serviceTypes[i]).append(" ");
158                 sBuffer.append(serviceTypes[serviceTypes.length - 1]);
159             }
160             sBuffer.append("]");
161 	} else {
162 	    sBuffer.append((Object)null);
163 	}
164 	sBuffer.append(", attributeSetTemplates=");
165 	if (attributeSetTemplates != null) {
166             sBuffer.append("[");
167             if (attributeSetTemplates.length > 0) {
168                 for (int i = 0; i < attributeSetTemplates.length - 1; i++)
169                     sBuffer.append(attributeSetTemplates[i]).append(" ");
170                 sBuffer.append(
171                     attributeSetTemplates[attributeSetTemplates.length - 1]);
172             }
173             sBuffer.append("]");
174 	} else {
175 	    sBuffer.append((Object)null);
176 	}
177 	return sBuffer.append("]").toString();
178     }
179             
180     private void writeObject(ObjectOutputStream out) throws IOException {
181 	out.defaultWriteObject();
182 }
183 }