/** * When an instance of this class is used as a delegate for the implementation of the BeanContext * protocols (and its subprotocols) there exists a 'chicken and egg' problem during * deserialization */ public final void readChildren(ObjectInputStream ois) throws IOException, ClassNotFoundException { int count = serializable; while (count-- > 0) { Object child = null; BeanContextSupport.BCSChild bscc = null; try { child = ois.readObject(); bscc = (BeanContextSupport.BCSChild) ois.readObject(); } catch (IOException ioe) { continue; } catch (ClassNotFoundException cnfe) { continue; } synchronized (child) { BeanContextChild bcc = null; try { bcc = (BeanContextChild) child; } catch (ClassCastException cce) { // do nothing; } if (bcc != null) { try { bcc.setBeanContext(getBeanContextPeer()); bcc.addPropertyChangeListener("beanContext", childPCL); bcc.addVetoableChangeListener("beanContext", childVCL); } catch (PropertyVetoException pve) { continue; } } childDeserializedHook(child, bscc); } } }
/** * internal remove used when removal caused by unexpected <tt>setBeanContext</tt> or by * <tt>remove()</tt> invocation. * * @param targetChild the JavaBean, BeanContext, or Object to be removed * @param callChildSetBC used to indicate that the child should be notified that it is no longer * nested in this <tt>BeanContext</tt>. */ protected boolean remove(Object targetChild, boolean callChildSetBC) { if (targetChild == null) throw new IllegalArgumentException(); synchronized (BeanContext.globalHierarchyLock) { if (!containsKey(targetChild)) return false; if (!validatePendingRemove(targetChild)) { throw new IllegalStateException(); } BCSChild bcsc = (BCSChild) children.get(targetChild); BCSChild pbcsc = null; Object peer = null; // we are required to notify the child that it is no longer nested here if // it implements java.beans.beancontext.BeanContextChild synchronized (targetChild) { if (callChildSetBC) { BeanContextChild cbcc = getChildBeanContextChild(targetChild); if (cbcc != null) synchronized (cbcc) { cbcc.removePropertyChangeListener("beanContext", childPCL); cbcc.removeVetoableChangeListener("beanContext", childVCL); try { cbcc.setBeanContext(null); } catch (PropertyVetoException pve1) { cbcc.addPropertyChangeListener("beanContext", childPCL); cbcc.addVetoableChangeListener("beanContext", childVCL); throw new IllegalStateException(); } } } synchronized (children) { children.remove(targetChild); if (bcsc.isProxyPeer()) { pbcsc = (BCSChild) children.get(peer = bcsc.getProxyPeer()); children.remove(peer); } } if (getChildSerializable(targetChild) != null) serializable--; childJustRemovedHook(targetChild, bcsc); if (peer != null) { if (getChildSerializable(peer) != null) serializable--; childJustRemovedHook(peer, pbcsc); } } fireChildrenRemoved( new BeanContextMembershipEvent( getBeanContextPeer(), peer == null ? new Object[] {targetChild} : new Object[] {targetChild, peer})); } return true; }
/** * Adds/nests a child within this <tt>BeanContext</tt>. * * <p>Invoked as a side effect of java.beans.Beans.instantiate(). If the child object is not valid * for adding then this method throws an IllegalStateException. * * @param targetChild The child objects to nest within this <tt>BeanContext</tt> * @return true if the child was added successfully. * @see #validatePendingAdd */ public boolean add(Object targetChild) { if (targetChild == null) throw new IllegalArgumentException(); // The specification requires that we do nothing if the child // is already nested herein. if (children.containsKey(targetChild)) return false; // test before locking synchronized (BeanContext.globalHierarchyLock) { if (children.containsKey(targetChild)) return false; // check again if (!validatePendingAdd(targetChild)) { throw new IllegalStateException(); } // The specification requires that we invoke setBeanContext() on the // newly added child if it implements the java.beans.beancontext.BeanContextChild interface BeanContextChild cbcc = getChildBeanContextChild(targetChild); BeanContextChild bccp = null; synchronized (targetChild) { if (targetChild instanceof BeanContextProxy) { bccp = ((BeanContextProxy) targetChild).getBeanContextProxy(); if (bccp == null) throw new NullPointerException("BeanContextPeer.getBeanContextProxy()"); } BCSChild bcsc = createBCSChild(targetChild, bccp); BCSChild pbcsc = null; synchronized (children) { children.put(targetChild, bcsc); if (bccp != null) children.put(bccp, pbcsc = createBCSChild(bccp, targetChild)); } if (cbcc != null) synchronized (cbcc) { try { cbcc.setBeanContext(getBeanContextPeer()); } catch (PropertyVetoException pve) { synchronized (children) { children.remove(targetChild); if (bccp != null) children.remove(bccp); } throw new IllegalStateException(); } cbcc.addPropertyChangeListener("beanContext", childPCL); cbcc.addVetoableChangeListener("beanContext", childVCL); } Visibility v = getChildVisibility(targetChild); if (v != null) { if (okToUseGui) v.okToUseGui(); else v.dontUseGui(); } if (getChildSerializable(targetChild) != null) serializable++; childJustAddedHook(targetChild, bcsc); if (bccp != null) { v = getChildVisibility(bccp); if (v != null) { if (okToUseGui) v.okToUseGui(); else v.dontUseGui(); } if (getChildSerializable(bccp) != null) serializable++; childJustAddedHook(bccp, pbcsc); } } // The specification requires that we fire a notification of the change fireChildrenAdded( new BeanContextMembershipEvent( getBeanContextPeer(), bccp == null ? new Object[] {targetChild} : new Object[] {targetChild, bccp})); } return true; }