KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > collections > functors > PrototypeFactory


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.collections.functors;
17
18 import java.io.ByteArrayInputStream JavaDoc;
19 import java.io.ByteArrayOutputStream JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.ObjectInputStream JavaDoc;
22 import java.io.ObjectOutputStream JavaDoc;
23 import java.io.Serializable JavaDoc;
24 import java.lang.reflect.InvocationTargetException JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26
27 import org.apache.commons.collections.Factory;
28 import org.apache.commons.collections.FunctorException;
29
30 /**
31  * Factory implementation that creates a new instance each time based on a prototype.
32  *
33  * @since Commons Collections 3.0
34  * @version $Revision: 1.7 $ $Date: 2004/05/16 11:47:38 $
35  *
36  * @author Stephen Colebourne
37  */

38 public class PrototypeFactory {
39
40     /**
41      * Factory method that performs validation.
42      * <p>
43      * Creates a Factory that will return a clone of the same prototype object
44      * each time the factory is used. The prototype will be cloned using one of these
45      * techniques (in order):
46      * <ul>
47      * <li>public clone method
48      * <li>public copy constructor
49      * <li>serialization clone
50      * <ul>
51      *
52      * @param prototype the object to clone each time in the factory
53      * @return the <code>prototype</code> factory
54      * @throws IllegalArgumentException if the prototype is null
55      * @throws IllegalArgumentException if the prototype cannot be cloned
56      */

57     public static Factory getInstance(Object JavaDoc prototype) {
58         if (prototype == null) {
59             return ConstantFactory.NULL_INSTANCE;
60         }
61         try {
62             Method JavaDoc method = prototype.getClass().getMethod("clone", null);
63             return new PrototypeCloneFactory(prototype, method);
64
65         } catch (NoSuchMethodException JavaDoc ex) {
66             try {
67                 prototype.getClass().getConstructor(new Class JavaDoc[] { prototype.getClass()});
68                 return new InstantiateFactory(
69                     prototype.getClass(),
70                     new Class JavaDoc[] { prototype.getClass()},
71                     new Object JavaDoc[] { prototype });
72
73             } catch (NoSuchMethodException JavaDoc ex2) {
74                 if (prototype instanceof Serializable JavaDoc) {
75                     return new PrototypeSerializationFactory((Serializable JavaDoc) prototype);
76                 }
77             }
78         }
79         throw new IllegalArgumentException JavaDoc("The prototype must be cloneable via a public clone method");
80     }
81
82     /**
83      * Constructor that performs no validation.
84      * Use <code>getInstance</code> if you want that.
85      */

86     private PrototypeFactory() {
87         super();
88     }
89
90     // PrototypeCloneFactory
91
//-----------------------------------------------------------------------
92
/**
93      * PrototypeCloneFactory creates objects by copying a prototype using the clone method.
94      */

95     static class PrototypeCloneFactory implements Factory, Serializable JavaDoc {
96         
97         /** The serial version */
98         static final long serialVersionUID = 5604271422565175555L;
99         
100         /** The object to clone each time */
101         private final Object JavaDoc iPrototype;
102         /** The method used to clone */
103         private transient Method JavaDoc iCloneMethod;
104
105         /**
106          * Constructor to store prototype.
107          */

108         private PrototypeCloneFactory(Object JavaDoc prototype, Method JavaDoc method) {
109             super();
110             iPrototype = prototype;
111             iCloneMethod = method;
112         }
113
114         /**
115          * Find the Clone method for the class specified.
116          */

117         private void findCloneMethod() {
118             try {
119                 iCloneMethod = iPrototype.getClass().getMethod("clone", null);
120
121             } catch (NoSuchMethodException JavaDoc ex) {
122                 throw new IllegalArgumentException JavaDoc("PrototypeCloneFactory: The clone method must exist and be public ");
123             }
124         }
125
126         /**
127          * Creates an object by calling the clone method.
128          *
129          * @return the new object
130          */

131         public Object JavaDoc create() {
132             // needed for post-serialization
133
if (iCloneMethod == null) {
134                 findCloneMethod();
135             }
136
137             try {
138                 return iCloneMethod.invoke(iPrototype, null);
139
140             } catch (IllegalAccessException JavaDoc ex) {
141                 throw new FunctorException("PrototypeCloneFactory: Clone method must be public", ex);
142             } catch (InvocationTargetException JavaDoc ex) {
143                 throw new FunctorException("PrototypeCloneFactory: Clone method threw an exception", ex);
144             }
145         }
146     }
147
148     // PrototypeSerializationFactory
149
//-----------------------------------------------------------------------
150
/**
151      * PrototypeSerializationFactory creates objects by cloning a prototype using serialization.
152      */

153     static class PrototypeSerializationFactory implements Factory, Serializable JavaDoc {
154         
155         /** The serial version */
156         static final long serialVersionUID = -8704966966139178833L;
157         
158         /** The object to clone via serialization each time */
159         private final Serializable JavaDoc iPrototype;
160
161         /**
162          * Constructor to store prototype
163          */

164         private PrototypeSerializationFactory(Serializable JavaDoc prototype) {
165             super();
166             iPrototype = prototype;
167         }
168
169         /**
170          * Creates an object using serialization.
171          *
172          * @return the new object
173          */

174         public Object JavaDoc create() {
175             ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc(512);
176             ByteArrayInputStream JavaDoc bais = null;
177             try {
178                 ObjectOutputStream JavaDoc out = new ObjectOutputStream JavaDoc(baos);
179                 out.writeObject(iPrototype);
180
181                 bais = new ByteArrayInputStream JavaDoc(baos.toByteArray());
182                 ObjectInputStream JavaDoc in = new ObjectInputStream JavaDoc(bais);
183                 return in.readObject();
184
185             } catch (ClassNotFoundException JavaDoc ex) {
186                 throw new FunctorException(ex);
187             } catch (IOException JavaDoc ex) {
188                 throw new FunctorException(ex);
189             } finally {
190                 try {
191                     if (bais != null) {
192                         bais.close();
193                     }
194                 } catch (IOException JavaDoc ex) {
195                     // ignore
196
}
197                 try {
198                     if (baos != null) {
199                         baos.close();
200                     }
201                 } catch (IOException JavaDoc ex) {
202                     // ignore
203
}
204             }
205         }
206     }
207
208 }
209
Popular Tags