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
018 package org.apache.commons.proxy.provider;
019
020 import org.apache.commons.proxy.ObjectProvider;
021 import org.apache.commons.proxy.ProxyUtils;
022 import org.apache.commons.proxy.exception.ObjectProviderException;
023
024 import java.lang.reflect.InvocationTargetException;
025 import java.lang.reflect.Method;
026
027 /**
028 * Merely calls <code>clone()</code> (reflectively) on the given {@link Cloneable} object.
029 *
030 * @author James Carman
031 * @since 1.0
032 */
033 public class CloningProvider implements ObjectProvider
034 {
035 private final Cloneable cloneable;
036 private Method cloneMethod;
037
038 /**
039 * Constructs a provider which returns clone copies of the specified {@link Cloneable}
040 * object.
041 * @param cloneable the object to clone
042 */
043 public CloningProvider( Cloneable cloneable )
044 {
045 this.cloneable = cloneable;
046 }
047
048 private synchronized Method getCloneMethod()
049 {
050 if( cloneMethod == null )
051 {
052 try
053 {
054 cloneMethod = cloneable.getClass().getMethod( "clone", ProxyUtils.EMPTY_ARGUMENT_TYPES );
055 }
056 catch( NoSuchMethodException e )
057 {
058 throw new ObjectProviderException(
059 "Class " + cloneable.getClass().getName() + " does not have a public clone() method." );
060 }
061 }
062 return cloneMethod;
063 }
064
065 public Object getObject()
066 {
067 try
068 {
069 return getCloneMethod().invoke( cloneable, ProxyUtils.EMPTY_ARGUMENTS );
070 }
071 catch( IllegalAccessException e )
072 {
073 throw new ObjectProviderException(
074 "Class " + cloneable.getClass().getName() + " does not have a public clone() method.", e );
075 }
076 catch( InvocationTargetException e )
077 {
078 throw new ObjectProviderException(
079 "Attempt to clone object of type " + cloneable.getClass().getName() + " threw an exception.", e );
080 }
081 }
082
083 }