001 /**
002 *
003 * Copyright 2005 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.kernel.config;
018
019 import java.io.Serializable;
020 import java.io.IOException;
021 import java.io.ObjectInputStream;
022 import java.io.ByteArrayInputStream;
023 import java.io.EOFException;
024 import java.io.ByteArrayOutputStream;
025 import java.io.ObjectOutputStream;
026 import java.util.List;
027 import java.util.ArrayList;
028 import java.util.Collection;
029 import java.util.Collections;
030 import java.util.Iterator;
031
032 import org.apache.geronimo.gbean.GBeanData;
033 import org.apache.geronimo.gbean.GBeanInfo;
034 import org.apache.geronimo.gbean.AbstractName;
035 import org.apache.geronimo.kernel.Naming;
036 import org.apache.geronimo.kernel.ObjectInputStreamExt;
037 import org.apache.geronimo.kernel.repository.Environment;
038
039 /**
040 * @version $Rev: 410741 $ $Date: 2006-05-31 21:35:48 -0700 (Wed, 31 May 2006) $
041 */
042 public class SerializedGBeanState implements GBeanState, Serializable {
043 private static final long serialVersionUID = 6015138334529564307L;
044
045 /**
046 * GBeans contained in this configuration.
047 */
048 private final List gbeans = new ArrayList();
049
050 /**
051 * The serialized form of the gbeans. Once this is set on more gbeans can be added.
052 */
053 private byte[] gbeanState;
054
055 public SerializedGBeanState(Collection gbeans) {
056 if (gbeans != null){
057 this.gbeans.addAll(gbeans);
058 }
059 }
060
061 public List getGBeans(ClassLoader classLoader) throws InvalidConfigException {
062 if (gbeanState == null) {
063 return Collections.unmodifiableList(gbeans);
064 }
065 gbeans.addAll(loadGBeans(gbeanState, classLoader));
066 return Collections.unmodifiableList(gbeans);
067 }
068
069 public void addGBean(GBeanData gbeanData) {
070 if (gbeanState != null) {
071 throw new IllegalStateException("GBeans have been serialized, so no more GBeans can be added");
072 }
073
074 gbeans.add(gbeanData);
075 }
076
077 public GBeanData addGBean(String name, GBeanInfo gbeanInfo, Naming naming, Environment environment) {
078 if (gbeanState != null) {
079 throw new IllegalStateException("GBeans have been serialized, so no more GBeans can be added");
080 }
081
082 String j2eeType = gbeanInfo.getJ2eeType();
083 if (j2eeType == null) j2eeType = "GBean";
084 AbstractName abstractName = naming.createRootName(environment.getConfigId(), name, j2eeType);
085 GBeanData gBeanData = new GBeanData(abstractName, gbeanInfo);
086 addGBean(gBeanData);
087 return gBeanData;
088 }
089
090 private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
091 if (gbeanState == null) {
092 gbeanState = storeGBeans(gbeans);
093 gbeans.clear();
094 }
095
096 stream.defaultWriteObject();
097 }
098
099 private static List loadGBeans(byte[] gbeanState, ClassLoader classLoader) throws InvalidConfigException {
100 List gbeans = new ArrayList();
101 if (gbeanState != null && gbeanState.length > 0) {
102 // Set the thread context classloader so deserializing classes can grab the cl from the thread
103 ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
104 try {
105 Thread.currentThread().setContextClassLoader(classLoader);
106
107 ObjectInputStream ois = new ObjectInputStreamExt(new ByteArrayInputStream(gbeanState), classLoader);
108 try {
109 while (true) {
110 GBeanData gbeanData = new GBeanData();
111 gbeanData.readExternal(ois);
112 gbeans.add(gbeanData);
113 }
114 } catch (EOFException e) {
115 // ok
116 } finally {
117 ois.close();
118 }
119 } catch (Exception e) {
120 throw new InvalidConfigException("Unable to deserialize GBeanState", e);
121 } finally {
122 Thread.currentThread().setContextClassLoader(oldCl);
123 }
124 }
125 return gbeans;
126 }
127
128 private static byte[] storeGBeans(List gbeans) throws IOException {
129 ByteArrayOutputStream baos = new ByteArrayOutputStream();
130 ObjectOutputStream oos;
131 try {
132 oos = new ObjectOutputStream(baos);
133 } catch (IOException e) {
134 throw (AssertionError) new AssertionError("Unable to initialize ObjectOutputStream").initCause(e);
135 }
136 for (Iterator iterator = gbeans.iterator(); iterator.hasNext();) {
137 GBeanData gbeanData = (GBeanData) iterator.next();
138 try {
139 gbeanData.writeExternal(oos);
140 } catch (Exception e) {
141 throw (IOException) new IOException("Unable to serialize GBeanData for " + gbeanData.getAbstractName()).initCause(e);
142 }
143 }
144 try {
145 oos.flush();
146 } catch (IOException e) {
147 throw (AssertionError) new AssertionError("Unable to flush ObjectOutputStream").initCause(e);
148 }
149 return baos.toByteArray();
150 }
151 }