001// Copyright 2011, 2012, 2023 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007// http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry5.commons.services;
016
017import java.lang.reflect.Constructor;
018import java.lang.reflect.Method;
019
020import org.apache.tapestry5.commons.Location;
021import org.apache.tapestry5.commons.ObjectCreator;
022import org.apache.tapestry5.ioc.annotations.IncompatibleChange;
023import org.apache.tapestry5.plastic.ClassInstantiator;
024import org.apache.tapestry5.plastic.PlasticClassListenerHub;
025import org.apache.tapestry5.plastic.PlasticClassTransformation;
026import org.apache.tapestry5.plastic.PlasticClassTransformer;
027import org.apache.tapestry5.plastic.PlasticManager;
028
029/**
030 * A service used to create proxies of varying types. As a secondary concern, manages to identify the
031 * location of methods and constructors, which is important for exception reporting.
032 *
033 * @since 5.3
034 */
035public interface PlasticProxyFactory extends PlasticClassListenerHub
036{
037    /**
038     * Returns the class loader used when creating new classes, this is a child class loader
039     * of another class loader (usually, the thread's context class loader).
040     */
041    ClassLoader getClassLoader();
042
043    /**
044     * Creates a proxy object that implements the indicated interface, then invokes the callback to further
045     * configure the proxy.
046     *
047     * @param interfaceType
048     *         interface implemented by proxy
049     * @param callback
050     *         configures the proxy
051     * @return instantiator that can be used to create an instance of the proxy class
052     */
053    <T> ClassInstantiator<T> createProxy(Class<T> interfaceType, PlasticClassTransformer callback);
054
055    /**
056     * Creates a proxy object that implements the indicated interface and indicated service implementation type,
057     * then invokes the callback to further configure the proxy.
058     *
059     * @param interfaceType
060     *         interface implemented by proxy
061     * @param implementationType
062     *         a class that implements the interfaceType. It can be null.
063     * @param callback
064     *         configures the proxy
065     * @return instantiator that can be used to create an instance of the proxy class
066     */
067    @IncompatibleChange(release = "5.4.5", details = "TAP5-2528")
068    <T> ClassInstantiator<T> createProxy(Class<T> interfaceType, Class<? extends T> implementationType, PlasticClassTransformer callback, boolean introduceInterface);
069
070    /**
071     * Same as <code>createProxy(interfacetype, implementationType, callback, true)</code>
072     *
073     * @param interfaceType
074     *         interface implemented by proxy
075     * @param implementationType
076     *         a class that implements the interfaceType. It can be null.
077     * @param callback
078     *         configures the proxy
079     * @return instantiator that can be used to create an instance of the proxy class
080     */
081    @IncompatibleChange(release = "5.4", details = "TAP5-2029")
082    <T> ClassInstantiator<T> createProxy(Class<T> interfaceType, Class<? extends T> implementationType, PlasticClassTransformer callback);
083
084    /**
085     * Creates the underlying {@link PlasticClassTransformation} for an interface proxy. This should only be
086     * used in the cases where encapsulating the PlasticClass construction into a {@linkplain PlasticClassTransformer
087     * callback} is not feasible (which is the case for some of the older APIs inside Tapestry IoC).
088     *
089     * @param interfaceType
090     *         class proxy will extend from
091     * @return transformation from which an instantiator may be created
092     */
093    <T> PlasticClassTransformation<T> createProxyTransformation(Class<T> interfaceType);
094
095    /**
096     * Creates the underlying {@link PlasticClassTransformation} for an interface proxy with a given
097     * implementation class. This should only be
098     * used in the cases where encapsulating the PlasticClass construction into a {@linkplain PlasticClassTransformer
099     * callback} is not feasible (which is the case for some of the older APIs inside Tapestry IoC).
100     *
101     * @param interfaceType
102     *         class proxy will extend from
103     * @param implementationType
104     *         a class that implements the interfaceType. It can be null.
105     * @return transformation from which an instantiator may be created
106     */
107    @IncompatibleChange(release = "5.4", details = "TAP5-2029")
108    <T> PlasticClassTransformation<T> createProxyTransformation(Class<T> interfaceType, Class<? extends T> implementationType);
109
110    /**
111     * Creates a proxy instance that delegates all methods through a corresponding
112     * ObjectCreator. Each method invocation on the proxy will route through {@link ObjectCreator#createObject()} (the
113     * creator implementation may decide to
114     * cache the return value as appropriate).
115     *
116     * @param <T>
117     *         type of proxy
118     * @param interfaceType
119     *         interface class for proxy
120     * @param creator
121     *         object responsible for creating the real object
122     * @param description
123     *         the <code>toString()</code> of the proxy
124     * @return proxy instance
125     */
126    <T> T createProxy(Class<T> interfaceType, ObjectCreator<T> creator, String description);
127    
128    /**
129     * Creates a proxy instance that delegates all methods through a corresponding
130     * ObjectCreator. Each method invocation on the proxy will route through {@link ObjectCreator#createObject()} (the
131     * creator implementation may decide to
132     * cache the return value as appropriate).
133     *
134     * @param <T>
135     *         type of proxy
136     * @param interfaceType
137     *         interface class for proxy
138     * @param implementationType
139     *         class that implements the interface type. It may be null
140     * @param creator
141     *         object responsible for creating the real object
142     * @param description
143     *         the <code>toString()</code> of the proxy
144     * @return proxy instance
145     */
146    @IncompatibleChange(release = "5.4", details = "Added for TAP5-2029")
147    <T> T createProxy(Class<T> interfaceType, Class<? extends T> implementationType, ObjectCreator<T> creator, String description);
148
149    /**
150     * Converts a method to a {@link Location}, which includes information about the source file name and line number.
151     *
152     * @param method
153     *         to look up
154     * @return the location (identifying the method and possibly, the line number within the method)
155     */
156    Location getMethodLocation(Method method);
157
158    /**
159     * Return a string representation for the constructor (including class and parameters) and (if available) file name
160     * and line number.
161     *
162     * @return the location (identifying the constructor and possibly, the line number within the method)
163     */
164    Location getConstructorLocation(Constructor constructor);
165
166    /**
167     * Clears any cached information stored by the proxy factory; this is useful in Tapestry development mode
168     * when a class loader may have been discarded (because the proxy factory may indirectly keep references
169     * to classes loaded by the old class loader).
170     *
171     * @since 5.3.3
172     */
173    @IncompatibleChange(release = "5.3.3", details = "Added method")
174    void clearCache();
175    
176    /**
177     * Returns the {@linkplain PlasticManager} instance used by this PlasticProxyFactory.
178     * @since 5.8.3
179     */
180    @IncompatibleChange(release = "5.8.3", details = "Added method")
181    PlasticManager getPlasticManager();
182
183    /**
184     * Returns the {@linkplain PlasticProxyFactory} instance to be used for a given class.
185     * Default implementation returns <code>this</code>.
186     * @since 5.8.3
187     */
188    default PlasticProxyFactory getProxyFactory(String className)
189    {
190        return this;
191    }
192
193}