Statistics
| Revision:

gvsig-tools / org.gvsig.tools / library / trunk / org.gvsig.tools / org.gvsig.tools.lib / src / main / java / org / gvsig / tools / library / AbstractLibrary.java @ 1169

History | View | Annotate | Download (11.7 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
/*
25
 * AUTHORS (In addition to CIT):
26
 * 2008 {DiSiD Technologies}   {Create a base Locator implementation}
27
 */
28
package org.gvsig.tools.library;
29

    
30
import java.util.HashSet;
31
import java.util.Iterator;
32
import java.util.Set;
33

    
34
import org.slf4j.Logger;
35
import org.slf4j.LoggerFactory;
36

    
37
/**
38
 * Base Library implementation, checking that a Library is initialized and
39
 * postInitialized only once.
40
 * 
41
 * Also adds initialization logging.
42
 * 
43
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
44
 * @author jjdelcerro
45
 */
46
public abstract class AbstractLibrary implements Library {
47

    
48
    private static Set initialized = new HashSet();
49
    private static Set postInitialized = new HashSet();
50

    
51
    private static final int DEFAULT_PRIORITY = 0;
52

    
53
    private Set requireds = null;
54
    private Class library;
55
    private String type;
56
    private int priority = DEFAULT_PRIORITY;
57

    
58
    /**
59
     * Association between a library class and its type.
60
     * 
61
     * @author gvSIG team
62
     */
63
    public static class Required {
64

    
65
        Class library;
66
        String type;
67
        private boolean added = false;
68

    
69
        Required(Class library, String type) {
70
            this.library = library;
71
            this.type = type;
72
        }
73

    
74
        public Class getLibrary() {
75
            return this.library;
76
        }
77

    
78
        public String getType() {
79
            return this.type;
80
        }
81

    
82
        public String toString() {
83
            return this.library.toString() + ":"
84
                + (this.type == null ? "UNDEFINED" : this.type.toUpperCase());
85
        }
86

    
87
        /**
88
         * @return the added
89
         */
90
        public boolean isAdded() {
91
            return added;
92
        }
93

    
94
        /**
95
         * @param added
96
         *            the added to set
97
         */
98
        public void setAdded(boolean added) {
99
            this.added = added;
100
        }
101
    }
102

    
103
    /**
104
     * Empty constructor.
105
     */
106
    protected AbstractLibrary() {
107
        // Nothing to do
108
    }
109

    
110
    /**
111
     * Creates a new library registering with type of library it is: API or
112
     * implementation of a library.
113
     * <p>
114
     * When it is an API library, the class will be itself.
115
     * </p>
116
     * 
117
     * @param library
118
     *            the library class we relate to
119
     * @param type
120
     *            the library type. See {@link TYPE}.
121
     * @deprecated to be removed in the 4.x version. Use the
122
     *             {@link #AbstractLibrary()} empty constructor and override the
123
     *             {@link #doRegistration()} method instead.
124
     * @see #AbstractLibrary()
125
     */
126
    protected AbstractLibrary(Class library, String type) {
127
        registerAs(library, type);
128
    }
129

    
130
    /**
131
     * Creates a new library registering it as an implementation.
132
     * A priority is also provided just in case there is another
133
     * implementation available, so the one with the highest priority
134
     * will be the one used.
135
     * 
136
     * @param library
137
     *            the library class we relate to
138
     * @param priority
139
     *            the priority of the library against other implementations
140
     *            of the same library
141
     * @deprecated to be removed in the 4.x version. Use the
142
     *             {@link #AbstractLibrary()} empty constructor and override the
143
     *             {@link #doRegistration()} method instead.
144
     * @see #AbstractLibrary()
145
     */
146
    protected AbstractLibrary(Class library, int priority) {
147
        registerAsImplementationOf(library, priority);
148
    }
149

    
150
    public Set getRequireds() {
151
        return this.requireds;
152
    }
153

    
154
    /**
155
     * Returns the name of the current Library
156
     */
157
    public Class getLibrary() {
158
        return this.library;
159
    }
160

    
161
    public String getType() {
162
        return this.type;
163
    }
164

    
165
    public int getPriority() {
166
        return this.priority;
167
    }
168

    
169
    /**
170
     * Adds a required library, so it is initialized before the current one.
171
     * 
172
     * @param library
173
     *            the required library
174
     * @param type
175
     *            the type of the required library
176
     * @deprecated use the {@link #require(Class)} method instead, as you may
177
     *             have problems if the type specified is not correct. Moreover,
178
     *             this is not needed.
179
     */
180
    public synchronized final void require(Class library, String type) {
181
        doRequire(library, type);
182
    }
183

    
184
    /**
185
     * Adds a required library, so it is initialized before the current one.
186
     * 
187
     * @param library
188
     *            the required library
189
     */
190
    public synchronized final void require(Class library) {
191
        doRequire(library, null);
192
    }
193

    
194
    private void doRequire(Class library, String type) {
195
        if (requireds == null) {
196
            this.requireds = new HashSet();
197
        }
198
        this.requireds.add(new Required(library, type));
199
    }
200

    
201
    /**
202
     * Registers the library with type of library it is: API or
203
     * implementation of a library.
204
     * <p>
205
     * When it is an API library, the class will be itself.
206
     * </p>
207
     * 
208
     * @param library
209
     *            the library class we relate to
210
     * @param type
211
     *            the library type. See {@link TYPE}.
212
     */
213
    protected synchronized final void registerAs(Class library, String type) {
214
        this.library = library;
215
        this.type = type;
216
        if (this.library != null) {
217
            if (!Library.class.isAssignableFrom(library)) {
218
                throw new IllegalArgumentException(
219
                "Invalid argument in registerAs(library:'"+library+"', type:"+type+") of class '"+this.getClass().getName()+"', the library argument don't implement the interface Library.");
220
            }
221
            // Add default dependencies between services, implementation and API
222
            if (!Library.TYPE.API.equals(type)) {
223
                doRequire(this.library, Library.TYPE.API);
224
                if (Library.TYPE.SERVICE.equals(type)) {
225
                    doRequire(this.library, Library.TYPE.IMPL);
226
                }
227
            }
228
        }
229
    }
230

    
231
    /**
232
     * Registers the library as an API one.
233
     * 
234
     * @param library
235
     *            the library class we relate to
236
     */
237
    protected synchronized final void registerAsAPI(Class library) {
238
        registerAs(library, TYPE.API);
239
    }
240

    
241
    /**
242
     * Registers the library as an implementation of an API library, with the
243
     * default priority.
244
     * 
245
     * @param library
246
     *            the library class we relate to
247
     */
248
    protected synchronized final void registerAsImplementationOf(Class library) {
249
        registerAsImplementationOf(library, DEFAULT_PRIORITY);
250
    }
251

    
252
    /**
253
     * Registers the library as an implementation of an API library.
254
     * A priority is also provided just in case there is another
255
     * implementation available, so the one with the highest priority
256
     * will be the one used.
257
     * 
258
     * @param library
259
     *            the library class we relate to
260
     * @param priority
261
     *            the priority of the library against other implementations
262
     *            of the same library
263
     */
264
    protected synchronized final void registerAsImplementationOf(Class library,
265
        int priority) {
266

    
267
        registerAs(library, Library.TYPE.IMPL);
268
        this.priority = priority;
269
    }
270

    
271
    /**
272
     * Registers the library as a service or provider of an API library.
273
     * 
274
     * @param library
275
     *            the library class we relate to
276
     */
277
    protected synchronized final void registerAsServiceOf(Class library) {
278
        registerAs(library, TYPE.SERVICE);
279
    }
280

    
281
    public synchronized final void initialize() throws LibraryException {
282
        Logger logger = null;
283

    
284
        // Check if we have been already initialized
285
        String name = getClass().getName();
286
        if (initialized.contains(name)) {
287
            return;
288
        }
289

    
290
        logger = LoggerFactory.getLogger(this.getClass());
291
        logger
292
            .info("Initializing library '" + this.getClass().getName() + "'.");
293

    
294
        // Set the current Library as initialized
295
        initialized.add(name);
296

    
297
        try {
298
                doInitialize();
299
        } catch(Throwable t) {
300
            logger.info("Can't initialize library '" + this.getClass().getName() + "'.", t);
301
        }
302
    }
303

    
304
    public synchronized final void postInitialize() throws LibraryException {
305
        Logger logger = null;
306

    
307
        // Check if we have been already postInitialized
308
        String name = getClass().getName();
309
        if (postInitialized.contains(name)) {
310
            return;
311
        }
312

    
313
        logger = LoggerFactory.getLogger(this.getClass());
314
        logger.info("PostInitializing library '" + this.getClass().getName()
315
            + "'.");
316
        try {
317
            doPostInitialize();
318
        } catch(Throwable t) {
319
            logger.info("Can't postinitialize library '" + this.getClass().getName() + "'.", t);
320
        }
321

    
322
        // Set the current Library as postInitialized
323
        postInitialized.add(name);
324
    }
325

    
326
    public void doRegistration() {
327
        // Empty implementation so child classes may still use the registration
328
        // in its constructor
329
    }
330

    
331
    public boolean equals(Object obj) {
332
        return obj != null
333
            && getClass().getName().equals(obj.getClass().getName());
334
    }
335

    
336
    public int hashCode() {
337
        return getClass().getName().hashCode();
338
    }
339

    
340
    public String toString() {
341
        if (getType() == null) {
342
            return getClass().getName();
343
        }
344
        String relatedLibName =
345
            library == null ? getClass().getName() : library.getName();
346
        return getClass().getName() + " (" + getType().toUpperCase() + " of "
347
            + relatedLibName + ")";
348
    }
349

    
350
    public boolean isRequired(Library lib) {
351
        return isRequired(lib.getClass());
352
    }
353

    
354
    public boolean isRequired(Class libClass) {
355
        if (requireds != null) {
356
            for (Iterator iterator = requireds.iterator(); iterator.hasNext();) {
357
                Required req = (Required) iterator.next();
358
                if (libClass.equals(req.getLibrary())) {
359
                    return true;
360
                }
361
            }
362
        }
363
        return false;
364
    }
365

    
366
    /**
367
     * Performs all the initializations of the library, only related to himself:
368
     * register implementation classes through the Locator, start services, etc.
369
     * 
370
     * @throws LibraryException
371
     *             if there is an error while performing the initialization of
372
     *             the library
373
     */
374
    protected abstract void doInitialize() throws LibraryException;
375

    
376
    /**
377
     * Performs all the initializations or validations related to the library
378
     * dependencies, as getting references to objects through other libraries
379
     * Locators.
380
     * 
381
     * @throws LibraryException
382
     *             if there is an error while loading an implementation of the
383
     *             library
384
     */
385
    protected abstract void doPostInitialize() throws LibraryException;
386

    
387
}