User: d_jencks
  Date: 02/03/24 14:00:45

  Added:       src/main/org/jboss/test/jca/bank/ejb AccountBean.java
                        CustomerBean.java TellerBean.java
  Log:
  Tests for new ConnectionManager implementation. Many of these fail with the current 
less-than-spec-compliant jca-jdbc wrappers, but work ok with e.g. the firebird 
connector. Also, nojars combined targets removed, any test target can be run with 
-Dnojars=t.  Also, log4j logging fixed and moved to xml config.
  
  Revision  Changes    Path
  1.1                  jbosstest/src/main/org/jboss/test/jca/bank/ejb/AccountBean.java
  
  Index: AccountBean.java
  ===================================================================
  /*
   * Copyright 1999 by dreamBean Software,
   * All rights reserved.
   */
  package org.jboss.test.jca.bank.ejb;
  
  
  
  import java.rmi.RemoteException;
  import java.sql.Connection;
  import java.sql.PreparedStatement;
  import java.sql.ResultSet;
  import java.util.Collection;
  import javax.ejb.CreateException;
  import javax.ejb.EJBException;
  import javax.ejb.EntityBean;
  import javax.ejb.EntityContext;
  import javax.ejb.FinderException;
  import javax.ejb.ObjectNotFoundException;
  import javax.sql.DataSource;
  
  import javax.naming.InitialContext;
  import java.util.ArrayList;
  import java.sql.SQLException;
  
  import org.apache.log4j.Category;
  
  import org.jboss.test.jca.bank.interfaces.Customer;
  
  /**
   * Describe class <code>AccountBean</code> here.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>David Jencks</a>
   * @version 1.0
   * @ejb:bean   name="Account"
   *             jndi-name="Account"
   *             local-jndi-name="LocalAccount"
   *             view-type="both"
   *             type="BMP"
   *             primkey-field="id"
   * @ejb:pk class="java.lang.Integer"
   */
  public class AccountBean
     implements EntityBean
  {
  
     private Connection c;
  
     private Integer id;
     private int balance;
     private Integer customerId;    
     
     /**
      * Abstract cmp2 field get-set pair for field id
      * Get the value of id
      * @return value of id
      *
      * @ejb:interface-method
      */
     public Integer getId()
     {
        return id;
     }
     
     /**
      * Set the value of id
      * @param id  Value to assign to id
      *
      * @ejb:interface-method view-type="remote"
      */
     public void setId(final Integer id)
     {
        this.id = id;
     }
     
     
     
     /**
      * field get-set pair for field balance
      * Get the value of balance
      * @return value of balance
      *
      * @ejb:interface-method
      */
     public int getBalance()
     {
        return balance;
     }
     
     /**
      * Set the value of balance
      * @param balance  Value to assign to balance
      *
      * @ejb:interface-method view-type="remote"
      */
     public void setBalance(final int balance)
     {
        this.balance = balance;
     }
     
     
     
     /**
      * field get-set pair for field customerId
      * Get the value of customerId
      * @return value of customerId
      *
      * @ejb:interface-method
      */
     public Integer getCustomerId()
     {
        return customerId;
     }
     
     /**
      * Set the value of customerId
      * @param customerId  Value to assign to customerId
      *
      * @ejb:interface-method
      */
     public void setCustomerId(final Integer customerId)
     {
        this.customerId = customerId;
     }
     
  
  
  
     /**
      * Describe <code>deposit</code> method here.
      *
      * @param amount an <code>int</code> value
      * @ejb:interface-method
      */
     public void deposit(int amount)
     {
        setBalance(getBalance()+amount);
     }
     
     /**
      * Describe <code>withdraw</code> method here.
      *
      * @param amount an <code>int</code> value
      * @ejb:interface-method
      */
     public void withdraw(int amount)
     {
        setBalance(getBalance()-amount);
     }
  
  
     //ENTITY methods
     /**
      * Describe <code>ejbCreate</code> method here.
      *
      * @param id an <code>Integer</code> value
      * @param balance an <code>int</code> value
      * @param customerId an <code>Integer</code> value
      * @return an <code>Integer</code> value
      * @ejb:create-method
      */
     public Integer ejbCreate(final Integer id, final int balance, final Integer 
customerId) 
        throws CreateException
     { 
        setId(id);
        setBalance(balance);
        setCustomerId(customerId);
        PreparedStatement ps = null;
        try 
        {
        
           ps = getConnection().prepareStatement("INSERT INTO CCBMPACCOUNT (ID, 
BALANCE, CUSTOMERID) VALUES (?, ?, ?)");
           ps.setInt(1, id.intValue());
           ps.setInt(1, balance);
           ps.setObject(1, customerId);
        }
        catch (Exception e)
        {
           Category.getInstance(getClass().getName()).info("Exception in ejbCreate", 
e);
           throw new CreateException("Can't insert: " + e);
        } // end of try-catch
        finally
        {
           try 
           {
              if (ps != null) {ps.close();}
           }
           catch (Exception e)
           {
              Category.getInstance(getClass().getName()).info("Exception closing ps: " 
+ e);
           } // end of try-catch
           
        } // end of finally
        return id;
     }
     
     public void ejbPostCreate(final Integer id, final int balance, final Integer 
customerId) 
     { 
     }
  
     /**
      * Describe <code>ejbFindByPrimaryKey</code> method here.
      *
      * @param id an <code>Integer</code> value
      * @return an <code>Integer</code> value
      * @exception FinderException if an error occurs
      * @ejb:finder-method
      */
     public Integer ejbFindByPrimaryKey(final Integer id)
        throws FinderException
     {
        PreparedStatement ps = null;
        try 
        {
           ps = getConnection().prepareStatement("SELECT ID FROM CCBMPACCOUNT WHERE ID 
= ?");
           ps.setInt(1, id.intValue());
           ResultSet rs = ps.executeQuery();
           if (!rs.next()) 
           {
              throw new ObjectNotFoundException("No such account: " + id);
           } // end of if ()
           rs.close();
  
        }
        catch (Exception e)
        {
           Category.getInstance(getClass().getName()).info("Exception in findByPK", e);
           throw new EJBException("Problem in findByPrimaryKey: " + e);
        } // end of try-catch
        finally
        {
           try 
           {
              if (ps != null) {ps.close();}
           }
           catch (Exception e)
           {
              Category.getInstance(getClass().getName()).info("Exception closing ps: " 
+ e);
           } // end of try-catch
        } // end of finally
        return id;
     }
  
     /**
      * Describe <code>ejbFindByCustomerId</code> method here.
      *
      * @param customerId an <code>Integer</code> value
      * @return a <code>Collection</code> value
      * @ejb:finder-method
      */
     public Collection ejbFindByCustomerId(final Integer customerId)
     {
        PreparedStatement ps = null;
        try 
        {
           ps = getConnection().prepareStatement("SELECT ID FROM CCBMPACCOUNT WHERE 
CUSTOMERID = ?");
           ps.setInt(1, customerId.intValue());
           ResultSet rs = ps.executeQuery();
           Collection result = new ArrayList();
           while (rs.next()) 
           {
              result.add(new Integer(rs.getInt(1)));
           } // end of if ()
           rs.close();
              return result;
        }
        catch (Exception e)
        {
           Category.getInstance(getClass().getName()).info("Exception in 
findbyCustomerID", e);
           throw new EJBException(e);
        } // end of try-catch
        finally
        {
           try 
           {
              if (ps != null) {ps.close();}
           }
           catch (Exception e)
           {
              Category.getInstance(getClass().getName()).info("Exception closing ps: " 
+ e);
           } // end of try-catch
        } // end of finally
     }
  
     public void ejbActivate()
     {
     }
     
     public void ejbPassivate()
     {
        if (c != null) 
        {
           try 
           {
              c.close();
           }
           catch (Exception e)
           {
              Category.getInstance(getClass().getName()).info("Exception closing c: " 
+ e);
           } // end of try-catch
           c = null;
        } // end of if ()
     }
     
     public void ejbLoad()
     {
        if (id == null) 
        {
           Category.getInstance(getClass().getName()).info("null id!");
        } // end of if ()
        
        PreparedStatement ps = null;
        try 
        {
        
           ps = getConnection().prepareStatement("SELECT BALANCE, CUSTOMERID FROM 
CCBMPACCOUNT WHERE ID = ?");
           if (ps == null) 
           {
              Category.getInstance(getClass().getName()).info("WFT? null ps!");
           } // end of if ()
           
           ps.setInt(1, id.intValue());
           ResultSet rs = ps.executeQuery();
           rs.next();
           this.balance = rs.getInt(1);
           this.customerId = (Integer)rs.getObject(1);
        }
        catch (Exception e)
        {
           Category.getInstance(getClass().getName()).info("Exception in ejbLoad", e);
           throw new EJBException(e);
        } // end of try-catch
        finally
        {
           try 
           {
              if (ps != null) {ps.close();}
           }
           catch (Exception e)
           {
              Category.getInstance(getClass().getName()).info("Exception closing ps: " 
+ e);
           } // end of try-catch
        } // end of finally
     }
     
     public void ejbStore()
     {
        PreparedStatement ps = null;
        try 
        {
           ps = getConnection().prepareStatement("UPDATE CCBMPACCOUNT SET BALANCE = ?, 
CUSTOMERID = ? WHERE ID = ?");         
           ps.setInt(1, balance);
           ps.setObject(2, customerId);
           ps.setInt(3, id.intValue());
           ps.execute();
        }
        catch (Exception e)
        {
           Category.getInstance(getClass().getName()).info("Exception in ejbStore", e);
           throw new EJBException(e);
        } // end of try-catch
        finally
        {
           try 
           {
              if (ps != null) {ps.close();}
           }
           catch (Exception e)
           {
              Category.getInstance(getClass().getName()).info("Exception closing ps: " 
+ e);
           } // end of try-catch
        } // end of finally
        
     }
     
     public void ejbRemove()
     {
        PreparedStatement ps = null;
        try 
        {
           ps = getConnection().prepareStatement("DELETE FROM CCBMPACCOUNT WHERE ID = 
?");         
           ps.setInt(1, id.intValue());
           ps.execute();
        }
        catch (Exception e)
        {
           Category.getInstance(getClass().getName()).info("Exception in ejbRemove", 
e);
           throw new EJBException(e);
        } // end of try-catch
        finally
        {
           try 
           {
              if (ps != null) {ps.close();}
           }
           catch (Exception e)
           {
              Category.getInstance(getClass().getName()).info("Exception closing ps: " 
+ e);
           } // end of try-catch
        } // end of finally
     }
     
     public void setEntityContext(EntityContext ctx)
     {
     }
     
     public void unsetEntityContext()
     {
     }
  
     private Connection getConnection() throws Exception
     {
        if (c == null) 
        {
           DataSource ds = (DataSource)new InitialContext().lookup("java:/DefaultDS");
           c = ds.getConnection();
           
        } // end of if ()
        return c;
     }
  }
  
  
  
  
  1.1                  jbosstest/src/main/org/jboss/test/jca/bank/ejb/CustomerBean.java
  
  Index: CustomerBean.java
  ===================================================================
  /*
   * Copyright 1999 by dreamBean Software,
   * All rights reserved.
   */
  package org.jboss.test.jca.bank.ejb;
  
  
  import java.util.Collection;
  import java.sql.Connection;
  import java.sql.PreparedStatement;
  import java.sql.ResultSet;
  import javax.sql.DataSource;
  import java.sql.SQLException;
  
  import javax.ejb.ObjectNotFoundException;
  import javax.ejb.CreateException;
  import javax.ejb.EJBException;
  import javax.ejb.EntityBean;
  import javax.ejb.EntityContext;
  import javax.ejb.EntityContext;
  import javax.ejb.FinderException;
  import javax.naming.InitialContext;
  import java.util.ArrayList;
  
  import org.apache.log4j.Category;
  
  import org.jboss.test.jca.bank.interfaces.Account;
  import org.jboss.test.jca.bank.interfaces.AccountHome;
  
  
  /**
   * Describe class <code>CustomerBean</code> here.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>David Jencks</a>
   * @version 1.0
   * @ejb:bean   name="Customer"
   *             jndi-name="Customer"
   *             local-jndi-name="LocalCustomer"
   *             view-type="both"
   *             type="BMP"
   *             primkey-field="id"
   * @ejb:pk class="java.lang.Integer"
   */
  public class CustomerBean
     implements EntityBean
  {
  
     private Connection c;
  
     public Integer id;
     public String name;
     public Collection accounts;
     
     
     /**
      * field get-set pair for field id
      * Get the value of id
      * @return value of id
      *
      * @ejb:interface-method
      */
     public Integer getId()
     {
        return id;
     }
     
     /**
      * Set the value of id
      * @param id  Value to assign to id
      *
      * @ejb:interface-method view-type="remote"
      */
     public void setId(final Integer id)
     {
        this.id = id;
     }
     
     
     /**
      * field get-set pair for field name
      * Get the value of name
      * @return value of name
      *
      * @ejb:interface-method
      */
     public String getName()
     {
        return name;
     }
     
     /**
      * Set the value of name
      * @param name  Value to assign to name
      *
      * @ejb:interface-method view-type="remote"
      */
     public void setName(final String name)
     {
        this.name = name;
     }
     
     
     
     /**
      * field get-set pair for field accounts
      * Get the value of accounts
      * @return value of accounts
      *
      * @ejb:interface-method
      */
     public Collection getAccounts()
     {
        return accounts;
     }
     
     
  
     
     /**
      * Describe <code>addAccount</code> method here.
      *
      * @param account an <code>Account</code> value
      * @ejb:interface-method
      */
     public void addAccount(Account account)
     {
        try
        {
           account.setCustomerId(id);
           accounts.add(account);
        }
        catch (Exception e)
        {
           throw new EJBException("Problem in addAccount: " + e);
        }
     }
     
     /**
      * Describe <code>removeAccount</code> method here.
      *
      * @param acct an <code>Account</code> value
      * @ejb:interface-method
      */
     public void removeAccount(Account account)
     {
        try
        {
           accounts.remove(account);
           account.remove();
        }
        catch (Exception e)
        {
           throw new EJBException("Problem in removeAccount: " + e);
        }
  
     }
     
     // EntityHome implementation -------------------------------------
     /**
      * Describe <code>ejbCreate</code> method here.
      *
      * @param id an <code>Integer</code> value
      * @param name a <code>String</code> value
      * @return a <code>Integer</code> value
      * @ejb:create-method
      */
     public Integer ejbCreate(Integer id, String name) 
        throws CreateException
     { 
        setId(id);
        setName(name);
        PreparedStatement ps = null;
        try 
        {
        
           ps = getConnection().prepareStatement("INSERT INTO CCBMPCUSTOMER (ID, NAME) 
VALUES (?, ?)");
           ps.setInt(1, id.intValue());
           ps.setString(1, name);
           accounts = new ArrayList();
        }
        catch (Exception e)
        {
           throw new CreateException("Problem in ejbCreate: " + e);
        } // end of try-catch
        finally
        {
           try 
           {
              ps.close();
           }
           catch (SQLException e)
           {
              Category.getInstance(getClass().getName()).info("SQLException closing 
ps: " + e);
           } // end of try-catch
        } // end of finally
        return id;
     }
  
     public void ejbPostCreate(Integer id, String name) 
     { 
     }
  
     public Integer ejbFindByPrimaryKey(final Integer id)
        throws FinderException
     {
        PreparedStatement ps = null;
        try 
        {
           ps = getConnection().prepareStatement("SELECT ID FROM CCBMPCUSTOMER WHERE 
ID = ?");
           ps.setInt(1, id.intValue());
           ResultSet rs = ps.executeQuery();
           if (!rs.next()) 
           {
              throw new ObjectNotFoundException("No such customer: " + id);
           } // end of if ()
           rs.close();
  
        }
        catch (Exception e)
        {
           throw new EJBException("problem in findByPK: " + e);
        } // end of try-catch
        finally
        {
           try 
           {
              ps.close();
           }
           catch (SQLException e)
           {
              Category.getInstance(getClass().getName()).info("SQLException closing 
ps: " + e);
           } // end of try-catch
        } // end of finally
        return id;
     }
     
     public void ejbPostCreate(String id, String name) 
     { 
     }
  
     public void ejbActivate()
     {
     }
     
     public void ejbPassivate()
     {
        if (c != null) 
        {
           try 
           {
              c.close();
           }
           catch (SQLException e)
           {
              Category.getInstance(getClass().getName()).info("SQLException closing c: 
" + e);
           } // end of try-catch
           c = null;
        } // end of if ()
     }
     
     public void ejbLoad()
     {
        PreparedStatement ps = null;
        try 
        {
        
           ps = getConnection().prepareStatement("SELECT NAME FROM CCBMPCUSTOMER WHERE 
ID = ?");
           ps.setInt(1, id.intValue());
           ResultSet rs = ps.executeQuery();
           rs.next();
           this.name = rs.getString(1);
           AccountHome ah = (AccountHome)new InitialContext().lookup("Account");
           accounts = ah.findByCustomerId(id);
  
        }
        catch (Exception e)
        {
           throw new EJBException("Problem in ejbLoad: " +  e);
        } // end of try-catch
        finally
        {
           try 
           {
              ps.close();
           }
           catch (SQLException e)
           {
              Category.getInstance(getClass().getName()).info("SQLException closing 
ps: " + e);
           } // end of try-catch
        } // end of finally
     }
     
     public void ejbStore()
     {
        PreparedStatement ps = null;
        try 
        {
           ps = getConnection().prepareStatement("UPDATE CCBMPCUSTOMER SET NAME = ? 
WHERE ID = ?");         
           ps.setString(1, name);
           ps.setInt(2, id.intValue());
           ps.execute();
        }
        catch (Exception e)
        {
           throw new EJBException("Problem in ejbStore: " + e);
        } // end of try-catch
        finally
        {
           try 
           {
              ps.close();
           }
           catch (SQLException e)
           {
              Category.getInstance(getClass().getName()).info("SQLException closing 
ps: " + e);
           } // end of try-catch
        } // end of finally
        
     }
     
     public void ejbRemove()
     {
        PreparedStatement ps = null;
        try 
        {
           ps = getConnection().prepareStatement("DELETE FROM CCBMPCUSTOMER WHERE ID = 
?");         
           ps.setInt(1, id.intValue());
           ps.execute();
        }
        catch (Exception e)
        {
           throw new EJBException("Problem in ejbRemove: " + e);
        } // end of try-catch
        finally
        {
           try 
           {
              ps.close();
           }
           catch (SQLException e)
           {
              Category.getInstance(getClass().getName()).info("SQLException closing 
ps: " + e);
           } // end of try-catch
        } // end of finally
        
     }
     
     public void setEntityContext(EntityContext ctx)
     {
     }
     
     public void unsetEntityContext()
     {
     }
  
     private Connection getConnection() throws Exception
     {
        if (c == null) 
        {
           DataSource ds = (DataSource)new InitialContext().lookup("java:/DefaultDS");
           c = ds.getConnection();
           
        } // end of if ()
        
        return c;
     }
  }
  
  
  
  
  1.1                  jbosstest/src/main/org/jboss/test/jca/bank/ejb/TellerBean.java
  
  Index: TellerBean.java
  ===================================================================
  /*
   * Copyright 1999 by dreamBean Software,
   * All rights reserved.
   */
  package org.jboss.test.jca.bank.ejb;
  
  
  
  
  
  
  import java.sql.Connection;
  import java.sql.SQLException;
  import java.sql.Statement;
  import java.util.*;
  import javax.ejb.EJBException;
  import javax.ejb.SessionBean;
  import javax.ejb.SessionContext;
  import javax.naming.InitialContext;
  import javax.sql.DataSource;
  import org.apache.log4j.Category;
  import org.jboss.test.jca.bank.interfaces.Account;
  import org.jboss.test.jca.bank.interfaces.AccountHome;
  
  
  /**
   * Describe class <code>TellerBean</code> here.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>David Jencks</a>
   * @version 1.0
   *
   * @ejb:bean   name="Teller"
   *             jndi-name="Teller"
   *             local-jndi-name="LocalTellerBean"
   *             view-type="both"
   *             type="Stateless"
   */
  public class TellerBean 
     implements SessionBean
  {
     static int invocations;
  
     private Connection c;
  
     /**
      * Describe <code>setUp</code> method here.
      *
      * @exception EJBException if an error occurs
      * @ejb:interface-method
      */
     public void setUp()
     {
        try 
        {
           Statement s = getConnection().createStatement();
           s.execute("CREATE TABLE CCBMPCUSTOMER (ID INTEGER NOT NULL PRIMARY KEY, 
NAME VARCHAR(64))");
           s.execute("CREATE TABLE CCBMPACCOUNT (ID INTEGER NOT NULL PRIMARY KEY, 
BALANCE INTEGER NOT NULL, CUSTOMERID INTEGER)");
           s.close();         
  
        }
        catch (Exception e)
        {
           throw new EJBException(e);
        } // end of try-catch
        
     }
  
     /**
      * Describe <code>tearDown</code> method here.
      *
      * @exception EJBException if an error occurs
      * @ejb:interface-method
      */
     public void tearDown()
     {
        try 
        {
           Statement s = getConnection().createStatement();
           s.execute("DROP TABLE CCBMPCUSTOMER");
           s.execute("DROP TABLE CCBMPACCOUNT");
           s.close();         
  
        }
        catch (Exception e)
        {
           throw new EJBException(e);
        } // end of try-catch
        
     }
     /**
      * Describe <code>transfer</code> method here.
      *
      * @param from an <code>Account</code> value
      * @param to an <code>Account</code> value
      * @param amount a <code>float</code> value
      * @exception EJBException if an error occurs
      * @ejb:interface-method
      */
     public void transfer(Account from, Account to, int amount)
     {
        try
        {
           Category.getInstance(TellerBean.class.getName()).info("Invocation 
#"+invocations++);
           from.withdraw(amount);
           to.deposit(amount);
        } catch (Exception e)
        {
           throw new EJBException("Could not transfer "+amount+" from "+from+" to 
"+to, e);
        }
     }
     
     /**
      * Describe <code>createAccount</code> method here.
      *
      * @param id a <code>Integer</code> value, id of account
      * @return an <code>Account</code> value
      * @exception EJBException if an error occurs
      * @ejb:interface-method
      */
     public Account createAccount(Integer id)
        throws EJBException
     {
        try
        {
           AccountHome home = (AccountHome)new InitialContext().lookup("Account");
           Account acct = home.create(id, 0, null);
          
           return acct;
        } catch (Exception e)
        {
           throw new EJBException("Could not create account", e);
        }
     }
     
     /**
      * Describe <code>getAccountBalance</code> method here.
      *
      * @param id a <code>integer</code> value, id of account
      * @return an <code>int</code> value, balbance of account
      * @exception EJBException if an error occurs
      * @ejb:interface-method
      */
     public int getAccountBalance(Integer id)
     {
        try
        {
           AccountHome home = (AccountHome)new InitialContext().lookup("Account");
           Account a = home.findByPrimaryKey(id);
           return a.getBalance();
        } catch (Exception e)
        {
           Category.getInstance(getClass().getName()).info("getAccountBalance failed", 
e);
           throw new EJBException("Could not get account for id " + id, e);
        }
     }
     
     
     /**
      * Describe <code>transferTest</code> method here.
      *
      * @param from an <code>Account</code> value
      * @param to an <code>Account</code> value
      * @param amount a <code>float</code> value
      * @param iter an <code>int</code> value
      * @exception java.rmi.RemoteException if an error occurs
      * @exception EJBException if an error occurs
      * @ejb:interface-method
      */
     public void transferTest(Account from, Account to, int amount, int iter)
        throws java.rmi.RemoteException, EJBException
     {
        for (int i = 0; i < iter; i++)
        {
           from.withdraw(amount);
           to.deposit(amount);
        }
     }
  
     public void ejbCreate()
     {
     }
  
     public void ejbActivate()
     {
     }
  
     public void ejbPassivate()
     {
        if (c != null) 
        {
           try 
           {
              c.close();
           }
           catch (SQLException e)
           {
              Category.getInstance(getClass().getName()).info("SQLException closing c: 
" + e);
           } // end of try-catch
           c = null;
        } // end of if ()
     }
  
     public void ejbRemove()
     {
     }
  
     public void setSessionContext(SessionContext ctx)
     {
     }
  
     public void unsetSessionContext()
     {
     }
  
     private Connection getConnection() throws Exception
     {
        if (c == null) 
        {
           DataSource ds = (DataSource)new InitialContext().lookup("java:/DefaultDS");
           c = ds.getConnection();
           
        } // end of if ()
        
        return c;
     }
  }
  
  
  

_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to