/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package java.beans.beancontext;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.beans.VetoableChangeSupport;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import org.apache.harmony.beans.internal.nls.Messages;

public class BeanContextChildSupport implements BeanContextChild,
        BeanContextServicesListener, Serializable {

    private static final long serialVersionUID = 6328947014421475877L;

    static final String BEAN_CONTEXT = "beanContext"; //$NON-NLS-1$

    protected transient BeanContext beanContext;

    public BeanContextChild beanContextChildPeer;

    protected PropertyChangeSupport pcSupport;

    protected transient boolean rejectedSetBCOnce;

    protected VetoableChangeSupport vcSupport;

    public BeanContextChildSupport() {
        // This class implements the JavaBean component itself
        this(null);
    }

    public BeanContextChildSupport(BeanContextChild bcc) {
        // If 'bcc' parameter is not null the JavaBean component itself
        // implements BeanContextChild
        this.beanContextChildPeer = (bcc == null ? this : bcc);

        // Initialize necessary fields for later use
        pcSupport = new PropertyChangeSupport(this.beanContextChildPeer);
        vcSupport = new VetoableChangeSupport(this.beanContextChildPeer);
        this.rejectedSetBCOnce = false;
    }

    public void addPropertyChangeListener(String name,
            PropertyChangeListener pcl) {
        // Do nothing if name or listener is null
        if ((name == null) || (pcl == null)) {
            return;
        }

        this.pcSupport.addPropertyChangeListener(name, pcl);
    }

    public void addVetoableChangeListener(String name,
            VetoableChangeListener vcl) {
        // Do nothing if name or listener is null
        if ((name == null) || (vcl == null)) {
            return;
        }

        this.vcSupport.addVetoableChangeListener(name, vcl);
    }

    public void firePropertyChange(String name, Object oldValue, Object newValue) {
        this.pcSupport.firePropertyChange(name, oldValue, newValue);
    }

    public void fireVetoableChange(String name, Object oldValue, Object newValue)
            throws PropertyVetoException {

        this.vcSupport.fireVetoableChange(name, oldValue, newValue);
    }

    public synchronized BeanContext getBeanContext() {
        return this.beanContext;
    }

    public BeanContextChild getBeanContextChildPeer() {
        return this.beanContextChildPeer;
    }

    protected void initializeBeanContextResources() {
    }

    public boolean isDelegated() {
        return (!this.beanContextChildPeer.equals(this));
    }

    private void readObject(ObjectInputStream ois) throws IOException,
            ClassNotFoundException {

        ois.defaultReadObject();
    }

    protected void releaseBeanContextResources() {
    }

    public void removePropertyChangeListener(String name,
            PropertyChangeListener pcl) {

        this.pcSupport.removePropertyChangeListener(name, pcl);
    }

    public void removeVetoableChangeListener(String name,
            VetoableChangeListener vcl) {

        this.vcSupport.removeVetoableChangeListener(name, vcl);
    }

    public void serviceAvailable(BeanContextServiceAvailableEvent bcsae) {
        if (isDelegated()) {
            ((BeanContextServicesListener) beanContextChildPeer)
                    .serviceAvailable(bcsae);
        }
    }

    public void serviceRevoked(BeanContextServiceRevokedEvent bcsre) {
        if (isDelegated()) {
            ((BeanContextServicesListener) beanContextChildPeer)
                    .serviceRevoked(bcsre);
        }
    }

    public synchronized void setBeanContext(BeanContext bc)
            throws PropertyVetoException {

        // Do nothing if the old and new values are equal
        if ((this.beanContext == null) && (bc == null)) {
            return;
        }

        if ((this.beanContext != null) && this.beanContext.equals(bc)) {
            return;
        }

       
        

        // Children are not allowed to repeatedly veto this operation.
        // So, we set rejectedSetBCOnce flag to true if veto occurs
        // and never veto the change again
        if (!this.rejectedSetBCOnce) {

            this.rejectedSetBCOnce = true;
            // Validate the new BeanContext value and throw
            // PropertyVetoException if it was not successful
            if (!validatePendingSetBeanContext(bc)) {
                

                throw new PropertyVetoException(Messages.getString("beans.0F"), //$NON-NLS-1$
                        new PropertyChangeEvent(this.beanContextChildPeer,
                                BEAN_CONTEXT, this.beanContext, bc));
            }
            fireVetoableChange(BEAN_CONTEXT, this.beanContext, bc);
            this.rejectedSetBCOnce = false;
            
            releaseBeanContextResources();

            // We have to notify all listeners about "beanContext"
            // property change
            firePropertyChange(BEAN_CONTEXT, this.beanContext, bc);
            this.beanContext = bc;
            initializeBeanContextResources();
        }
    }

    public boolean validatePendingSetBeanContext(BeanContext newValue) {
        return true;
    }

    private void writeObject(ObjectOutputStream oos) throws IOException {
        oos.defaultWriteObject();
    }
}

@@ -1772,24 +1772,82 @@
 t vcSupport;
+%0A    %0A    private transient BeanContext lastVetoedContext;
 %0A%0A    public
@@ -3019,32 +3019,71 @@
 ner(name, vcl);%0A
+        this.lastVetoedContext = null;%0A
     %7D%0A%0A    publi
@@ -4336,24 +4336,63 @@
 name, vcl);%0A
+        this.lastVetoedContext = null;%0A
     %7D%0A%0A    p
@@ -5209,32 +5209,41 @@
      %0A        %0A%0A
+        %0A
         // Child
@@ -5421,16 +5421,17 @@
    if (!
+(
 this.rej
@@ -5444,20 +5444,93 @@
 etBCOnce
-) %7B%0A
+ && this.lastVetoedContext == bc)) %7B%0A            this.lastVetoedContext = bc;
 %0A       
@@ -5736,25 +5736,24 @@
 ntext(bc)) %7B
-%0A
             
@@ -5749,33 +5749,32 @@
                %0A
-%0A
                 
@@ -6070,32 +6070,55 @@
 anContext, bc);%0A
+        %7D%0A            %0A
             this
@@ -6449,24 +6449,24 @@
 rces();%0A
-
         
 %7D%0A    %7D%0A
@@ -6449,32 +6449,34 @@
 rces();%0A        
+//
 %7D%0A    %7D%0A%0A    pub

Fix bugs in java.beans.beancontext.BeanContextChildSupport.