]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
2c6b1d8c0efb5de5a0e8c472833498c21ba1d165
[tmp/jakarta-migration.git] /
1 /*\r
2  * (C) Copyright 2006-2010 Nuxeo SAS (http://nuxeo.com/) and contributors.\r
3  *\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the GNU Lesser General Public License\r
6  * (LGPL) version 2.1 which accompanies this distribution, and is available at\r
7  * http://www.gnu.org/licenses/lgpl.html\r
8  *\r
9  * This library is distributed in the hope that it will be useful,\r
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
12  * Lesser General Public License for more details.\r
13  *\r
14  * Contributors:\r
15  *     bstefanescu, jcarsique\r
16  *\r
17  * $Id$\r
18  */\r
19 \r
20 package org.collectionspace.services.nuxeo.client.java;\r
21 \r
22 import java.security.Principal;\r
23 import java.util.Collection;\r
24 import java.util.HashMap;\r
25 import java.util.Iterator;\r
26 import java.util.List;\r
27 import java.util.Map;\r
28 import java.util.Set;\r
29 import java.util.Vector;\r
30 \r
31 import javax.security.auth.Subject;\r
32 import javax.security.auth.login.AppConfigurationEntry;\r
33 import javax.security.auth.login.LoginException;\r
34 import javax.security.auth.login.LoginContext;\r
35 \r
36 import org.apache.commons.logging.Log;\r
37 import org.apache.commons.logging.LogFactory;\r
38 import org.jboss.remoting.InvokerLocator;\r
39 import org.nuxeo.common.collections.ListenerList;\r
40 import org.nuxeo.ecm.core.api.ClientException;\r
41 import org.nuxeo.ecm.core.api.local.ClientLoginModule;\r
42 import org.nuxeo.ecm.core.api.local.LoginStack;\r
43 import org.nuxeo.ecm.core.api.repository.Repository;\r
44 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;\r
45 import org.nuxeo.ecm.core.api.repository.RepositoryInstanceHandler;\r
46 import org.nuxeo.ecm.core.api.repository.RepositoryManager;\r
47 import org.nuxeo.ecm.core.client.ConnectionListener;\r
48 import org.nuxeo.ecm.core.client.DefaultLoginHandler;\r
49 import org.nuxeo.ecm.core.client.LoginHandler;\r
50 import org.nuxeo.ecm.core.schema.SchemaManager;\r
51 import org.nuxeo.ecm.core.schema.SchemaManagerImpl;\r
52 import org.nuxeo.ecm.core.schema.TypeProvider;\r
53 import org.nuxeo.runtime.api.Framework;\r
54 import org.nuxeo.runtime.api.ServiceDescriptor;\r
55 import org.nuxeo.runtime.api.ServiceManager;\r
56 import org.nuxeo.runtime.api.login.LoginComponent;\r
57 import org.nuxeo.runtime.api.login.LoginService;\r
58 import org.nuxeo.runtime.api.login.SecurityDomain;\r
59 import org.nuxeo.runtime.config.AutoConfigurationService;\r
60 import org.nuxeo.runtime.remoting.RemotingService;\r
61 import org.nuxeo.runtime.services.streaming.StreamingService;\r
62 import org.nuxeo.runtime.transaction.TransactionHelper;\r
63 import org.slf4j.Logger;\r
64 import org.slf4j.LoggerFactory;\r
65 \r
66 /**\r
67  * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>\r
68  *\r
69  */\r
70 public final class NuxeoClientEmbedded {\r
71 \r
72         private Logger logger = LoggerFactory.getLogger(NuxeoClientEmbedded.class);\r
73         \r
74     private LoginHandler loginHandler;\r
75 \r
76     private final List<RepositoryInstance> repositoryInstances;\r
77 \r
78     private final ListenerList connectionListeners;\r
79 \r
80     private InvokerLocator locator;\r
81 \r
82     private String serverName;\r
83 \r
84     private final AutoConfigurationService cfg;\r
85 \r
86     private RepositoryManager repositoryMgr;\r
87 \r
88     private boolean multiThreadedLogin = false;\r
89 \r
90     private static final NuxeoClientEmbedded instance = new NuxeoClientEmbedded();\r
91 \r
92     private static final Log log = LogFactory.getLog(NuxeoClientEmbedded.class);\r
93 \r
94     /**\r
95      * Constructs a new NuxeoClient. NOTE: Using {@link #getInstance()} instead\r
96      * of this constructor is recommended.\r
97      */\r
98     public NuxeoClientEmbedded() {\r
99         connectionListeners = new ListenerList();\r
100         cfg = new AutoConfigurationService();\r
101         loginHandler = loginHandler == null ? new DefaultLoginHandler()\r
102                 : loginHandler;\r
103         repositoryInstances = new Vector<RepositoryInstance>();\r
104     }\r
105 \r
106     public static NuxeoClientEmbedded getInstance() {\r
107         return instance;\r
108     }\r
109 \r
110     public void setMultiThreadedLogin(boolean useMultiThreadedLogin) {\r
111         multiThreadedLogin = useMultiThreadedLogin;\r
112     }\r
113 \r
114     public boolean getMultiThreadedLogin() {\r
115         return multiThreadedLogin;\r
116     }\r
117 \r
118     public synchronized void connect(String locator) throws Exception {\r
119         if (this.locator != null) {\r
120             throw new IllegalStateException("Client is already connected");\r
121         }\r
122         doConnect(AutoConfigurationService.createLocator(locator));\r
123     }\r
124 \r
125     public synchronized void connect(InvokerLocator locator) throws Exception {\r
126         if (this.locator != null) {\r
127             throw new IllegalStateException("Client is already connected");\r
128         }\r
129         doConnect(locator);\r
130     }\r
131 \r
132     public synchronized void connect(String host, int port) throws Exception {\r
133         if (locator != null) {\r
134             throw new IllegalStateException("Client is already connected");\r
135         }\r
136         doConnect(AutoConfigurationService.createLocator(host, port));\r
137     }\r
138 \r
139     public synchronized void forceConnect(InvokerLocator locator)\r
140             throws Exception {\r
141         if (this.locator != null) {\r
142             disconnect();\r
143         }\r
144         doConnect(locator);\r
145     }\r
146 \r
147     public synchronized void forceConnect(String locator) throws Exception {\r
148         if (this.locator != null) {\r
149             disconnect();\r
150         }\r
151         doConnect(AutoConfigurationService.createLocator(locator));\r
152     }\r
153 \r
154     public synchronized void forceConnect(String host, int port)\r
155             throws Exception {\r
156         if (locator != null) {\r
157             disconnect();\r
158         }\r
159         doConnect(AutoConfigurationService.createLocator(host, port));\r
160     }\r
161 \r
162     public synchronized void tryConnect(String host, int port) throws Exception {\r
163         if (locator != null) {\r
164             return; // do nothing\r
165         }\r
166         doConnect(AutoConfigurationService.createLocator(host, port));\r
167     }\r
168 \r
169     public synchronized void tryConnect(String url) throws Exception {\r
170         if (locator != null) {\r
171             return; // do nothing\r
172         }\r
173         doConnect(AutoConfigurationService.createLocator(url));\r
174     }\r
175 \r
176     public synchronized void tryConnect(InvokerLocator locator)\r
177             throws Exception {\r
178         if (this.locator != null) {\r
179             return; // do nothing\r
180         }\r
181         doConnect(locator);\r
182     }\r
183 \r
184     @Deprecated\r
185     private void doConnect(InvokerLocator locator) throws Exception {\r
186         this.locator = locator;\r
187         try {\r
188             cfg.load(locator);\r
189             // FIXME TODO workaround to work with nxruntime core 1.3.3\r
190             // --------------\r
191             String newPort = Framework.getProperty("org.nuxeo.runtime.1.3.3.streaming.port");\r
192             if (newPort != null) {\r
193                 StreamingService streamingService = (StreamingService) Framework.getRuntime().getComponent(\r
194                         StreamingService.NAME);\r
195                 // streaming config\r
196                 String oldLocator = streamingService.getServerLocator();\r
197                 int p = oldLocator.lastIndexOf(':');\r
198                 if (p > -1) {\r
199                     String withoutPort = oldLocator.substring(0, p);\r
200                     String serverLocator = withoutPort + ":" + newPort;\r
201                     streamingService.stopManager();\r
202                     streamingService.setServerLocator(serverLocator);\r
203                     streamingService.setServer(false);\r
204                     streamingService.startManager();\r
205                 }\r
206             }\r
207             // FIXME TODO workaround for remote services\r
208             // -------------------------------\r
209             schemaRemotingWorkaround(locator.getHost());\r
210             // workaround for client login configuration - we need to make it\r
211             // not multi threaded\r
212             // TODO put an option for this in NuxeoClient\r
213             if (!multiThreadedLogin) {\r
214                 LoginService ls = Framework.getService(LoginService.class);\r
215                 SecurityDomain sysDomain = ls.getSecurityDomain(LoginComponent.SYSTEM_LOGIN);\r
216                 SecurityDomain clientDomain = ls.getSecurityDomain(LoginComponent.CLIENT_LOGIN);\r
217                 adaptClientSecurityDomain(sysDomain);\r
218                 adaptClientSecurityDomain(clientDomain);\r
219             }\r
220             // ----------------\r
221 //            login();\r
222             if (!multiThreadedLogin) {\r
223                 throw new RuntimeException("This coode is dead and should never be called?"); //FIXME: REM - If you're reading this, this was left here by mistake and should be removed.\r
224             }\r
225         } catch (Exception e) {\r
226             this.locator = null;\r
227             throw e;\r
228         }\r
229         fireConnected(this);\r
230     }\r
231 \r
232     public static void adaptClientSecurityDomain(SecurityDomain sd) {\r
233         AppConfigurationEntry[] entries = sd.getAppConfigurationEntries();\r
234         if (entries != null) {\r
235             for (int i = 0; i < entries.length; i++) {\r
236                 AppConfigurationEntry entry = entries[i];\r
237                 if ("org.jboss.security.ClientLoginModule".equals(entry.getLoginModuleName())) {\r
238                     Map<String, ?> opts = entry.getOptions();\r
239                     Map<String, Object> newOpts = new HashMap<String, Object>(\r
240                             opts);\r
241                     newOpts.put("multi-threaded", "false");\r
242                     entries[i] = new AppConfigurationEntry(\r
243                             entry.getLoginModuleName(), entry.getControlFlag(),\r
244                             entry.getOptions());\r
245                 }\r
246             }\r
247         }\r
248     }\r
249 \r
250     /**\r
251      * Workaround for being able to load schemas from remote\r
252      * TODO integrate this in core\r
253      */\r
254     private static void schemaRemotingWorkaround(String host) throws Exception {\r
255         ServiceManager serviceManager = Framework.getLocalService(ServiceManager.class);\r
256         ServiceDescriptor sd = new ServiceDescriptor(TypeProvider.class, "core");\r
257         sd.setLocator("%TypeProviderBean");\r
258         serviceManager.registerService(sd);\r
259         TypeProvider typeProvider = Framework.getService(TypeProvider.class);\r
260         SchemaManager schemaMgr = Framework.getLocalService(SchemaManager.class);\r
261         ((SchemaManagerImpl) schemaMgr).importTypes(typeProvider);\r
262     }\r
263 \r
264     public synchronized void disconnect() throws Exception {\r
265         if (locator == null) {\r
266             throw new IllegalStateException("Client is not connected");\r
267         }\r
268         doDisconnect();\r
269     }\r
270 \r
271     public synchronized void tryDisconnect() throws Exception {\r
272         if (locator == null) {\r
273             return; // do nothing\r
274         }\r
275         doDisconnect();\r
276     }\r
277 \r
278     @Deprecated\r
279     private void doDisconnect() throws Exception {\r
280         locator = null;\r
281         serverName = null;\r
282         // close repository sessions if any\r
283         Iterator<RepositoryInstance> it = repositoryInstances.iterator();\r
284         while (it.hasNext()) {\r
285             RepositoryInstance repo = it.next();\r
286             try {\r
287                 repo.close();\r
288             } catch (Exception e) {\r
289                 log.debug("Error while trying to close " + repo, e);\r
290             }\r
291             it.remove();\r
292         }\r
293         // logout\r
294 //        logout();\r
295         if (!multiThreadedLogin) {\r
296                 throw new RuntimeException("This coode is dead and should never be called?"); //FIXME: REM - If you're reading this, this was left here by mistake and should be removed.\r
297         }\r
298         repositoryMgr = null;\r
299         fireDisconnected(this);\r
300     }\r
301 \r
302     public synchronized void reconnect() throws Exception {\r
303         if (locator == null) {\r
304             throw new IllegalStateException("Client is not connected");\r
305         }\r
306         InvokerLocator locator = this.locator;\r
307         disconnect();\r
308         connect(locator);\r
309     }\r
310 \r
311     public AutoConfigurationService getConfigurationService() {\r
312         return cfg;\r
313     }\r
314 \r
315     public synchronized String getServerName() {\r
316         if (locator == null) {\r
317             throw new IllegalStateException("Client is not connected");\r
318         }\r
319         if (serverName == null) {\r
320             if (cfg == null) { // compatibility\r
321                 serverName = RemotingService.ping(locator.getHost(),\r
322                         locator.getPort());\r
323             } else {\r
324                 serverName = cfg.getServerConfiguration().getProductInfo();\r
325             }\r
326         }\r
327         return serverName;\r
328     }\r
329 \r
330     public synchronized boolean isConnected() {\r
331         return true;\r
332     }\r
333 \r
334     public String getServerHost() {\r
335         if (locator == null) {\r
336             throw new IllegalStateException("Client is not connected");\r
337         }\r
338         return locator.getHost();\r
339     }\r
340 \r
341     public int getServerPort() {\r
342         if (locator == null) {\r
343             throw new IllegalStateException("Client is not connected");\r
344         }\r
345         return locator.getPort();\r
346     }\r
347 \r
348     public InvokerLocator getLocator() {\r
349         return locator;\r
350     }\r
351 \r
352     public synchronized LoginHandler getLoginHandler() {\r
353         return loginHandler;\r
354     }\r
355 \r
356     public synchronized void setLoginHandler(LoginHandler loginHandler) {\r
357         this.loginHandler = loginHandler;\r
358     }\r
359 \r
360     public RepositoryManager getRepositoryManager() throws Exception {\r
361         if (repositoryMgr == null) {\r
362             repositoryMgr = Framework.getService(RepositoryManager.class);\r
363         }\r
364         return repositoryMgr;\r
365     }\r
366 \r
367     /**\r
368      * Gets the repositories available on the connected server.\r
369      *\r
370      * @return the repositories\r
371      */\r
372     public Repository[] getRepositories() throws Exception {\r
373         Collection<Repository> repos = getRepositoryManager().getRepositories();\r
374         return repos.toArray(new Repository[repos.size()]);\r
375     }\r
376 \r
377     public Repository getDefaultRepository() throws Exception {\r
378         return getRepositoryManager().getDefaultRepository();\r
379     }\r
380 \r
381     public Repository getRepository(String name) throws Exception {\r
382         return getRepositoryManager().getRepository(name);\r
383     }\r
384 \r
385     public RepositoryInstance openRepository() throws Exception {\r
386         return openRepository(null);\r
387     }\r
388 \r
389     public RepositoryInstance openRepository(String name) throws Exception {\r
390         boolean startTransaction = TransactionHelper.startTransaction();\r
391         if (startTransaction == false) {\r
392                 logger.warn("Could not start a Nuxeo transaction with the TransactionHelper class.");\r
393         }\r
394         \r
395         Repository repository = null;\r
396         if (name != null) {\r
397                 repository = getRepositoryManager().getRepository(name);\r
398         } else {\r
399                 repository = getRepositoryManager().getDefaultRepository();\r
400         }\r
401         RepositoryInstance repo = newRepositoryInstance(repository);\r
402         repositoryInstances.add(repo);\r
403 \r
404         return repo;\r
405     }\r
406 \r
407     public void releaseRepository(RepositoryInstance repo) throws Exception {\r
408         try {\r
409                 repo.save();\r
410             repo.close();\r
411         } catch (Exception e) {\r
412                 logger.error("Could not save and/or release the repository.", e);\r
413                 throw e;\r
414         } finally {\r
415             repositoryInstances.remove(repo);\r
416             TransactionHelper.commitOrRollbackTransaction();\r
417         }\r
418     }\r
419 \r
420     public RepositoryInstance[] getRepositoryInstances() {\r
421         return repositoryInstances.toArray(new RepositoryInstance[repositoryInstances.size()]);\r
422     }\r
423 \r
424     public static RepositoryInstance newRepositoryInstance(Repository repository) {\r
425         ClassLoader cl = Thread.currentThread().getContextClassLoader();\r
426         if (cl == null) {\r
427             cl = NuxeoClientEmbedded.class.getClassLoader();\r
428         }\r
429         return new RepositoryInstanceHandler(repository).getProxy();\r
430     }\r
431 \r
432     public void addConnectionListener(ConnectionListener listener) {\r
433         connectionListeners.add(listener);\r
434     }\r
435 \r
436     public void removeConnectionListener(ConnectionListener listener) {\r
437         connectionListeners.remove(listener);\r
438     }\r
439 \r
440     private void fireDisconnected(NuxeoClientEmbedded client) {\r
441         Object[] listeners = connectionListeners.getListeners();\r
442         for (Object listener : listeners) {\r
443 //            ((ConnectionListener) listener).disconnected(client);\r
444         }\r
445     }\r
446 \r
447     private void fireConnected(NuxeoClientEmbedded client) {\r
448         Object[] listeners = connectionListeners.getListeners();\r
449         for (Object listener : listeners) {\r
450 //            ((ConnectionListener) listener).connected(client);\r
451         }\r
452     }    \r
453 }\r