47 * @since 1.2
48 *
49 *
50 * @see Signature
51 */
52
53 public abstract class SignatureSpi {
54
55 /**
56 * Application-specified source of randomness.
57 */
58 protected SecureRandom appRandom = null;
59
60 /**
61 * Initializes this signature object with the specified
62 * public key for verification operations.
63 *
64 * @param publicKey the public key of the identity whose signature is
65 * going to be verified.
66 *
67 * @exception InvalidKeyException if the key is improperly
68 * encoded, parameters are missing, and so on.
69 */
70 protected abstract void engineInitVerify(PublicKey publicKey)
71 throws InvalidKeyException;
72
73 /**
74 * Initializes this signature object with the specified
75 * public key for verification operations.
76 *
77 * @param publicKey the public key of the identity whose signature is
78 * going to be verified.
79 * @param params the parameters for generating this signature
80 *
81 * @exception InvalidKeyException if the key is improperly
82 * encoded, does not work with the given parameters, and so on.
83 * @exception InvalidAlgorithmParameterException if the given parameters
84 * is invalid.
85 */
86 void engineInitVerify(PublicKey publicKey,
87 AlgorithmParameterSpec params)
88 throws InvalidKeyException, InvalidAlgorithmParameterException {
89 if (params != null) {
90 try {
91 engineSetParameter(params);
92 } catch (UnsupportedOperationException usoe) {
93 // error out if not overrridden
94 throw new InvalidAlgorithmParameterException(usoe);
95 }
96 }
97 engineInitVerify(publicKey);
98 }
99
100 /**
101 * Initializes this signature object with the specified
102 * private key for signing operations.
103 *
104 * @param privateKey the private key of the identity whose signature
105 * will be generated.
106 *
107 * @exception InvalidKeyException if the key is improperly
108 * encoded, parameters are missing, and so on.
109 */
110 protected abstract void engineInitSign(PrivateKey privateKey)
111 throws InvalidKeyException;
112
113 /**
114 * Initializes this signature object with the specified
115 * private key and source of randomness for signing operations.
116 *
117 * <p>This concrete method has been added to this previously-defined
118 * abstract class. (For backwards compatibility, it cannot be abstract.)
119 *
120 * @param privateKey the private key of the identity whose signature
121 * will be generated.
122 * @param random the source of randomness
123 *
124 * @exception InvalidKeyException if the key is improperly
125 * encoded, parameters are missing, and so on.
126 */
127 protected void engineInitSign(PrivateKey privateKey,
128 SecureRandom random)
129 throws InvalidKeyException {
130 this.appRandom = random;
131 engineInitSign(privateKey);
132 }
133
134 /**
135 * Initializes this signature object with the specified
136 * private key and source of randomness for signing operations.
137 *
138 * <p>This concrete method has been added to this previously-defined
139 * abstract class. (For backwards compatibility, it cannot be abstract.)
140 *
141 * @param privateKey the private key of the identity whose signature
142 * will be generated.
143 * @param params the parameters for generating this signature
144 * @param random the source of randomness
145 *
146 * @exception InvalidKeyException if the key is improperly
147 * encoded, parameters are missing, and so on.
148 * @exception InvalidAlgorithmParameterException if the parameters is
149 * invalid.
150 */
151 void engineInitSign(PrivateKey privateKey,
152 AlgorithmParameterSpec params, SecureRandom random)
153 throws InvalidKeyException, InvalidAlgorithmParameterException {
154 if (params != null) {
155 try {
156 engineSetParameter(params);
157 } catch (UnsupportedOperationException usoe) {
158 // error out if not overrridden
159 throw new InvalidAlgorithmParameterException(usoe);
160 }
161 }
162 engineInitSign(privateKey, random);
163 }
164
165 /**
166 * Updates the data to be signed or verified
167 * using the specified byte.
168 *
169 * @param b the byte to use for the update.
170 *
171 * @exception SignatureException if the engine is not initialized
172 * properly.
173 */
174 protected abstract void engineUpdate(byte b) throws SignatureException;
175
176 /**
177 * Updates the data to be signed or verified, using the
178 * specified array of bytes, starting at the specified offset.
179 *
180 * @param b the array of bytes
181 * @param off the offset to start from in the array of bytes
182 * @param len the number of bytes to use, starting at offset
183 *
184 * @exception SignatureException if the engine is not initialized
185 * properly
186 */
187 protected abstract void engineUpdate(byte[] b, int off, int len)
188 throws SignatureException;
189
190 /**
191 * Updates the data to be signed or verified using the specified
192 * ByteBuffer. Processes the {@code data.remaining()} bytes
193 * starting at {@code data.position()}.
194 * Upon return, the buffer's position will be equal to its limit;
195 * its limit will not have changed.
196 *
197 * @param input the ByteBuffer
198 * @since 1.5
199 */
200 protected void engineUpdate(ByteBuffer input) {
201 if (input.hasRemaining() == false) {
202 return;
203 }
204 try {
217 input.get(b, 0, chunk);
218 engineUpdate(b, 0, chunk);
219 len -= chunk;
220 }
221 }
222 } catch (SignatureException e) {
223 // is specified to only occur when the engine is not initialized
224 // this case should never occur as it is caught in Signature.java
225 throw new ProviderException("update() failed", e);
226 }
227 }
228
229 /**
230 * Returns the signature bytes of all the data
231 * updated so far.
232 * The format of the signature depends on the underlying
233 * signature scheme.
234 *
235 * @return the signature bytes of the signing operation's result.
236 *
237 * @exception SignatureException if the engine is not
238 * initialized properly or if this signature algorithm is unable to
239 * process the input data provided.
240 */
241 protected abstract byte[] engineSign() throws SignatureException;
242
243 /**
244 * Finishes this signature operation and stores the resulting signature
245 * bytes in the provided buffer {@code outbuf}, starting at
246 * {@code offset}.
247 * The format of the signature depends on the underlying
248 * signature scheme.
249 *
250 * <p>The signature implementation is reset to its initial state
251 * (the state it was in after a call to one of the
252 * {@code engineInitSign} methods)
253 * and can be reused to generate further signatures with the same private
254 * key.
255 *
256 * This method should be abstract, but we leave it concrete for
257 * binary compatibility. Knowledgeable providers should override this
258 * method.
259 *
260 * @param outbuf buffer for the signature result.
261 *
262 * @param offset offset into {@code outbuf} where the signature is
263 * stored.
264 *
265 * @param len number of bytes within {@code outbuf} allotted for the
266 * signature.
267 * Both this default implementation and the SUN provider do not
268 * return partial digests. If the value of this parameter is less
269 * than the actual signature length, this method will throw a
270 * SignatureException.
271 * This parameter is ignored if its value is greater than or equal to
272 * the actual signature length.
273 *
274 * @return the number of bytes placed into {@code outbuf}
275 *
276 * @exception SignatureException if the engine is not
277 * initialized properly, if this signature algorithm is unable to
278 * process the input data provided, or if {@code len} is less
279 * than the actual signature length.
280 *
281 * @since 1.2
282 */
283 protected int engineSign(byte[] outbuf, int offset, int len)
284 throws SignatureException {
285 byte[] sig = engineSign();
286 if (len < sig.length) {
287 throw new SignatureException
288 ("partial signatures not returned");
289 }
290 if (outbuf.length - offset < sig.length) {
291 throw new SignatureException
292 ("insufficient space in the output buffer to store the "
293 + "signature");
294 }
295 System.arraycopy(sig, 0, outbuf, offset, sig.length);
296 return sig.length;
297 }
298
299 /**
300 * Verifies the passed-in signature.
301 *
302 * @param sigBytes the signature bytes to be verified.
303 *
304 * @return true if the signature was verified, false if not.
305 *
306 * @exception SignatureException if the engine is not
307 * initialized properly, the passed-in signature is improperly
308 * encoded or of the wrong type, if this signature algorithm is unable to
309 * process the input data provided, etc.
310 */
311 protected abstract boolean engineVerify(byte[] sigBytes)
312 throws SignatureException;
313
314 /**
315 * Verifies the passed-in signature in the specified array
316 * of bytes, starting at the specified offset.
317 *
318 * <p> Note: Subclasses should overwrite the default implementation.
319 *
320 *
321 * @param sigBytes the signature bytes to be verified.
322 * @param offset the offset to start from in the array of bytes.
323 * @param length the number of bytes to use, starting at offset.
324 *
325 * @return true if the signature was verified, false if not.
326 *
327 * @exception SignatureException if the engine is not
328 * initialized properly, the passed-in signature is improperly
329 * encoded or of the wrong type, if this signature algorithm is unable to
330 * process the input data provided, etc.
331 * @since 1.4
332 */
333 protected boolean engineVerify(byte[] sigBytes, int offset, int length)
334 throws SignatureException {
335 byte[] sigBytesCopy = new byte[length];
336 System.arraycopy(sigBytes, offset, sigBytesCopy, 0, length);
337 return engineVerify(sigBytesCopy);
338 }
339
340 /**
341 * Sets the specified algorithm parameter to the specified
342 * value. This method supplies a general-purpose mechanism through
343 * which it is possible to set the various parameters of this object.
344 * A parameter may be any settable parameter for the algorithm, such as
345 * a parameter size, or a source of random bits for signature generation
346 * (if appropriate), or an indication of whether or not to perform
347 * a specific but optional computation. A uniform algorithm-specific
348 * naming scheme for each parameter is desirable but left unspecified
349 * at this time.
350 *
351 * @param param the string identifier of the parameter.
352 *
353 * @param value the parameter value.
354 *
355 * @exception InvalidParameterException if {@code param} is an
356 * invalid parameter for this signature algorithm engine,
357 * the parameter is already set
358 * and cannot be set again, a security exception occurs, and so on.
359 *
360 * @deprecated Replaced by {@link
361 * #engineSetParameter(java.security.spec.AlgorithmParameterSpec)
362 * engineSetParameter}.
363 */
364 @Deprecated
365 protected abstract void engineSetParameter(String param, Object value)
366 throws InvalidParameterException;
367
368 /**
369 * <p>This method is overridden by providers to initialize
370 * this signature engine with the specified parameter set.
371 *
372 * @param params the parameters
373 *
374 * @exception UnsupportedOperationException if this method is not
375 * overridden by a provider
376 *
377 * @exception InvalidAlgorithmParameterException if this method is
378 * overridden by a provider and the given parameters
379 * are inappropriate for this signature engine
380 */
381 protected void engineSetParameter(AlgorithmParameterSpec params)
382 throws InvalidAlgorithmParameterException {
383 throw new UnsupportedOperationException();
384 }
385
386 /**
387 * <p>This method is overridden by providers to return the parameters
388 * used with this signature engine.
389 *
390 * <p> If this signature engine has been previously initialized with
391 * parameters (by calling the {@code engineSetParameter} method), this
392 * method returns the same parameters. If this signature engine has not been
393 * initialized with parameters, this method may return a combination of
394 * default and randomly generated parameter values if the underlying
395 * signature implementation supports it and can successfully generate
396 * them. Otherwise, {@code null} is returned.
397 *
398 * @return the parameters used with this signature engine, or {@code null}
399 *
400 * @exception UnsupportedOperationException if this method is
401 * not overridden by a provider
402 * @since 1.4
403 */
404 protected AlgorithmParameters engineGetParameters() {
405 throw new UnsupportedOperationException();
406 }
407
408 /**
409 * Gets the value of the specified algorithm parameter.
410 * This method supplies a general-purpose mechanism through which it
411 * is possible to get the various parameters of this object. A parameter
412 * may be any settable parameter for the algorithm, such as a parameter
413 * size, or a source of random bits for signature generation (if
414 * appropriate), or an indication of whether or not to perform a
415 * specific but optional computation. A uniform algorithm-specific
416 * naming scheme for each parameter is desirable but left unspecified
417 * at this time.
418 *
419 * @param param the string name of the parameter.
420 *
421 * @return the object that represents the parameter value, or {@code null} if
422 * there is none.
423 *
424 * @exception InvalidParameterException if {@code param} is an
425 * invalid parameter for this engine, or another exception occurs while
426 * trying to get this parameter.
427 *
428 * @deprecated
429 */
430 @Deprecated
431 protected abstract Object engineGetParameter(String param)
432 throws InvalidParameterException;
433
434 /**
435 * Returns a clone if the implementation is cloneable.
436 *
437 * @return a clone if the implementation is cloneable.
438 *
439 * @exception CloneNotSupportedException if this is called
440 * on an implementation that does not support {@code Cloneable}.
441 */
442 public Object clone() throws CloneNotSupportedException {
443 if (this instanceof Cloneable) {
444 return super.clone();
445 } else {
446 throw new CloneNotSupportedException();
447 }
448 }
449 }
|
47 * @since 1.2
48 *
49 *
50 * @see Signature
51 */
52
53 public abstract class SignatureSpi {
54
55 /**
56 * Application-specified source of randomness.
57 */
58 protected SecureRandom appRandom = null;
59
60 /**
61 * Initializes this signature object with the specified
62 * public key for verification operations.
63 *
64 * @param publicKey the public key of the identity whose signature is
65 * going to be verified.
66 *
67 * @throws InvalidKeyException if the key is improperly
68 * encoded, parameters are missing, and so on.
69 */
70 protected abstract void engineInitVerify(PublicKey publicKey)
71 throws InvalidKeyException;
72
73 /**
74 * Initializes this signature object with the specified
75 * public key for verification operations.
76 *
77 * @param publicKey the public key of the identity whose signature is
78 * going to be verified.
79 * @param params the parameters for generating this signature
80 *
81 * @throws InvalidKeyException if the key is improperly
82 * encoded, does not work with the given parameters, and so on.
83 * @throws InvalidAlgorithmParameterException if the given parameters
84 * is invalid.
85 */
86 void engineInitVerify(PublicKey publicKey,
87 AlgorithmParameterSpec params)
88 throws InvalidKeyException, InvalidAlgorithmParameterException {
89 if (params != null) {
90 try {
91 engineSetParameter(params);
92 } catch (UnsupportedOperationException usoe) {
93 // error out if not overrridden
94 throw new InvalidAlgorithmParameterException(usoe);
95 }
96 }
97 engineInitVerify(publicKey);
98 }
99
100 /**
101 * Initializes this signature object with the specified
102 * private key for signing operations.
103 *
104 * @param privateKey the private key of the identity whose signature
105 * will be generated.
106 *
107 * @throws InvalidKeyException if the key is improperly
108 * encoded, parameters are missing, and so on.
109 */
110 protected abstract void engineInitSign(PrivateKey privateKey)
111 throws InvalidKeyException;
112
113 /**
114 * Initializes this signature object with the specified
115 * private key and source of randomness for signing operations.
116 *
117 * <p>This concrete method has been added to this previously-defined
118 * abstract class. (For backwards compatibility, it cannot be abstract.)
119 *
120 * @param privateKey the private key of the identity whose signature
121 * will be generated.
122 * @param random the source of randomness
123 *
124 * @throws InvalidKeyException if the key is improperly
125 * encoded, parameters are missing, and so on.
126 */
127 protected void engineInitSign(PrivateKey privateKey,
128 SecureRandom random)
129 throws InvalidKeyException {
130 this.appRandom = random;
131 engineInitSign(privateKey);
132 }
133
134 /**
135 * Initializes this signature object with the specified
136 * private key and source of randomness for signing operations.
137 *
138 * <p>This concrete method has been added to this previously-defined
139 * abstract class. (For backwards compatibility, it cannot be abstract.)
140 *
141 * @param privateKey the private key of the identity whose signature
142 * will be generated.
143 * @param params the parameters for generating this signature
144 * @param random the source of randomness
145 *
146 * @throws InvalidKeyException if the key is improperly
147 * encoded, parameters are missing, and so on.
148 * @throws InvalidAlgorithmParameterException if the parameters is
149 * invalid.
150 */
151 void engineInitSign(PrivateKey privateKey,
152 AlgorithmParameterSpec params, SecureRandom random)
153 throws InvalidKeyException, InvalidAlgorithmParameterException {
154 if (params != null) {
155 try {
156 engineSetParameter(params);
157 } catch (UnsupportedOperationException usoe) {
158 // error out if not overrridden
159 throw new InvalidAlgorithmParameterException(usoe);
160 }
161 }
162 engineInitSign(privateKey, random);
163 }
164
165 /**
166 * Updates the data to be signed or verified
167 * using the specified byte.
168 *
169 * @param b the byte to use for the update.
170 *
171 * @throws SignatureException if the engine is not initialized
172 * properly.
173 */
174 protected abstract void engineUpdate(byte b) throws SignatureException;
175
176 /**
177 * Updates the data to be signed or verified, using the
178 * specified array of bytes, starting at the specified offset.
179 *
180 * @param b the array of bytes
181 * @param off the offset to start from in the array of bytes
182 * @param len the number of bytes to use, starting at offset
183 *
184 * @throws SignatureException if the engine is not initialized
185 * properly
186 */
187 protected abstract void engineUpdate(byte[] b, int off, int len)
188 throws SignatureException;
189
190 /**
191 * Updates the data to be signed or verified using the specified
192 * ByteBuffer. Processes the {@code data.remaining()} bytes
193 * starting at {@code data.position()}.
194 * Upon return, the buffer's position will be equal to its limit;
195 * its limit will not have changed.
196 *
197 * @param input the ByteBuffer
198 * @since 1.5
199 */
200 protected void engineUpdate(ByteBuffer input) {
201 if (input.hasRemaining() == false) {
202 return;
203 }
204 try {
217 input.get(b, 0, chunk);
218 engineUpdate(b, 0, chunk);
219 len -= chunk;
220 }
221 }
222 } catch (SignatureException e) {
223 // is specified to only occur when the engine is not initialized
224 // this case should never occur as it is caught in Signature.java
225 throw new ProviderException("update() failed", e);
226 }
227 }
228
229 /**
230 * Returns the signature bytes of all the data
231 * updated so far.
232 * The format of the signature depends on the underlying
233 * signature scheme.
234 *
235 * @return the signature bytes of the signing operation's result.
236 *
237 * @throws SignatureException if the engine is not
238 * initialized properly or if this signature algorithm is unable to
239 * process the input data provided.
240 */
241 protected abstract byte[] engineSign() throws SignatureException;
242
243 /**
244 * Finishes this signature operation and stores the resulting signature
245 * bytes in the provided buffer {@code outbuf}, starting at
246 * {@code offset}.
247 * The format of the signature depends on the underlying
248 * signature scheme.
249 *
250 * <p>The signature implementation is reset to its initial state
251 * (the state it was in after a call to one of the
252 * {@code engineInitSign} methods)
253 * and can be reused to generate further signatures with the same private
254 * key.
255 *
256 * This method should be abstract, but we leave it concrete for
257 * binary compatibility. Knowledgeable providers should override this
258 * method.
259 *
260 * @param outbuf buffer for the signature result.
261 *
262 * @param offset offset into {@code outbuf} where the signature is
263 * stored.
264 *
265 * @param len number of bytes within {@code outbuf} allotted for the
266 * signature.
267 * Both this default implementation and the SUN provider do not
268 * return partial digests. If the value of this parameter is less
269 * than the actual signature length, this method will throw a
270 * SignatureException.
271 * This parameter is ignored if its value is greater than or equal to
272 * the actual signature length.
273 *
274 * @return the number of bytes placed into {@code outbuf}
275 *
276 * @throws SignatureException if the engine is not
277 * initialized properly, if this signature algorithm is unable to
278 * process the input data provided, or if {@code len} is less
279 * than the actual signature length.
280 *
281 * @since 1.2
282 */
283 protected int engineSign(byte[] outbuf, int offset, int len)
284 throws SignatureException {
285 byte[] sig = engineSign();
286 if (len < sig.length) {
287 throw new SignatureException
288 ("partial signatures not returned");
289 }
290 if (outbuf.length - offset < sig.length) {
291 throw new SignatureException
292 ("insufficient space in the output buffer to store the "
293 + "signature");
294 }
295 System.arraycopy(sig, 0, outbuf, offset, sig.length);
296 return sig.length;
297 }
298
299 /**
300 * Verifies the passed-in signature.
301 *
302 * @param sigBytes the signature bytes to be verified.
303 *
304 * @return true if the signature was verified, false if not.
305 *
306 * @throws SignatureException if the engine is not
307 * initialized properly, the passed-in signature is improperly
308 * encoded or of the wrong type, if this signature algorithm is unable to
309 * process the input data provided, etc.
310 */
311 protected abstract boolean engineVerify(byte[] sigBytes)
312 throws SignatureException;
313
314 /**
315 * Verifies the passed-in signature in the specified array
316 * of bytes, starting at the specified offset.
317 *
318 * <p> Note: Subclasses should overwrite the default implementation.
319 *
320 *
321 * @param sigBytes the signature bytes to be verified.
322 * @param offset the offset to start from in the array of bytes.
323 * @param length the number of bytes to use, starting at offset.
324 *
325 * @return true if the signature was verified, false if not.
326 *
327 * @throws SignatureException if the engine is not
328 * initialized properly, the passed-in signature is improperly
329 * encoded or of the wrong type, if this signature algorithm is unable to
330 * process the input data provided, etc.
331 * @since 1.4
332 */
333 protected boolean engineVerify(byte[] sigBytes, int offset, int length)
334 throws SignatureException {
335 byte[] sigBytesCopy = new byte[length];
336 System.arraycopy(sigBytes, offset, sigBytesCopy, 0, length);
337 return engineVerify(sigBytesCopy);
338 }
339
340 /**
341 * Sets the specified algorithm parameter to the specified
342 * value. This method supplies a general-purpose mechanism through
343 * which it is possible to set the various parameters of this object.
344 * A parameter may be any settable parameter for the algorithm, such as
345 * a parameter size, or a source of random bits for signature generation
346 * (if appropriate), or an indication of whether or not to perform
347 * a specific but optional computation. A uniform algorithm-specific
348 * naming scheme for each parameter is desirable but left unspecified
349 * at this time.
350 *
351 * @param param the string identifier of the parameter.
352 *
353 * @param value the parameter value.
354 *
355 * @throws InvalidParameterException if {@code param} is an
356 * invalid parameter for this signature algorithm engine,
357 * the parameter is already set
358 * and cannot be set again, a security exception occurs, and so on.
359 *
360 * @deprecated Replaced by {@link
361 * #engineSetParameter(java.security.spec.AlgorithmParameterSpec)
362 * engineSetParameter}.
363 */
364 @Deprecated
365 protected abstract void engineSetParameter(String param, Object value)
366 throws InvalidParameterException;
367
368 /**
369 * <p>This method is overridden by providers to initialize
370 * this signature engine with the specified parameter set.
371 *
372 * @param params the parameters
373 *
374 * @throws UnsupportedOperationException if this method is not
375 * overridden by a provider
376 *
377 * @throws InvalidAlgorithmParameterException if this method is
378 * overridden by a provider and the given parameters
379 * are inappropriate for this signature engine
380 */
381 protected void engineSetParameter(AlgorithmParameterSpec params)
382 throws InvalidAlgorithmParameterException {
383 throw new UnsupportedOperationException();
384 }
385
386 /**
387 * <p>This method is overridden by providers to return the parameters
388 * used with this signature engine.
389 *
390 * <p> If this signature engine has been previously initialized with
391 * parameters (by calling the {@code engineSetParameter} method), this
392 * method returns the same parameters. If this signature engine has not been
393 * initialized with parameters, this method may return a combination of
394 * default and randomly generated parameter values if the underlying
395 * signature implementation supports it and can successfully generate
396 * them. Otherwise, {@code null} is returned.
397 *
398 * @return the parameters used with this signature engine, or {@code null}
399 *
400 * @throws UnsupportedOperationException if this method is
401 * not overridden by a provider
402 * @since 1.4
403 */
404 protected AlgorithmParameters engineGetParameters() {
405 throw new UnsupportedOperationException();
406 }
407
408 /**
409 * Gets the value of the specified algorithm parameter.
410 * This method supplies a general-purpose mechanism through which it
411 * is possible to get the various parameters of this object. A parameter
412 * may be any settable parameter for the algorithm, such as a parameter
413 * size, or a source of random bits for signature generation (if
414 * appropriate), or an indication of whether or not to perform a
415 * specific but optional computation. A uniform algorithm-specific
416 * naming scheme for each parameter is desirable but left unspecified
417 * at this time.
418 *
419 * @param param the string name of the parameter.
420 *
421 * @return the object that represents the parameter value, or {@code null} if
422 * there is none.
423 *
424 * @throws InvalidParameterException if {@code param} is an
425 * invalid parameter for this engine, or another exception occurs while
426 * trying to get this parameter.
427 *
428 * @deprecated
429 */
430 @Deprecated
431 protected abstract Object engineGetParameter(String param)
432 throws InvalidParameterException;
433
434 /**
435 * Returns a clone if the implementation is cloneable.
436 *
437 * @return a clone if the implementation is cloneable.
438 *
439 * @throws CloneNotSupportedException if this is called
440 * on an implementation that does not support {@code Cloneable}.
441 */
442 public Object clone() throws CloneNotSupportedException {
443 if (this instanceof Cloneable) {
444 return super.clone();
445 } else {
446 throw new CloneNotSupportedException();
447 }
448 }
449 }
|