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.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: 510752 $ $Date: 2007-02-22 20:27:16 -0500 (Thu, 22 Feb 2007) $ 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 (ClassNotFoundException e) { 120 throw new InvalidConfigException("Class not loadable in classloader: " + classLoader, e); 121 } catch (NoClassDefFoundError e) { 122 throw new InvalidConfigException("Class not loadable in classloader: " + classLoader, e); 123 } catch (Exception e) { 124 throw new InvalidConfigException("Unable to deserialize GBeanState in classloader: " + classLoader, e); 125 } finally { 126 Thread.currentThread().setContextClassLoader(oldCl); 127 } 128 } 129 return gbeans; 130 } 131 132 private static byte[] storeGBeans(List gbeans) throws IOException { 133 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 134 ObjectOutputStream oos; 135 try { 136 oos = new ObjectOutputStream(baos); 137 } catch (IOException e) { 138 throw (AssertionError) new AssertionError("Unable to initialize ObjectOutputStream").initCause(e); 139 } 140 for (Iterator iterator = gbeans.iterator(); iterator.hasNext();) { 141 GBeanData gbeanData = (GBeanData) iterator.next(); 142 try { 143 gbeanData.writeExternal(oos); 144 } catch (Exception e) { 145 throw (IOException) new IOException("Unable to serialize GBeanData for " + gbeanData.getAbstractName()).initCause(e); 146 } 147 } 148 try { 149 oos.flush(); 150 } catch (IOException e) { 151 throw (AssertionError) new AssertionError("Unable to flush ObjectOutputStream").initCause(e); 152 } 153 return baos.toByteArray(); 154 } 155 }