001    /**
002     *
003     * Copyright 2004 The Apache Software Foundation
004     *
005     *  Licensed under the Apache License, Version 2.0 (the "License");
006     *  you may not use this file except in compliance with the License.
007     *  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.geronimo.gbean;
018    
019    import java.io.Externalizable;
020    import java.io.IOException;
021    import java.io.ObjectInput;
022    import java.io.ObjectOutput;
023    import java.util.Collections;
024    import java.util.Comparator;
025    import java.util.HashMap;
026    import java.util.HashSet;
027    import java.util.Iterator;
028    import java.util.Map;
029    import java.util.Set;
030    
031    /**
032     * @version $Rev: 471683 $ $Date: 2006-11-06 02:28:54 -0800 (Mon, 06 Nov 2006) $
033     */
034    public class GBeanData implements Externalizable {
035        private static final long serialVersionUID = -1012491431781444074L;
036    
037        private Externalizable backwardExternalizables[] = new Externalizable[] {
038                new V0Externalizable(),
039                new V1Externalizable()
040        };
041    
042        private GBeanInfo gbeanInfo;
043        private final Map attributes;
044        private final Map references;
045        private final Set dependencies;
046        private AbstractName abstractName;
047        private int priority;
048    
049        public GBeanData() {
050            attributes = new HashMap();
051            references = new HashMap();
052            dependencies = new HashSet();
053        }
054    
055        public GBeanData(GBeanInfo gbeanInfo) {
056            this();
057            setGBeanInfo(gbeanInfo);
058        }
059    
060        public GBeanData(AbstractName abstractName, GBeanInfo gbeanInfo) {
061            this();
062            this.abstractName = abstractName;
063            setGBeanInfo(gbeanInfo);
064        }
065    
066        public GBeanData(GBeanData gbeanData) {
067            setGBeanInfo(gbeanData.gbeanInfo);
068            attributes = new HashMap(gbeanData.attributes);
069            references = new HashMap(gbeanData.references);
070            dependencies = new HashSet(gbeanData.dependencies);
071            abstractName = gbeanData.abstractName;
072        }
073    
074        public AbstractName getAbstractName() {
075            return abstractName;
076        }
077    
078        public void setAbstractName(AbstractName abstractName) {
079            this.abstractName = abstractName;
080        }
081    
082        public GBeanInfo getGBeanInfo() {
083            return gbeanInfo;
084        }
085    
086        public void clearAttribute(String name) {
087            attributes.remove(name);
088        }
089    
090        public void clearReference(String name) {
091            references.remove(name);
092        }
093    
094        public void setGBeanInfo(GBeanInfo gbeanInfo) {
095            this.gbeanInfo = gbeanInfo;
096            if (gbeanInfo == null) {
097                priority = GBeanInfo.PRIORITY_NORMAL;
098            } else {
099                priority = gbeanInfo.getPriority();
100            }
101        }
102    
103        public Map getAttributes() {
104            return new HashMap(attributes);
105        }
106    
107        public Set getAttributeNames() {
108            return new HashSet(attributes.keySet());
109        }
110    
111        public Object getAttribute(String name) {
112            return attributes.get(name);
113        }
114    
115        public void setAttribute(String name, Object value) {
116            attributes.put(name, value);
117        }
118    
119        public Map getReferences() {
120            return new HashMap(references);
121        }
122    
123        public Set getReferencesNames() {
124            return new HashSet(references.keySet());
125        }
126    
127        public ReferencePatterns getReferencePatterns(String name) {
128            return (ReferencePatterns) references.get(name);
129        }
130    
131        public void setReferencePattern(String name, AbstractNameQuery pattern) {
132            setReferencePatterns(name, Collections.singleton(pattern));
133        }
134    
135        public void setReferencePattern(String name, AbstractName abstractName) {
136            setReferencePatterns(name, new ReferencePatterns(abstractName));
137        }
138    
139        public void setReferencePatterns(String name, Set patterns) {
140            setReferencePatterns(name, new ReferencePatterns(patterns));
141        }
142    
143        public void setReferencePatterns(String name, ReferencePatterns patterns) {
144            references.put(name, patterns);
145        }
146    
147        public Set getDependencies() {
148            return new HashSet(dependencies);
149        }
150    
151        public void setDependencies(Set dependencies) {
152            this.dependencies.clear();
153            addDependencies(dependencies);
154        }
155    
156        public void addDependencies(Set dependencies) {
157            for (Iterator iterator = dependencies.iterator(); iterator.hasNext();) {
158                Object dependency = iterator.next();
159                if (dependency instanceof AbstractName) {
160                    AbstractName name = (AbstractName) dependency;
161                    addDependency(name);
162                } else if (dependency instanceof AbstractNameQuery) {
163                    AbstractNameQuery nameQuery = (AbstractNameQuery) dependency;
164                    addDependency(nameQuery);
165                } else if (dependency instanceof ReferencePatterns) {
166                    ReferencePatterns referencePatterns = (ReferencePatterns) dependency;
167                    addDependency(referencePatterns);
168                } else {
169                    throw new IllegalArgumentException("Unknown dependency type: " + dependency);
170                }
171            }
172        }
173    
174        public void addDependency(ReferencePatterns dependency) {
175            this.dependencies.add(dependency);
176        }
177    
178        public void addDependency(AbstractNameQuery refInfo) {
179            this.dependencies.add(new ReferencePatterns(refInfo));
180        }
181    
182        public void addDependency(AbstractName dependency) {
183            this.dependencies.add(new ReferencePatterns(dependency));
184        }
185    
186        public int getPriority() {
187            return priority;
188        }
189    
190        public void setPriority(int priority) {
191            this.priority = priority;
192        }
193    
194        public void writeExternal(ObjectOutput out) throws IOException {
195            // write version index
196            out.writeObject(new Integer(backwardExternalizables.length -1));
197    
198            // write the gbean info
199            out.writeObject(gbeanInfo);
200    
201            // write the abstract name
202            out.writeObject(abstractName);
203    
204            // write the priority
205            out.writeInt(priority);
206    
207            // write the attributes
208            out.writeInt(attributes.size());
209            for (Iterator iterator = attributes.entrySet().iterator(); iterator.hasNext();) {
210                Map.Entry entry = (Map.Entry) iterator.next();
211                String name = (String) entry.getKey();
212                Object value = entry.getValue();
213                try {
214                    out.writeObject(name);
215                    out.writeObject(value);
216                } catch (IOException e) {
217                    throw (IOException) new IOException("Unable to write attribute: " + name + " in gbean: " + abstractName).initCause(e);
218                } catch (NoClassDefFoundError e) {
219                    throw (IOException) new IOException("Unable to write attribute: " + name + " in gbean: " + abstractName).initCause(e);
220                }
221            }
222    
223            // write the references
224            out.writeInt(references.size());
225            for (Iterator iterator = references.entrySet().iterator(); iterator.hasNext();) {
226                Map.Entry entry = (Map.Entry) iterator.next();
227                String name = (String) entry.getKey();
228                ReferencePatterns value = (ReferencePatterns) entry.getValue();
229                try {
230                    out.writeObject(name);
231                    out.writeObject(value);
232                } catch (IOException e) {
233                    throw (IOException) new IOException("Unable to write reference pattern: " + name + " in gbean: " + abstractName).initCause(e);
234                }
235            }
236            //write the dependencies
237            out.writeInt(dependencies.size());
238            for (Iterator iterator = dependencies.iterator(); iterator.hasNext();) {
239                ReferencePatterns referencePatterns = (ReferencePatterns) iterator.next();
240                try {
241                    out.writeObject(referencePatterns);
242                } catch (IOException e) {
243                    throw (IOException) new IOException("Unable to write dependency pattern in gbean: " + abstractName).initCause(e);
244                }
245            }
246        }
247    
248    
249        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
250            Object opaque = in.readObject();
251            if (opaque instanceof Integer) {
252                backwardExternalizables[((Integer) opaque).intValue()].readExternal(in);
253            } else {
254                gbeanInfo = (GBeanInfo) opaque;
255                backwardExternalizables[0].readExternal(in);
256            }
257        }
258    
259        /**
260         * Note: this comparator
261         * imposes orderings that are inconsistent with equals.
262         */
263        public static class PriorityComparator implements Comparator {
264    
265            public int compare(Object o1, Object o2) {
266                if (o1 instanceof GBeanData && o2 instanceof GBeanData) {
267                    return ((GBeanData)o1).priority - ((GBeanData)o2).priority;
268                }
269                return 0;
270            }
271        }
272    
273        private class V0Externalizable implements Externalizable {
274    
275            public void writeExternal(ObjectOutput out) throws IOException {
276                throw new UnsupportedOperationException();
277            }
278    
279            public final void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
280                // read the gbean info
281                readGBeanInfo(in);
282    
283                // read the abstract name
284                try {
285                    abstractName = (AbstractName) in.readObject();
286                } catch (IOException e) {
287                    throw (IOException) new IOException("Unable to deserialize AbstractName for GBeanData of type " + gbeanInfo.getClassName()).initCause(e);
288                }
289    
290                readPriority(in);
291    
292                try {
293                    // read the attributes
294                    int attributeCount = in.readInt();
295                    for (int i = 0; i < attributeCount; i++) {
296                        String attributeName = (String) in.readObject();
297                        Object attributeValue;
298                        try {
299                            attributeValue = in.readObject();
300                        } catch (ClassNotFoundException e) {
301                            throw new ClassNotFoundException("Unable to find class used in GBeanData " + abstractName + ", attribute: " + attributeName, e);
302                        } catch (IOException e) {
303                            throw (IOException) new IOException("Unable to deserialize GBeanData " + abstractName + ", attribute: " + attributeName).initCause(e);
304                        }
305                        setAttribute(attributeName, attributeValue);
306                    }
307    
308                    // read the references
309                    int endpointCount = in.readInt();
310                    for (int i = 0; i < endpointCount; i++) {
311                        String referenceName = (String) in.readObject();
312                        ReferencePatterns referencePattern;
313                        try {
314                            referencePattern = (ReferencePatterns) in.readObject();
315                        } catch (ClassNotFoundException e) {
316                            throw new ClassNotFoundException("Unable to find class used in GBeanData " + abstractName + ", reference: " + referenceName, e);
317                        } catch (IOException e) {
318                            throw (IOException) new IOException("Unable to deserialize GBeanData " + abstractName + ", reference: " + referenceName).initCause(e);
319                        }
320                        setReferencePatterns(referenceName, referencePattern);
321                    }
322    
323                    //read the dependencies
324                    int dependencyCount = in.readInt();
325                    for (int i = 0; i < dependencyCount; i++) {
326                        ReferencePatterns depdendencyPattern = (ReferencePatterns) in.readObject();
327                        dependencies.add(depdendencyPattern);
328                    }
329                } catch (IOException e) {
330                    throw (IOException) new IOException("Unable to deserialize GBeanData " + abstractName).initCause(e);
331                } catch (ClassNotFoundException e) {
332                    throw new ClassNotFoundException("Unable to find class used in GBeanData " + abstractName, e);
333                }
334            }
335    
336            protected void readGBeanInfo(ObjectInput in) throws IOException, ClassNotFoundException {
337            }
338    
339            protected void readPriority(ObjectInput in) throws IOException, ClassNotFoundException {
340                priority = GBeanInfo.PRIORITY_NORMAL;
341            }
342    
343        }
344    
345        private class V1Externalizable extends V0Externalizable {
346    
347            public void writeExternal(ObjectOutput out) throws IOException {
348                throw new UnsupportedOperationException();
349            }
350    
351            protected void readGBeanInfo(ObjectInput in)  throws IOException, ClassNotFoundException {
352                gbeanInfo = (GBeanInfo) in.readObject();
353            }
354    
355            protected void readPriority(ObjectInput in) throws IOException, ClassNotFoundException {
356                priority = in.readInt();
357            }
358    
359        }
360    
361    }
362