Statistics
| Revision:

gvsig-tools / org.gvsig.tools / library / trunk / org.gvsig.tools / org.gvsig.tools.lib / src / main / java / org / gvsig / tools / library / AbstractLibrariesInitializer.java @ 654

History | View | Annotate | Download (14.8 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
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
 */
22

    
23
package org.gvsig.tools.library;
24

    
25
import java.text.MessageFormat;
26
import java.util.ArrayList;
27
import java.util.Collection;
28
import java.util.HashMap;
29
import java.util.HashSet;
30
import java.util.Iterator;
31
import java.util.LinkedHashSet;
32
import java.util.List;
33
import java.util.Map;
34
import java.util.Set;
35

    
36
import org.slf4j.Logger;
37
import org.slf4j.LoggerFactory;
38

    
39
import org.gvsig.tools.exception.BaseRuntimeException;
40
import org.gvsig.tools.library.AbstractLibrary.Required;
41

    
42
/**
43
 * Base implementation of an {@link LibrariesInitializer} with the
44
 * initialization of Libraries already implemented, delegating on child classes
45
 * the finding of available {@link Library} objects.
46
 * <p>
47
 * This class is NOT thread safe.
48
 * </p>
49
 * 
50
 * @author <a href="mailto:cordinyana@gvsig.org">C?sar Ordi?ana</a>
51
 */
52
public abstract class AbstractLibrariesInitializer implements
53
    LibrariesInitializer {
54

    
55
    private static final Logger LOG = LoggerFactory
56
        .getLogger(AbstractLibrariesInitializer.class);
57

    
58
    private Collection libs;
59

    
60
    private boolean libsLoaded = false;
61

    
62
    private final ClassLoader[] classLoaders;
63

    
64
    public AbstractLibrariesInitializer() {
65
        classLoaders = null;
66
    }
67

    
68
    public AbstractLibrariesInitializer(ClassLoader classLoader) {
69
        this(new ClassLoader[] { classLoader });
70
    }
71

    
72
    public AbstractLibrariesInitializer(ClassLoader[] classLoaders) {
73
        this.classLoaders = classLoaders;
74
    }
75

    
76
    public void initialize() {
77
        this.initialize(false);
78
    }
79

    
80
    public void initialize(boolean ignoreerrors) {
81
        if (!libsLoaded) {
82
            loadLibraries(classLoaders, ignoreerrors);
83
            libsLoaded = true;
84
        }
85
        if (libs != null && libs.size() > 0) {
86
            // Call all initialize()
87
            initializeLibraries(libs, false, ignoreerrors);
88
        }
89
    }
90

    
91
    public void postInitialize() {
92
        this.postInitialize(false);
93
    }
94

    
95
    public void postInitialize(boolean ignoreerrors) {
96
        if (!libsLoaded) {
97
            loadLibraries(classLoaders, ignoreerrors);
98
            libsLoaded = true;
99
        }
100
        if (libs != null && libs.size() > 0) {
101
            // Call all postInitialize()
102
            initializeLibraries(libs, true, ignoreerrors);
103
        }
104
    }
105

    
106
    public void fullInitialize() {
107
        initialize();
108
        postInitialize();
109
    }
110

    
111
    public void fullInitialize(boolean ignoreerrors) {
112
        initialize(ignoreerrors);
113
        postInitialize(ignoreerrors);
114
    }
115

    
116
    public List getLibraries() {
117
        if (!libsLoaded) {
118
            loadLibraries(classLoaders, false);
119
            libsLoaded = true;
120
        }
121

    
122
        return new ArrayList(this.libs);
123
    }
124

    
125
    private void loadLibraries(ClassLoader[] classLoaders, boolean ignoreerrors) {
126
        // Find the available Library instances
127
        Set libs = new HashSet();
128
        LOG.info("Loading libraries of classloaders:");
129
        if (classLoaders == null) {
130
            addLibrariesOfClassLoader(libs, null, ignoreerrors);
131
        } else {
132
            for (int i = 0; i < classLoaders.length; i++) {
133
                addLibrariesOfClassLoader(libs, classLoaders[i], ignoreerrors);
134
            }
135
        }
136

    
137
        int fullSize = libs.size();
138
        this.libs = new OrderedLibs(libs);
139

    
140
        if (LOG.isInfoEnabled()) {
141
            logLibraries(this.libs, fullSize);
142
        }
143
    }
144

    
145
    private void addLibrariesOfClassLoader(Set previousFoundLibs,
146
        ClassLoader classLoader, boolean ignoreerrors) {
147
        StringBuffer logBuf = new StringBuffer();
148
        try {
149
            Set foundLibs = findLibraries(Library.class, classLoader);
150
            foundLibs.removeAll(previousFoundLibs);
151
            logBuf
152
                .append(new Integer(foundLibs.size()))
153
                .append(" new libraries found in the classloader ")
154
                .append(
155
                    classLoader == null ? "DEFAULT" : classLoader.toString())
156
                .append(":");
157

    
158
            for (Iterator iterator = foundLibs.iterator(); iterator.hasNext();) {
159
                Library library = (Library) iterator.next();
160
                try {
161
                    library.doRegistration();
162
                } catch (Throwable e) {
163
                    manageLibraryException(ignoreerrors, "doRegistration",
164
                        library, e);
165
                }
166
                previousFoundLibs.add(library);
167
                logBuf.append("\n- ").append(library);
168
            }
169
            LOG.info(logBuf.toString());
170
        } catch (Exception e) {
171
            String msg =
172
                MessageFormat.format(
173
                    "Error finding libraries of classloader {0}",
174
                    new String[] { classLoader.toString() });
175
            manageLibraryException(ignoreerrors, msg, e);
176
        }
177
    }
178

    
179
    protected abstract Set findLibraries(Class libraryClass,
180
        ClassLoader classLoader);
181

    
182
    private void initializeLibraries(Collection libs, boolean post,
183
        boolean ignoreerrors) {
184
        String label;
185
        if (post) {
186
            label = "postInitialize";
187
        } else {
188
            label = "initialize";
189
        }
190

    
191
        for (Iterator iterator = libs.iterator(); iterator.hasNext();) {
192
            Library lib = (Library) iterator.next();
193
            try {
194
                if (post) {
195
                    LOG.trace("Calling {}.postInitialize()", lib.getClass()
196
                        .getName());
197
                    lib.postInitialize();
198
                } else {
199
                    LOG.trace("Calling {}.initialize()", lib.getClass()
200
                        .getName());
201
                    lib.initialize();
202
                }
203
            } catch (Throwable e) {
204
                manageLibraryException(ignoreerrors, label, lib, e);
205
            }
206
        }
207
    }
208

    
209
    private void manageLibraryException(boolean ignoreerrors, String label,
210
        Library lib, Throwable e) {
211
        String msg;
212
        if (e instanceof BaseRuntimeException) {
213
            msg = ((BaseRuntimeException) e).getLocalizedMessageStack();
214
        } else {
215
            msg = e.getLocalizedMessage();
216
        }
217
        String formattedMsg =
218
            MessageFormat.format("Error in {0} of library {1}. {2}",
219
                new String[] { label, lib.getClass().getName(), msg });
220
        manageLibraryException(ignoreerrors, formattedMsg, e);
221
    }
222

    
223
    private void manageLibraryException(boolean ignoreerrors, String message,
224
        Throwable e) {
225
        if (ignoreerrors) {
226
            LOG.error(message, e);
227
        } else {
228
            if (e instanceof RuntimeException) {
229
                throw (RuntimeException) e;
230
            } else
231
                if (e instanceof Error) {
232
                    throw (Error) e;
233
                }
234
        }
235
    }
236

    
237
    private void logLibraries(Collection libs, int fullSize) {
238
        StringBuffer buffer = new StringBuffer();
239
        buffer.append("Total libraries to initialize (")
240
            .append(libs == null ? 0 : libs.size()).append(" of ")
241
            .append(fullSize).append("):");
242
        if (libs != null) {
243
            for (Iterator iterator = libs.iterator(); iterator.hasNext();) {
244
                buffer.append("\n- ").append(iterator.next());
245
            }
246
        }
247
        LOG.info(buffer.toString());
248
    }
249

    
250
    private static class OrderedLibs extends LinkedHashSet {
251

    
252
        private static final long serialVersionUID = -8546268624773345053L;
253
        private Map organizedLibs = new HashMap();
254

    
255
        OrderedLibs(Set libs) {
256
            Iterator iterator = libs.iterator();
257
            while (iterator.hasNext()) {
258
                Library lib = (Library) iterator.next();
259
                addLibrary(lib);
260
            }
261
            iterator = libs.iterator();
262
            while (iterator.hasNext()) {
263
                Library lib = (Library) iterator.next();
264
                if (lib.getLibrary() != null && lib.getType() != null) {
265
                    // Always add services
266
                    if (Library.TYPE.SERVICE.equals(lib.getType())) {
267
                        this.add(lib);
268
                    } else {
269
                        String libName = getLibName(lib);
270
                        if (this.organizedLibs.containsKey(libName)) {
271
                            Library storeLib =
272
                                (Library) this.organizedLibs.get(libName);
273
                            // Only add a library if it has the greatest
274
                            // priority
275
                            if (lib.getPriority() >= storeLib.getPriority()) {
276
                                this.add(lib);
277
                            }
278
                        }
279
                    }
280
                } else {
281
                    this.add(lib);
282
                }
283
            }
284
        }
285

    
286
        private String getLibName(Library lib) {
287
            return lib.getLibrary().getName() + "-" + lib.getType();
288
        }
289

    
290
        private void addLibrary(Library lib) {
291
            if (lib.getLibrary() != null && lib.getType() != null) {
292
                String libName = getLibName(lib);
293

    
294
                if (Library.TYPE.SERVICE.equals(lib.getType())) {
295
                    Set serviceLibs;
296
                    if (this.organizedLibs.containsKey(libName)) {
297
                        serviceLibs = (Set) this.organizedLibs.get(libName);
298
                    } else {
299
                        serviceLibs = new HashSet();
300
                        this.organizedLibs.put(libName, serviceLibs);
301
                    }
302
                    serviceLibs.add(lib);
303
                    // Also add the library as itself of type implementation,
304
                    // just in case another library depends on it. Only for
305
                    // libraries whose type is SERVICE.
306
                    this.organizedLibs.put(lib.getClass().getName() + "-"
307
                        + Library.TYPE.IMPL, lib);
308
                } else
309
                    if (this.organizedLibs.containsKey(libName)) {
310

    
311
                        Library previousLibrary =
312
                            (Library) this.organizedLibs.get(libName);
313
                        LOG.warn(
314
                            "There's already a library initialized with the "
315
                                + "name '{}': '{}'  with priority '{}'"
316
                                + ", and '{}' with priority '{}",
317
                            new Object[] { libName,
318
                                previousLibrary.getClass().getName(),
319
                                String.valueOf(previousLibrary.getPriority()),
320
                                lib.getClass().getName(),
321
                                String.valueOf(lib.getPriority()) });
322

    
323
                        if (lib.getPriority() < previousLibrary.getPriority()) {
324
                            LOG.info(
325
                                "Old library '{}' with priority '{}'  was chosen.",
326
                                previousLibrary.getClass().getName(),
327
                                String.valueOf(previousLibrary.getPriority()));
328
                        } else {
329
                            this.organizedLibs.put(libName, lib);
330
                            LOG.info(
331
                                "New library '{}' with priority '{}'  was chosen.",
332
                                lib.getClass().getName(),
333
                                String.valueOf(lib.getPriority()));
334
                        }
335
                    } else {
336
                        this.organizedLibs.put(libName, lib);
337
                    }
338
            }
339
        }
340

    
341
        public void add(Library lib) {
342
            if (super.contains(lib)) {
343
                return;
344
            }
345
            Set requireds = lib.getRequireds();
346
            if (requireds != null) {
347
                Iterator iterator = requireds.iterator();
348
                while (iterator.hasNext()) {
349
                    Required req = (Required) iterator.next();
350
                    if (!req.isAdded()) {
351
                        req.setAdded(true);
352
                        addRequiredLibrary(req);
353
                    }
354
                }
355
            }
356

    
357
            if (lib.getLibrary() != null && lib.getType() != null) {
358
                organizedLibs.remove(getLibName(lib));
359
            }
360
            if (!super.contains(lib)) {
361
                super.add(lib);
362
            }
363
            String name = lib.getClass().getName();
364
            // Add as required all the related types so the library
365
            // has all implementation and services initialized
366
            if (Library.TYPE.API.equals(lib.getType())) {
367
                addRequiredLibrary(name, Library.TYPE.IMPL);
368
                addRequiredLibrary(name, Library.TYPE.SERVICE);
369
            }
370
        }
371

    
372
        private void addRequiredLibrary(Required req) {
373
            if (req.getLibrary() != null) {
374
                String name = req.getLibrary().getName();
375
                addRequiredLibrary(name, req.getType());
376
            }
377
        }
378

    
379
        private void addRequiredLibrary(String libraryName, String libraryType) {
380
            String type = getLibraryType(libraryName, libraryType);
381
            if (Library.TYPE.SERVICE.equals(type)) {
382
                Set libSet = (Set) organizedLibs.get(libraryName + "-" + type);
383
                if (libSet != null) {
384
                    for (Iterator iterator = libSet.iterator(); iterator
385
                        .hasNext();) {
386
                        this.add((Library) iterator.next());
387
                    }
388
                }
389
            } else {
390
                Library lib =
391
                    (Library) organizedLibs.get(libraryName + "-" + type);
392
                if (lib != null) {
393
                    this.add(lib);
394
                }
395
            }
396
        }
397

    
398
        private String getLibraryType(String libraryName, String libraryType) {
399
            if (libraryType != null) {
400
                return libraryType;
401
            }
402
            if (organizedLibs.get(libraryName + "-" + Library.TYPE.SERVICE) != null) {
403
                return Library.TYPE.SERVICE;
404
            } else
405
                if (organizedLibs.get(libraryName + "-" + Library.TYPE.IMPL) != null) {
406
                    return Library.TYPE.IMPL;
407
                } else {
408
                    return Library.TYPE.API;
409
                }
410

    
411
        }
412
    }
413
}