1 // -*- C++ -*-
2 // Module:  Log4CPLUS
3 // File:    factory.h
4 // Created: 2/2002
5 // Author:  Tad E. Smith
6 //
7 //
8 // Copyright 2002-2010 Tad E. Smith
9 //
10 // Licensed under the Apache License, Version 2.0 (the "License");
11 // you may not use this file except in compliance with the License.
12 // You may obtain a copy of the License at
13 //
14 //     http://www.apache.org/licenses/LICENSE-2.0
15 //
16 // Unless required by applicable law or agreed to in writing, software
17 // distributed under the License is distributed on an "AS IS" BASIS,
18 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 // See the License for the specific language governing permissions and
20 // limitations under the License.
21 
22 /** @file */
23 
24 #ifndef DCMTK_LOG4CPLUS_SPI_FACTORY_HEADER_
25 #define DCMTK_LOG4CPLUS_SPI_FACTORY_HEADER_
26 
27 #include "dcmtk/oflog/config.h"
28 
29 #if defined (DCMTK_LOG4CPLUS_HAVE_PRAGMA_ONCE)
30 #pragma once
31 #endif
32 
33 #include "dcmtk/oflog/appender.h"
34 #include "dcmtk/oflog/layout.h"
35 #include "dcmtk/oflog/tstring.h"
36 #include "dcmtk/oflog/spi/filter.h"
37 #include "dcmtk/oflog/spi/objreg.h"
38 #include <memory>
39 #include "dcmtk/ofstd/ofvector.h"
40 #include <locale>
41 
42 
43 namespace dcmtk {
44 namespace log4cplus {
45     namespace spi {
46 
47         /**
48          * This is the base class for all factories.
49          */
50         class DCMTK_LOG4CPLUS_EXPORT BaseFactory {
51         public:
52             virtual ~BaseFactory() = 0;
53 
54             /**
55              * Returns the typename of the objects this factory creates.
56              */
57             virtual log4cplus::tstring const & getTypeName() const = 0;
58         };
59 
60 
61         /**
62          * This abstract class defines the "Factory" interface to create "Appender"
63          * objects.
64          */
65         class DCMTK_LOG4CPLUS_EXPORT AppenderFactory : public BaseFactory {
66         public:
67             typedef Appender ProductType;
68             typedef SharedAppenderPtr ProductPtr;
69 
70             AppenderFactory();
71             virtual ~AppenderFactory() = 0;
72 
73             /**
74              * Create an "Appender" object.
75              */
76             virtual SharedAppenderPtr createObject(const log4cplus::helpers::Properties& props) = 0;
77         };
78 
79 
80 
81         /**
82          * This abstract class defines the "Factory" interface to create "Layout"
83          * objects.
84          */
85         class DCMTK_LOG4CPLUS_EXPORT LayoutFactory : public BaseFactory {
86         public:
87             typedef Layout ProductType;
88             typedef OFrvalue<OFunique_ptr<Layout> > ProductPtr;
89 
90             LayoutFactory();
91             virtual ~LayoutFactory() = 0;
92 
93             /**
94              * Create a "Layout" object.
95              */
96             virtual ProductPtr createObject(const log4cplus::helpers::Properties& props) = 0;
97         };
98 
99 
100 
101         /**
102          * This abstract class defines the "Factory" interface to create "Appender"
103          * objects.
104          */
105         class DCMTK_LOG4CPLUS_EXPORT FilterFactory : public BaseFactory {
106         public:
107             typedef Filter ProductType;
108             typedef FilterPtr ProductPtr;
109 
110             FilterFactory();
111             virtual ~FilterFactory() = 0;
112 
113             /**
114              * Create a "Filter" object.
115              */
116             virtual FilterPtr createObject(const log4cplus::helpers::Properties& props) = 0;
117         };
118 
119 
120         /**
121          * This abstract class defines the "Factory" interface to
122          * create STD_NAMESPACE locale instances.
123          */
124         class DCMTK_LOG4CPLUS_EXPORT LocaleFactory
125             : public BaseFactory
126         {
127         public:
128             typedef STD_NAMESPACE locale ProductType;
129             typedef STD_NAMESPACE locale ProductPtr;
130 
131             LocaleFactory();
132             virtual ~LocaleFactory() = 0;
133 
134             //! \returns STD_NAMESPACE locale instance
135             virtual ProductPtr createObject (
136                 const log4cplus::helpers::Properties & props) = 0;
137         };
138 
139 
140         /**
141          * This template class is used as a "Factory Registry".  Objects are
142          * "entered" into the registry with a "name" using the
143          * <code>put()</code> method.  (The registry then owns the object.)
144          * These object can then be retrieved using the <code>get()</code>
145          * method.
146          *
147          * <b>Note:</b>  This class is Thread-safe.
148          */
149         template<class T>
150         class DCMTK_LOG4CPLUS_EXPORT FactoryRegistry : ObjectRegistryBase {
151         public:
152             typedef T product_type;
153 
~FactoryRegistry()154             virtual ~FactoryRegistry() {
155                 clear();
156             }
157 
158           // public methods
159             /**
160              * Used to enter an object into the registry.  (The registry now
161              *  owns <code>object</code>.)
162              */
put(OFunique_ptr<T> object)163             bool put(OFunique_ptr<T> object) {
164                  bool putValResult = putVal(object->getTypeName(), object.get());
165                  object.release();
166                  return putValResult;
167             }
168 
169             /**
170              * Used to retrieve an object from the registry.  (The registry
171              * owns the returned pointer.)
172              */
get(const log4cplus::tstring & name)173             T* get(const log4cplus::tstring& name) const {
174                 return OFstatic_cast(T*, getVal(name));
175             }
176 
177         protected:
deleteObject(void * object)178             virtual void deleteObject(void *object) const {
179                 delete OFstatic_cast(T*, object);
180             }
181         };
182 
183 
184         typedef FactoryRegistry<AppenderFactory> AppenderFactoryRegistry;
185         typedef FactoryRegistry<LayoutFactory> LayoutFactoryRegistry;
186         typedef FactoryRegistry<FilterFactory> FilterFactoryRegistry;
187         typedef FactoryRegistry<LocaleFactory> LocaleFactoryRegistry;
188 
189 
190         /**
191          * Returns the "singleton" <code>AppenderFactoryRegistry</code>.
192          */
193         DCMTK_LOG4CPLUS_EXPORT AppenderFactoryRegistry& getAppenderFactoryRegistry();
194 
195         /**
196          * Returns the "singleton" <code>LayoutFactoryRegistry</code>.
197          */
198         DCMTK_LOG4CPLUS_EXPORT LayoutFactoryRegistry& getLayoutFactoryRegistry();
199 
200         /**
201          * Returns the "singleton" <code>FilterFactoryRegistry</code>.
202          */
203         DCMTK_LOG4CPLUS_EXPORT FilterFactoryRegistry& getFilterFactoryRegistry();
204 
205         /**
206          * Returns the "singleton" <code>LocaleFactoryRegistry</code>.
207          */
208         DCMTK_LOG4CPLUS_EXPORT LocaleFactoryRegistry& getLocaleFactoryRegistry();
209 
210 
211         template <typename ProductFactoryBase>
212         class LocalFactoryBase
213             : public ProductFactoryBase
214         {
215         public:
LocalFactoryBase(tchar const * n)216             LocalFactoryBase (tchar const * n)
217                 : name (n)
218             { }
219 
getTypeName()220             virtual log4cplus::tstring const & getTypeName() const
221             {
222                 return name;
223             }
224 
225         private:
226             log4cplus::tstring name;
227         };
228 
229 
230         template <typename LocalProduct, typename ProductFactoryBase>
231         class FactoryTempl
232             : public LocalFactoryBase<ProductFactoryBase>
233         {
234         public:
235             typedef typename ProductFactoryBase::ProductPtr ProductPtr;
236 
FactoryTempl(tchar const * n)237             FactoryTempl (tchar const * n)
238                 : LocalFactoryBase<ProductFactoryBase> (n)
239             { }
240 
createObject(helpers::Properties const & props)241             virtual ProductPtr createObject (helpers::Properties const & props)
242             {
243                 return ProductPtr (new LocalProduct (props));
244             }
245         };
246 
247 
248         #define DCMTK_LOG4CPLUS_REG_PRODUCT(reg, productprefix, productname, productns, productfact) \
249         reg.put (																               \
250             OFrvalue<OFunique_ptr<productfact> > (                                                       \
251                     new log4cplus::spi::FactoryTempl<productns productname, productfact> (     \
252                     DCMTK_LOG4CPLUS_TEXT(productprefix)                                              \
253                     DCMTK_LOG4CPLUS_TEXT(#productname))))
254 
255         #define DCMTK_LOG4CPLUS_REG_APPENDER(reg, appendername)                             \
256         DCMTK_LOG4CPLUS_REG_PRODUCT (reg, "log4cplus::", appendername, log4cplus::,         \
257             log4cplus::spi::AppenderFactory)
258 
259         #define DCMTK_LOG4CPLUS_REG_LAYOUT(reg, layoutname)                                 \
260         DCMTK_LOG4CPLUS_REG_PRODUCT (reg, "log4cplus::", layoutname, log4cplus::,           \
261             log4cplus::spi::LayoutFactory)
262 
263         #define DCMTK_LOG4CPLUS_REG_FILTER(reg, filtername)                                 \
264         DCMTK_LOG4CPLUS_REG_PRODUCT (reg, "log4cplus::spi::", filtername, log4cplus::spi::, \
265             log4cplus::spi::FilterFactory)
266 
267         #define DCMTK_LOG4CPLUS_REG_LOCALE(reg, name, factory)            \
268             reg.put (OFrvalue<OFunique_ptr<log4cplus::spi::LocaleFactory> > ( \
269                     new factory (name)))
270     } // namespace spi
271 }
272 } // end namespace dcmtk
273 
274 
275 #endif // DCMTK_LOG4CPLUS_SPI_FACTORY_HEADER_
276