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