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 }