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 }