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