001    /**
002     *   GRANITE DATA SERVICES
003     *   Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004     *
005     *   This file is part of Granite Data Services.
006     *
007     *   Granite Data Services is free software; you can redistribute it and/or modify
008     *   it under the terms of the GNU Library General Public License as published by
009     *   the Free Software Foundation; either version 2 of the License, or (at your
010     *   option) any later version.
011     *
012     *   Granite Data Services is distributed in the hope that it will be useful, but
013     *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014     *   FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015     *   for more details.
016     *
017     *   You should have received a copy of the GNU Library General Public License
018     *   along with this library; if not, see <http://www.gnu.org/licenses/>.
019     */
020    package org.granite.client.platform;
021    
022    import java.util.Iterator;
023    
024    import org.granite.client.configuration.Configuration;
025    import org.granite.client.configuration.SimpleConfiguration;
026    import org.granite.client.messaging.ExtCosRemoteAliasScanner;
027    import org.granite.client.messaging.RemoteAliasScanner;
028    import org.granite.client.messaging.StandardRemoteAliasScanner;
029    import org.granite.client.messaging.transport.Transport;
030    import org.granite.client.messaging.transport.apache.ApacheAsyncTransport;
031    import org.granite.client.persistence.Persistence;
032    import org.granite.logging.Logger;
033    import org.granite.messaging.reflect.Reflection;
034    import org.granite.scan.ServiceLoader;
035    
036    /**
037     * @author Franck WOLFF
038     */
039    public class Platform {
040    
041            private static final Logger log = Logger.getLogger(Platform.class);
042            
043            public static final String SYSTEM_PROPERTY_KEY = Platform.class.getName();
044            
045            protected static Platform instance = null;
046    
047            protected final Reflection reflection;
048            protected final Persistence persistence;
049            
050            protected Object context;
051            
052            public static synchronized Platform getInstance() {
053                    
054                    if (instance == null) {
055                            String platformClassName = System.getProperty(SYSTEM_PROPERTY_KEY);
056                            
057                            if (platformClassName == null)
058                                    initInstance((ClassLoader)null);
059                            
060                            if (instance == null)
061                                    initInstance(platformClassName, null);
062                    }
063                    
064                    return instance;
065            }
066            
067            public static synchronized Platform initInstance(ClassLoader platformClassLoader) {
068                    
069                    if (instance != null)
070                            throw new IllegalStateException("Platform already loaded");
071                    
072                    if (platformClassLoader == null)
073                            platformClassLoader = Thread.currentThread().getContextClassLoader();
074                    
075                    ServiceLoader<Platform> platformLoader = ServiceLoader.load(Platform.class, platformClassLoader);
076                    
077                    Iterator<Platform> platforms = null;
078                    try {
079                            platforms = platformLoader.iterator();
080                            
081                            if (platforms.hasNext())
082                                    instance = platforms.next();
083                            
084                            if (platforms.hasNext())
085                                    throw new PlatformConfigurationError("Multiple Platform services: " + instance + " / " + platforms.next());
086                    }
087                    catch (PlatformConfigurationError e) {
088                            throw e;
089                    }
090                    catch (Throwable t) {
091                            throw new PlatformConfigurationError("Could not load Platform service", t);
092                    }
093                    
094                    return instance;
095            }
096    
097            public static synchronized Platform initInstance(String platformClassName) {
098                    return initInstance(platformClassName, null);
099            }
100    
101            public static synchronized Platform initInstance(String platformClassName, ClassLoader platformClassLoader) {
102                    return initInstance(platformClassName, platformClassLoader, null);
103            }
104            
105            public static synchronized Platform initInstance(String platformClassName, ClassLoader platformClassLoader, ClassLoader reflectionClassLoader) {
106                    
107                    if (instance != null)
108                            throw new IllegalStateException("Platform already loaded");
109                    
110                    if (platformClassLoader == null)
111                            platformClassLoader = Thread.currentThread().getContextClassLoader();
112    
113                    if (platformClassName == null)
114                            platformClassName = Platform.class.getName();
115                    
116                    try {
117                            @SuppressWarnings("unchecked")
118                            Class<? extends Platform> platformClass = (Class<? extends Platform>)platformClassLoader.loadClass(platformClassName);
119                            instance = platformClass.getConstructor(ClassLoader.class).newInstance(reflectionClassLoader);
120                    }
121                    catch (Throwable t) {
122                            throw new PlatformConfigurationError("Could not create new Platform of type: " + platformClassName, t);
123                    }
124                    
125                    return instance;
126            }
127            
128            public Platform() {
129                    this(new Reflection(null));
130            }
131            
132            public Platform(ClassLoader reflectionClassLoader) {
133                    this(new Reflection(reflectionClassLoader));
134            }
135            
136            public Platform(Reflection reflection) {
137                    if (reflection == null)
138                            throw new NullPointerException("reflection cannot be null");
139                    
140                    this.reflection = reflection;
141                    this.persistence = new Persistence(reflection);
142            }
143            
144            public Object getContext() {
145                    return context;
146            }
147    
148            public void setContext(Object context) {
149                    this.context = context;
150            }
151    
152            public RemoteAliasScanner newRemoteAliasScanner() {
153                    try {
154                            return new ExtCosRemoteAliasScanner();
155                    }
156                    catch (Throwable t) {
157                            log.debug(t, "Extcos scanner not available, using classpath scanner");
158                    }
159                    
160                    return new StandardRemoteAliasScanner();
161            }
162            
163            public Reflection getReflection() {
164                    return reflection;
165            }
166    
167            public Configuration newConfiguration() {
168                    return new SimpleConfiguration();
169            }
170            
171            public Transport newRemotingTransport() {
172                    return new ApacheAsyncTransport();
173            }
174            
175            public Transport newMessagingTransport() {
176                    return null;
177            }
178    
179            public Persistence getPersistence() {
180                    return persistence;
181            }
182    
183            public static Reflection reflection() {
184                    return getInstance().reflection;
185            }
186            
187            public static Persistence persistence() {
188                    return getInstance().persistence;
189            }
190    }