KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas > resource > Rar


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999-2005 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: Rar.java,v 1.37 2005/04/29 11:18:34 benoitf Exp $
23  * --------------------------------------------------------------------------
24  */

25
26
27 package org.objectweb.jonas.resource;
28
29 import java.io.File JavaDoc;
30 import java.net.URL JavaDoc;
31 import java.util.Enumeration JavaDoc;
32 import java.util.Hashtable JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.List JavaDoc;
35 import java.util.Properties JavaDoc;
36 import java.util.Vector JavaDoc;
37 import java.util.jar.JarEntry JavaDoc;
38
39 import javax.management.InstanceNotFoundException JavaDoc;
40 import javax.management.MBeanRegistrationException JavaDoc;
41 import javax.management.MBeanServer JavaDoc;
42 import javax.management.MalformedObjectNameException JavaDoc;
43 import javax.management.ObjectName JavaDoc;
44 import javax.management.modelmbean.ModelMBean JavaDoc;
45 import javax.naming.Context JavaDoc;
46 import javax.naming.InitialContext JavaDoc;
47 import javax.naming.NamingException JavaDoc;
48 import javax.resource.Referenceable JavaDoc;
49 import javax.resource.spi.ActivationSpec JavaDoc;
50 import javax.resource.spi.ConnectionManager JavaDoc;
51 import javax.resource.spi.ManagedConnectionFactory JavaDoc;
52 import javax.resource.spi.ResourceAdapter JavaDoc;
53 import javax.resource.spi.ResourceAdapterAssociation JavaDoc;
54 import javax.resource.spi.ResourceAllocationException JavaDoc;
55 import javax.resource.spi.work.WorkManager JavaDoc;
56
57 import org.apache.commons.modeler.ManagedBean;
58 import org.apache.commons.modeler.Registry;
59
60 import org.objectweb.transaction.jta.TransactionManager;
61
62 import org.objectweb.jonas_ejb.deployment.api.ActivationConfigPropertyDesc;
63
64 import org.objectweb.jonas_rar.deployment.api.AdminobjectDesc;
65 import org.objectweb.jonas_rar.deployment.api.AuthenticationMechanismDesc;
66 import org.objectweb.jonas_rar.deployment.api.ConfigPropertyDesc;
67 import org.objectweb.jonas_rar.deployment.api.ConnectionDefinitionDesc;
68 import org.objectweb.jonas_rar.deployment.api.ConnectorDesc;
69 import org.objectweb.jonas_rar.deployment.api.InboundResourceadapterDesc;
70 import org.objectweb.jonas_rar.deployment.api.JonasActivationspecDesc;
71 import org.objectweb.jonas_rar.deployment.api.JonasAdminobjectDesc;
72 import org.objectweb.jonas_rar.deployment.api.JonasConnectionDefinitionDesc;
73 import org.objectweb.jonas_rar.deployment.api.JonasConnectorDesc;
74 import org.objectweb.jonas_rar.deployment.api.MessageadapterDesc;
75 import org.objectweb.jonas_rar.deployment.api.MessagelistenerDesc;
76 import org.objectweb.jonas_rar.deployment.api.OutboundResourceadapterDesc;
77 import org.objectweb.jonas_rar.deployment.api.RarDeploymentDesc;
78 import org.objectweb.jonas_rar.deployment.api.RequiredConfigPropertyDesc;
79 import org.objectweb.jonas_rar.deployment.api.ResourceadapterDesc;
80 import org.objectweb.jonas_rar.deployment.api.TmConfigPropertyDesc;
81 import org.objectweb.jonas_rar.deployment.lib.wrapper.RarManagerWrapper;
82
83 import org.objectweb.jonas.common.JJarFile;
84 import org.objectweb.jonas.common.Log;
85 import org.objectweb.jonas.ear.EarServiceImpl;
86 import org.objectweb.jonas.jmx.J2eeObjectName;
87 import org.objectweb.jonas.jmx.JmxService;
88 import org.objectweb.jonas.jmx.JonasObjectName;
89 import org.objectweb.jonas.jtm.TransactionService;
90 import org.objectweb.jonas.management.JonasMBeanTools;
91 import org.objectweb.jonas.service.ServiceException;
92 import org.objectweb.jonas.service.ServiceManager;
93
94 import org.objectweb.util.monolog.api.BasicLevel;
95 import org.objectweb.util.monolog.api.Logger;
96
97 /**
98  * Rar object
99  * @author Eric Hardesty
100  */

101
102 public class Rar {
103
104     /**
105      * Main logger
106      */

107     private static Logger logger = null;
108     /**
109      * Pool infomation logger
110      */

111     private static Logger poolLogger = null;
112     /**
113      * Config property setter logger
114      */

115     private static Logger setterLogger = null;
116     /**
117      * Management logger
118      */

119     private static Logger manageLogger = null;
120
121     String JavaDoc rarFileName = null;
122     ClassLoader JavaDoc curLoader = null;
123     boolean isInEar;
124     URL JavaDoc earUrl = null;
125     Context JavaDoc rCtx = null;
126     String JavaDoc jDomain = null;
127     String JavaDoc jServer = null;
128     Vector JavaDoc jndinames = new Vector JavaDoc();
129
130     String JavaDoc lnkJndiName = "";
131     String JavaDoc lnkRarFilename = "";
132
133     JCAResource jcaResourceMBean = null;
134     String JavaDoc JCAResourceName = null;
135     Registry oRegistry = null;
136
137     // J2EE CA 1.5 objects
138
private WorkManager JavaDoc workMgr = null;
139     private ResourceBootstrapContext bootCtx = null;
140
141     // Properties for inits
142

143     // JCA resource service configuration parameters
144
public static final String JavaDoc CLASS = "jonas.service.resource.class";
145     public static final String JavaDoc JNDI_NAME = "jndiname";
146     public static final String JavaDoc RAR_FILENAME = "rarfilename";
147     public static final String JavaDoc LNK_JNDI_NAME = "lnkjndiname";
148     public static final String JavaDoc LNK_RAR_FILENAME = "lnkrarfilename";
149     public static final String JavaDoc OBJ_TYPE = "objtype";
150     public static final String JavaDoc RESOURCE_LIST = "jonas.service.resource.resources";
151
152     public static final int DEF_WRK_THREADS = 5;
153     public static final int DEF_EXEC_TIME = 0;
154
155     public static final String JavaDoc JCD = "JCD";
156     public static final String JavaDoc JAS = "JAS";
157     public static final String JavaDoc JAO = "JAO";
158
159     public String JavaDoc objectName = null;
160     public String JavaDoc pathName = null;
161     public ResourceAdapter resAdp = null;
162     public ConnectorDesc raConn = null;
163     public JonasConnectorDesc lnkJonasConn = null;
164     public JonasConnectorDesc jonasConn = null;
165
166     public String JavaDoc xmlContent = null;
167     public String JavaDoc jonasXmlContent = null;
168
169
170     private class ConfigObj {
171         public String JavaDoc type;
172         public int offset;
173         public String JavaDoc jndiName;
174         public String JavaDoc rarFilename;
175         public String JavaDoc lnkJndiName;
176         public String JavaDoc lnkRarFilename;
177         public String JavaDoc interfaceStr;
178         public String JavaDoc classStr;
179         public Object JavaDoc factory;
180         public ConnectionManager JavaDoc cm;
181         public boolean basicPass;
182         public boolean defaultAS;
183         public List JavaDoc reqConfigProps;
184         public ConfigObj(String JavaDoc fType, int off, String JavaDoc jndi, String JavaDoc fName,
185                           String JavaDoc intStr, String JavaDoc clsStr, Object JavaDoc fact) {
186             type = fType;
187             offset = off;
188             jndiName = jndi;
189             rarFilename = fName;
190             interfaceStr = intStr;
191             classStr = clsStr;
192             factory = fact;
193             cm = null;
194             reqConfigProps = null;
195             lnkJndiName = "";
196             lnkRarFilename = "";
197             defaultAS = false;
198         }
199     }
200
201     /**
202      * Hold list of default ActivationSpecs
203      */

204     private static Vector JavaDoc defaultAS = new Vector JavaDoc();
205
206     /**
207      * Hashtable mapping a filename to an RAR object
208      */

209     public static Hashtable JavaDoc fileName2RA = new Hashtable JavaDoc();
210     /**
211      * These hashtables associate an RAR with other objects
212      */

213     public static Hashtable JavaDoc jndiName2RA = new Hashtable JavaDoc();
214
215     private Hashtable JavaDoc cfgObjs = new Hashtable JavaDoc();
216     /**
217      * Hashtable mapping a jndiname to an "external" factory
218      */

219     private static Hashtable JavaDoc jndiName2Factory = new Hashtable JavaDoc();
220
221     /**
222      * The transaction manager in the server
223      */

224     private TransactionManager tm = null;
225
226     /**
227      * Reference to a MBean server.
228      */

229     private MBeanServer JavaDoc mbeanServer = null;
230
231     /**
232      * ObjectName for the jcaResource
233      */

234     private String JavaDoc jcaResourceObjectName = null;
235
236     /**
237      * The ConnectionManager manages connections of resource adapters
238      * and more exactly the association between logical connections,
239      * physical connections, local transactions and global transaction(XA)
240      */

241     private ConnectionManagerImpl cm = null;
242
243     /**
244      * JNDI Context
245      */

246     private Context JavaDoc ictx = null;
247
248     /**
249      * Resource Utility factory
250      */

251     ResourceUtility ru = null;
252
253     /**
254      * - Get the loggers
255      * - Get the global jndi context
256      * - Get the list of the resource adapters. The list is reachable in the
257      * - context parameter under the name RESOURCE_LIST.
258      * - Get the transaction manager into the jndi
259      * - Set the XML validation property
260      */

261     public Rar() {
262         if (logger == null) {
263             logger = Log.getLogger(Log.JONAS_JCA_PREFIX+".process");
264         }
265         if (poolLogger == null) {
266             poolLogger = Log.getLogger(Log.JONAS_JCA_PREFIX+".pool");
267         }
268         if (setterLogger == null) {
269             setterLogger = Log.getLogger(Log.JONAS_JCA_PREFIX+".setters");
270         }
271         if (manageLogger == null) {
272             manageLogger = Log.getLogger(Log.JONAS_JCA_PREFIX+".management");
273         }
274
275         curLoader = Thread.currentThread().getContextClassLoader();
276
277         ru = new ResourceUtility(null, null, logger, setterLogger, manageLogger);
278     }
279
280     /**
281      * - Get the loggers
282      * - Get the global jndi context
283      * - Get the list of the resource adapters. The list is reachable in the
284      * - context parameter under the name RESOURCE_LIST.
285      * - Get the transaction manager into the jndi
286      * - Set the XML validation property
287      */

288     public Rar(Context JavaDoc ctx, String JavaDoc jDom, String JavaDoc jServ,
289                 WorkManager JavaDoc wrkMgr, ResourceBootstrapContext btCtx) {
290         if (logger == null) {
291             logger = Log.getLogger(Log.JONAS_JCA_PREFIX + ".process");
292         }
293         if (poolLogger == null) {
294             poolLogger = Log.getLogger(Log.JONAS_JCA_PREFIX + ".pool");
295         }
296         if (setterLogger == null) {
297             setterLogger = Log.getLogger(Log.JONAS_JCA_PREFIX + ".setters");
298         }
299         if (manageLogger == null) {
300             manageLogger = Log.getLogger(Log.JONAS_JCA_PREFIX + ".management");
301         }
302
303         try {
304             rarFileName = (String JavaDoc) ctx.lookup("rarFileName");
305             isInEar = ((Boolean JavaDoc) ctx.lookup("isInEar")).booleanValue();
306             if (isInEar) {
307                 earUrl = (URL JavaDoc) ctx.lookup("earUrl");
308             }
309             curLoader = (ClassLoader JavaDoc) ctx.lookup("classloader");
310         } catch (NamingException JavaDoc e) {
311             String JavaDoc err = "Error while getting parameter from context param.";
312             logger.log(BasicLevel.ERROR, err + e.getMessage());
313             throw new ResourceServiceException(err, e);
314         } catch (Exception JavaDoc ex) {
315             String JavaDoc err = "Error while getting parameter from context param.";
316             logger.log(BasicLevel.ERROR, err + ex.getMessage());
317             throw new ResourceServiceException(err, ex);
318         }
319
320         workMgr = wrkMgr;
321         bootCtx = btCtx;
322         rCtx = ctx;
323         jDomain = jDom;
324         jServer = jServ;
325
326         // Avoid using NamingManager here: performance is not a goal here.
327
try {
328             ictx = new InitialContext JavaDoc();
329         } catch (NamingException JavaDoc e) {
330             logger.log(BasicLevel.ERROR, "Cannot create initial context when Resource service initializing");
331             throw new ServiceException("Cannot create initial context when Resource service initializing", e);
332         }
333
334         // Get a reference to the Transaction service
335
try {
336             ServiceManager sm = ServiceManager.getInstance();
337             TransactionService ts = (TransactionService) sm.getTransactionService();
338             tm = ts.getTransactionManager();
339         } catch (Exception JavaDoc e) {
340             logger.log(BasicLevel.ERROR, "Cannot get the Transaction service: " + e);
341             throw new ServiceException("Cannot get the Transaction service: ", e);
342         }
343
344         // Get the JMX Server via JMX Service
345
try {
346             mbeanServer =
347                 ((JmxService) ServiceManager.getInstance().getJmxService()).getJmxServer();
348         } catch (Exception JavaDoc e) {
349             // the JMX service may not be started
350
mbeanServer = null;
351         }
352
353         // Use Jakarta Common Modeler API
354
oRegistry = JonasMBeanTools.getRegistry();
355
356         ru = new ResourceUtility(mbeanServer, oRegistry, logger, setterLogger, manageLogger);
357     }
358
359     /**
360      * Process the resource adapter. This Resource Adapter is configured via
361      * xml files in the rar file
362      */

363     public Context JavaDoc processRar() throws Exception JavaDoc {
364
365         String JavaDoc onRar = null;
366         // Get the ra.xml and jonas-ra.xml descriptions
367
RarDeploymentDesc radesc = null;
368         ConnectorDesc conn = null;
369         JonasConnectorDesc jConn = null;
370         xmlContent = null;
371         jonasXmlContent = null;
372         ConnectionManager JavaDoc cm = null;
373         ManagedConnectionFactory JavaDoc mcf = null;
374
375         radesc = RarManagerWrapper.getInstance(rCtx);
376         conn = radesc.getConnectorDesc();
377         jConn = radesc.getJonasConnectorDesc();
378         xmlContent = radesc.getXmlContent();
379         jonasXmlContent = radesc.getJOnASXmlContent();
380
381         if(conn == null && jConn == null) {
382             logger.log(BasicLevel.ERROR, "Rar.processRar: Resource (" + rarFileName
383                                          + ") must be a valid RAR file.");
384             throw new Exception JavaDoc("resource input file incorrect");
385         }
386
387         // Need to check if rarlink is specified. If yes and has been processed, then get the correct
388
// Connector object and continue, if it has not been processed, then add this rar to the
389
// deferred list and it will be processed at end of the rar files. If no rarlink, then
390
// make sure that the connector object is valid.
391
String JavaDoc rarVal = null;
392         if (jConn != null) {
393             rarVal = (jConn.getRarlink() == null
394                       ? null
395                       : jConn.getRarlink());
396             if (rarVal != null && rarVal.length() > 0) {
397                 lnkJndiName = rarVal;
398                 conn = getConnectorDesc(rarVal);
399                 if (conn == null) {
400                     return rCtx;
401                 }
402                 ConfigObj co = (ConfigObj) getConfigObject(rarVal);
403                 lnkRarFilename = co.rarFilename;
404                 xmlContent = getXmlContent(rarVal);
405                 // Get the config parameters
406
lnkJonasConn = getJonasConnectorDesc(rarVal);
407             } else if (conn == null) {
408                 logger.log(BasicLevel.ERROR, "Rar.processRar: Resource (" + rarFileName
409                                              + ") is not valid.");
410                 throw new Exception JavaDoc("resource input file incorrect: no ra.xml file");
411             }
412             bldSecurityTable(lnkJonasConn, jConn);
413             raConn = conn;
414             jonasConn = jConn;
415         } else {
416             logger.log(BasicLevel.ERROR, "Rar.processRar: Resource (" + rarFileName
417                                          + ") must be a valid RAR file, there must be jonas-ra.xml file.");
418             throw new Exception JavaDoc("resource input file incorrect: no jonas-ra.xml file");
419         }
420
421         // Setup the global pool parameters
422
ConnectionManagerPoolParams pParams =
423                 ru.configurePoolParams(jConn.getPoolParamsDesc(),
424                                        jConn.getJdbcConnParamsDesc(),
425                                        null);
426
427         // Process the RAR file adding each of the jar files into the classloader and if the
428
// native-lib is defined then place all other files into that directory.
429

430         extractJars(rarFileName, jConn);
431
432         // Process the config values
433
ResourceadapterDesc ra = conn.getResourceadapterDesc();
434
435         // Check Authentication Mechanisms, must if some exist then BasicPassword
436
// must be present
437
boolean basicPass = true;
438         List JavaDoc authList = ra.getAuthenticationMechanismList();
439         if (authList != null && authList.size() > 0) {
440             basicPass = false;
441             for (Iterator JavaDoc i = authList.iterator(); i.hasNext();) {
442                 AuthenticationMechanismDesc am = (AuthenticationMechanismDesc) i.next();
443                 if (am.getAuthenticationMechanismType().equalsIgnoreCase("BasicPassword")) {
444                     basicPass = true;
445                     break;
446                 }
447             }
448             if (!basicPass) {
449                 logger.log(BasicLevel.ERROR, "Rar.processRar: Resource (" + rarFileName + ") doesn't contain an AuthenticationMechanismType that is supported by JOnAS(BasicPassword).");
450                 throw new Exception JavaDoc("No AuthenticationMechanismType that is supported by JOnAS(BasicPassword).");
451             }
452         }
453
454         ConfigPropertyDesc [] cfgRaJonas = null;
455
456         String JavaDoc logEnabled = null;
457         if (jConn.getLogEnabled() != null) {
458             logEnabled = jConn.getLogEnabled().trim();
459         }
460         String JavaDoc logTopic = null;
461         if (jConn.getLogTopic() != null) {
462             logTopic = jConn.getLogTopic().trim();
463         }
464
465         Referenceable JavaDoc cf = null;
466         String JavaDoc jndiName = null;
467         String JavaDoc mcfc = null;
468         ConfigObj cObj = null;
469
470         if (lnkJonasConn != null) {
471             cfgRaJonas = ru.buildConfigProperty(ra.getConfigPropertyList(),
472                                                 jConn.getJonasConfigPropertyList(),
473                                                 lnkJonasConn.getJonasConfigPropertyList());
474         } else {
475             cfgRaJonas = ru.buildConfigProperty(ra.getConfigPropertyList(),
476                                                 jConn.getJonasConfigPropertyList(),
477                                                 null);
478         }
479
480         Properties JavaDoc tmProp = new Properties JavaDoc();
481         if (jConn.getTmParamsDesc() != null) {
482             List JavaDoc tmParams = jConn.getTmParamsDesc().getTmConfigPropertyList();
483             if (tmParams != null) {
484                 for (Iterator JavaDoc i = tmParams.iterator(); i.hasNext();) {
485                     TmConfigPropertyDesc tpd = (TmConfigPropertyDesc) i.next();
486                     String JavaDoc tpdVal = tpd.getTmConfigPropertyValue();
487                     if (tpdVal == null) {
488                         tpdVal = "";
489                     }
490                     tmProp.setProperty(tpd.getTmConfigPropertyName(), tpdVal);
491                 }
492                 if (logger.isLoggable(BasicLevel.DEBUG)) {
493                     logger.log(BasicLevel.DEBUG, "TM Properties: " + tmProp);
494                 }
495             }
496         }
497
498         String JavaDoc specVersion = conn.getSpecVersion();
499         if (specVersion.equals("1.0")) {
500             jndiName = jConn.getJndiName().trim();
501             ConnectionManagerPoolParams cmpp = ru.configurePoolParams(jConn.getPoolParamsDesc(),
502                                                jConn.getJdbcConnParamsDesc(), null);
503             onRar = registerRarMBean(cfgRaJonas, specVersion, jndiName);
504             cm = ru.createConnectionManager(ra.getTransactionSupport(), tm,
505                                             logger, poolLogger);
506             // Only need to build an MCF for a 1.0 resource adapter
507
mcfc = ra.getManagedconnectionfactoryClass();
508             mcf = (ManagedConnectionFactory JavaDoc) ru.processMCF(conn, jConn, cm, curLoader, rarFileName,
509                                                            mcfc,
510                                                            jndiName, logEnabled, logTopic,
511                                                            cfgRaJonas, resAdp, 0);
512             ((ConnectionManagerImpl) cm).setResourceAdapter(mcf, cmpp);
513
514             cf = (Referenceable JavaDoc) mcf.createConnectionFactory(cm);
515
516             // Add entry to list of configured objects
517
cObj = new ConfigObj(JCD, 0, jndiName, rarFileName, null, mcfc, cf);
518             cObj.cm = cm;
519             cObj.basicPass = basicPass;
520
521             cfgObjs.put(jndiName, cObj);
522
523             jndinames.add(jndiName);
524
525             ru.registerMBean(cf, jndiName, onRar, conn, jonasConn, JCD, 0,
526                              jcaResourceMBean, JCAResourceName, jDomain, jServer, ictx,
527                              buildProp(cfgRaJonas), "", (ConnectionManagerImpl)cm);
528             ((ConnectionManagerImpl) cm).setXAName(ru.getJcaMcfName(jndiName));
529             ((ConnectionManagerImpl) cm).registerXAResource(tmProp);
530
531         } else if (conn.getSpecVersion().equals("1.5")) {
532             String JavaDoc raStr = conn.getResourceadapterDesc().getResourceadapterClass().trim();
533             boolean isResAdapt = false;
534             logger.log(BasicLevel.INFO, "Starting deployment of " + rarFileName);
535             if (raStr != null && raStr.length() > 0) {
536                 isResAdapt = true;
537
538                 // Instantiate the resource adapter class
539
Class JavaDoc raClass = curLoader.loadClass(raStr);
540                 resAdp = (ResourceAdapter) raClass.newInstance();
541
542                 ru.processSetters(raClass, resAdp, rarFileName, cfgRaJonas);
543
544                 // Call Resourceadapter start method
545
try {
546                     resAdp.start(bootCtx);
547                 } catch (Exception JavaDoc ex) {
548                     logger.log(BasicLevel.ERROR, "Rar: Error from resource ("
549                                                  + rarFileName + ") start method.");
550                     throw new Exception JavaDoc("Error from start method. " + ex);
551                 } catch (Throwable JavaDoc th) {
552                     logger.log(BasicLevel.ERROR, "Rar: Error from resource ("
553                                                  + rarFileName + ") start method.");
554                     throw new Exception JavaDoc("Error from start method. ", th);
555                 }
556             }
557
558             onRar = registerRarMBean(cfgRaJonas, specVersion, null);
559
560             // Loop thru ConnectionDefinition(outbound) factories
561
OutboundResourceadapterDesc outRa = ra.getOutboundResourceadapterDesc();
562             List JavaDoc cdList = null;
563             if (outRa != null) {
564                 cdList = outRa.getConnectionDefinitionList();
565             }
566             ConnectionDefinitionDesc conDef = null;
567             JonasConnectionDefinitionDesc jConDef = null;
568             String JavaDoc id = null;
569             int idOffset = -1;
570             if (cdList != null) {
571                 for (int cd = 0; cd < cdList.size(); cd++) {
572                     conDef = (ConnectionDefinitionDesc) cdList.get(cd);
573                     id = conDef.getId();
574                     idOffset++;
575                     jConDef = (JonasConnectionDefinitionDesc)
576                                ru.getJonasXML(jConn, id, idOffset, JCD);
577
578
579                     if (jConDef.getLogEnabled() != null) {
580                         logEnabled = jConDef.getLogEnabled().trim();
581                     }
582                     if (jConDef.getLogTopic() != null) {
583                         logTopic = jConDef.getLogTopic().trim();
584                     }
585                     ConfigPropertyDesc [] cfgCdDesc =
586                                  ru.buildConfigProperty(conDef.getConfigPropertyList(),
587                                                         jConDef.getJonasConfigPropertyList(),
588                                                         null);
589                     ConnectionManagerPoolParams pool =
590                         ru.configurePoolParams(jConDef.getPoolParamsDesc(),
591                                                jConDef.getJdbcConnParamsDesc(),
592                                                pParams);
593                     cm = ru.createConnectionManager(outRa.getTransactionSupport(), tm,
594                             logger, poolLogger);
595
596                     jndiName = jConDef.getJndiName().trim();
597                     mcfc = conDef.getManagedconnectionfactoryClass();
598                     mcf = (ManagedConnectionFactory JavaDoc)
599                                      ru.processMCF(conn, jConn, cm, curLoader, rarFileName,
600                                                    mcfc, jndiName, logEnabled, logTopic,
601                                                    cfgCdDesc, resAdp, idOffset);
602                     ((ConnectionManagerImpl) cm).setResourceAdapter(mcf, pool);
603
604                     cf = (Referenceable JavaDoc) mcf.createConnectionFactory(cm);
605
606                     // Add entry to list of configured objects
607
cObj = new ConfigObj(JCD, idOffset, jndiName, rarFileName, null, mcfc, cf);
608                     cObj.cm = cm;
609                     cObj.basicPass = basicPass;
610
611                     cfgObjs.put(jndiName, cObj);
612
613                     jndinames.add(jndiName);
614
615                     String JavaDoc desc = "";
616                     List JavaDoc descList = jConDef.getDescriptionList();
617                     if (descList != null) {
618                         for (int i = 0; i < descList.size(); i++) {
619                             String JavaDoc tmp = (String JavaDoc) descList.get(i);
620                             desc = desc + tmp;
621                         }
622                     }
623                     ru.registerMBean(cf, jndiName, onRar, conn, jonasConn, JCD, idOffset,
624                             jcaResourceMBean, JCAResourceName, jDomain, jServer, ictx,
625                             buildProp(cfgCdDesc), desc, (ConnectionManagerImpl)cm);
626
627                     ((ConnectionManagerImpl) cm).setXAName(ru.getJcaMcfName(jndiName));
628                     ((ConnectionManagerImpl) cm).registerXAResource(tmProp);
629                 }
630             }
631
632             // We only want to do anything with Inbound or Adminobjects if the Resourceadapter
633
// class was specified, otherwise it is a 1.0 RAR with a 1.5 ra.xml
634
if (isResAdapt) {
635                 // Loop thru Messagelisteners (inbound) factories
636
InboundResourceadapterDesc inAdapt = ra.getInboundResourceadapterDesc();
637                 MessageadapterDesc msgAdapt = null;
638                 List JavaDoc mlList = null;
639                 if (inAdapt != null) {
640                     msgAdapt = inAdapt.getMessageadapterDesc();
641                     mlList = null;
642                     if (msgAdapt != null) {
643                         mlList = msgAdapt.getMessagelistenerList();
644                     }
645                 }
646                 MessagelistenerDesc msgList = null;
647                 JonasActivationspecDesc jAct = null;
648                 id = null;
649                 idOffset = -1;
650                 if (mlList != null) {
651                     for (int ml = 0; ml < mlList.size(); ml++) {
652                         msgList = (MessagelistenerDesc) mlList.get(ml);
653                         id = msgList.getId();
654                         idOffset++;
655                         jAct = (JonasActivationspecDesc)
656                                 ru.getJonasXML(jConn, id, idOffset, JAS);
657
658                         processJAS(rarFileName, msgList, jAct, idOffset);
659                     }
660                 }
661
662                 // Loop thru Adminobjects
663
List JavaDoc aoList = ra.getAdminobjectList();
664                 AdminobjectDesc admObj = null;
665                 JonasAdminobjectDesc jAObj = null;
666                 id = null;
667                 idOffset = -1;
668                 if (aoList != null) {
669                     for (int ao = 0; ao < aoList.size(); ao++) {
670                         admObj = (AdminobjectDesc) aoList.get(ao);
671                         id = admObj.getId();
672                         idOffset++;
673                         jAObj = (JonasAdminobjectDesc)
674                                  ru.getJonasXML(jConn, id, idOffset, JAO);
675
676                         ConfigPropertyDesc [] cfgCdDesc =
677                                      ru.buildConfigProperty(admObj.getConfigPropertyList(),
678                                                             jAObj.getJonasConfigPropertyList(),
679                                                             null);
680
681                         processJAO(rarFileName, admObj, jAObj, cfgCdDesc, idOffset);
682                     }
683                 }
684             }
685         } else {
686             logger.log(BasicLevel.ERROR, "ResourceService.createRA: Resource ("
687                                          + rarFileName
688                                          + ") must be specify a valid specification of 1.0 or 1.5.");
689             throw new Exception JavaDoc("resource input file incorrect: invalid specification support(only 1.0 & 1.5 are valid)");
690         }
691
692         logger.log(BasicLevel.INFO, rarFileName + " available");
693         try {
694             rCtx.rebind("onRar", onRar);
695             rCtx.rebind("deployed", new Boolean JavaDoc(true));
696         } catch (Exception JavaDoc ex) {
697             String JavaDoc err = "Error while getting parameter from context param.";
698             logger.log(BasicLevel.ERROR, err + ex.getMessage());
699             throw new ResourceServiceException(err, ex);
700         }
701         return rCtx;
702     }
703
704
705
706     /**
707      * Register the Rar.
708      * @param cfgRaJonas ConfigPropertyDesc []
709      * @param specVersion String
710      * @param pooProp Properties pool params
711      * @return String object Name of the Rar
712      * @throws Exception thrown
713      */

714     private String JavaDoc registerRarMBean(ConfigPropertyDesc [] cfgRaJonas, String JavaDoc specVersion, String JavaDoc jndiName) throws Exception JavaDoc {
715
716         // --------------------------
717
// Register MBeans cf. JSR 77
718
// --------------------------
719
if (mbeanServer != null) {
720
721             // ------------------------------------------------
722
// Register this ResourceAdapter with JMX - old way
723
// ------------------------------------------------
724
String JavaDoc raName = null; // ResourceAdapter name
725
Properties JavaDoc p = buildProp(cfgRaJonas);
726
727             // MBean resourcesource registering
728
String JavaDoc jmxRaName = (new File JavaDoc(rarFileName)).toURL().getFile().replace(':', '|');
729             mbeanServer.registerMBean(new JmxResourceAdapter(p, jndiName, rarFileName, isInEar, earUrl),
730                                       JonasObjectName.resourceAdapter(jmxRaName));
731
732             // ResourceAdapterModule MBean
733
// ---------------------------
734
String JavaDoc appName = null;
735             if (isInEar) {
736                 appName = EarServiceImpl.buildJ2eeApplicationName(earUrl);
737             }
738
739             // ResourceAdapter Module name
740
String JavaDoc resourceAdapaterModuleName = buildModuleName(jmxRaName, appName);
741
742             ObjectName JavaDoc onResourceAdapterModule =
743                 J2eeObjectName.getResourceAdapterModule(jDomain,
744                                                         jServer,
745                                                         appName,
746                                                         resourceAdapaterModuleName);
747
748             if (manageLogger.isLoggable(BasicLevel.DEBUG)) {
749                 manageLogger.log(BasicLevel.DEBUG, "ObjectName created for ResourceAdapterModule: " + onResourceAdapterModule.toString());
750             }
751
752             ResourceAdapterModule raModuleMBean = new ResourceAdapterModule(onResourceAdapterModule.toString(),
753                                                                             isInEar, earUrl);
754             raModuleMBean.setFileName(jmxRaName);
755             raModuleMBean.setDeploymentDescriptor(xmlContent);
756             raModuleMBean.setJonasDeploymentDescriptor(jonasXmlContent);
757             ManagedBean oManaged = oRegistry.findManagedBean("ResourceAdapterModule");
758
759             ModelMBean JavaDoc oMBean = oManaged.createMBean(raModuleMBean);
760
761             mbeanServer.registerMBean(oMBean, onResourceAdapterModule);
762             if (manageLogger.isLoggable(BasicLevel.DEBUG)) {
763                 manageLogger.log(BasicLevel.DEBUG, "ResourceAdapterModule MBean created");
764             }
765
766             // ResourceAdapter MBean
767
// ---------------------
768
raName = resourceAdapaterModuleName;
769             ObjectName JavaDoc onResourceAdapter = J2eeObjectName.getResourceAdapter(jDomain,
770                                                                              resourceAdapaterModuleName,
771                                                                              appName,
772                                                                              jServer,
773                                                                              raName);
774             org.objectweb.jonas.resource.ResourceAdapter raMBean =
775                            new org.objectweb.jonas.resource.ResourceAdapter(onResourceAdapter.toString(),
776                                                                             p,
777                                                                             jndiName,
778                                                                             jmxRaName,
779                                                                             isInEar,
780                                                                             earUrl,
781                                                                             specVersion);
782             oManaged = oRegistry.findManagedBean("ResourceAdapter");
783             oMBean = oManaged.createMBean(raMBean);
784             if (manageLogger.isLoggable(BasicLevel.DEBUG)) {
785                 manageLogger.log(BasicLevel.DEBUG, "ResourceAdapter ManagedBean created");
786             }
787             mbeanServer.registerMBean(oMBean, onResourceAdapter);
788
789             // Update the ResourceAdapterModule MBean with the ResourceAdapter MBean's OBJECT_NAME
790
raModuleMBean.setResourceAdapter(onResourceAdapter.toString());
791             if (manageLogger.isLoggable(BasicLevel.DEBUG)) {
792                 manageLogger.log(BasicLevel.DEBUG, "ResourceAdapterModule ManagedBean updated");
793             }
794
795             // JCA Resource implemented by this ResourceAdapter
796
// ------------------------------------------------
797
JCAResourceName = raName; // TO BE IMPLEMENTED
798
ObjectName JavaDoc onJCAResource =
799                 J2eeObjectName.getJCAResource(jDomain,
800                                               jServer,
801                                               raName,
802                                               JCAResourceName);
803             jcaResourceMBean = new JCAResource(onJCAResource.toString());
804             oManaged = oRegistry.findManagedBean("JCAResource");
805             oMBean = oManaged.createMBean(jcaResourceMBean);
806             if (manageLogger.isLoggable(BasicLevel.DEBUG)) {
807                 manageLogger.log(BasicLevel.DEBUG, "JCAResource J2EEResource created");
808             }
809             mbeanServer.registerMBean(oMBean, onJCAResource);
810
811             // Update the ResourceAdapter MBean with the JCAResource MBean's OBJECT_NAME
812
raMBean.setJcaResource(onJCAResource.toString());
813             if (manageLogger.isLoggable(BasicLevel.DEBUG)) {
814                 manageLogger.log(BasicLevel.DEBUG, "JCAResource J2EEResource updated");
815             }
816
817             return onResourceAdapterModule.toString();
818         } else {
819             String JavaDoc jmxRaName = (new File JavaDoc(rarFileName)).toURL().getFile().replace(':', '|');
820             return jmxRaName;
821         }
822     }
823
824
825     /**
826      * Unregister the resource adapter.
827      *
828      * @throws Exception thrown
829      */

830     public void unRegister() throws Exception JavaDoc {
831
832         for (int i = 0; i < jndinames.size(); i++) {
833             String JavaDoc jName = (String JavaDoc) jndinames.get(i);
834             ConfigObj co = (ConfigObj) cfgObjs.get(jName);
835             try {
836                 // Unbind from jndi
837
ictx.unbind(jName);
838             } catch (NamingException JavaDoc ex) {
839                 if (logger.isLoggable(BasicLevel.DEBUG)) {
840                     logger.log(BasicLevel.DEBUG, "ResourceService: cannot unbind jndiname of "
841                             + jName + " for ResourceAdapter "
842                             + rarFileName, ex);
843                 }
844                 throw new ServiceException("Cannot unregister", ex);
845             }
846
847             if (co.defaultAS) {
848                 removeDefaultAS(jName);
849             }
850             if (co != null) { // Add for now, take out for final
851
if (co.cm != null) {
852                     // The connection manger must stop managing the RA
853
((ConnectionManagerImpl) co.cm).cleanResourceAdapter();
854                 }
855             }
856
857         }
858         cfgObjs.clear();
859
860         // --------------------------
861
// unregister MBeans cf. JSR 77
862
// --------------------------
863
if (mbeanServer != null) {
864             // MBean resourcesource registering
865
String JavaDoc jmxRaName = (new File JavaDoc(rarFileName)).toURL().getFile().replace(':', '|');
866             mbeanServer.unregisterMBean(JonasObjectName.resourceAdapter(jmxRaName));
867
868             // Construct ResourceAdapterModule MBean name
869
// ------------------------------------------
870
String JavaDoc appName = null;
871             if (isInEar) {
872                 appName = EarServiceImpl.buildJ2eeApplicationName(earUrl);
873             }
874             // ResourceAdapter Module name
875
String JavaDoc resourceAdapaterModuleName = buildModuleName(jmxRaName, appName);
876             ObjectName JavaDoc onResourceAdapterModule =
877                 J2eeObjectName.getResourceAdapterModule(jDomain,
878                                                     jServer,
879                                                     appName,
880                                                     resourceAdapaterModuleName);
881             try {
882                 String JavaDoc[] resourceAdapaterNames = (String JavaDoc[]) mbeanServer.getAttribute(onResourceAdapterModule, "resourceAdapters");
883
884                 // Unregister ResourceAdapterModule MBean
885
mbeanServer.unregisterMBean(onResourceAdapterModule);
886
887                 // Unregister ResourceAdapters
888
for (int i = 0; i < resourceAdapaterNames.length; i++) {
889                     String JavaDoc resourceAdapaterName = resourceAdapaterNames[i];
890                     ObjectName JavaDoc onResourceAdapater = new ObjectName JavaDoc(resourceAdapaterName);
891                     // Determine this ResourceAdapter's JCAResource
892
String JavaDoc jcaResourceName = (String JavaDoc) mbeanServer.getAttribute(onResourceAdapater, "jcaResource");
893                     // Update the list of resources in the J2EEServer MBean with the JCAResource MBean's OBJECT_NAME
894
mbeanServer.unregisterMBean(onResourceAdapater);
895                     ObjectName JavaDoc onJCAResource = new ObjectName JavaDoc(jcaResourceName);
896                     String JavaDoc [] connectionFactoriesNames = (String JavaDoc []) mbeanServer.getAttribute(onJCAResource, "connectionFactories");
897                     // Unregister the JCA ConnectionFactories of this JCAResource
898
for (int j = 0; j < connectionFactoriesNames.length; j++) {
899                         String JavaDoc connectionFactoryName = (String JavaDoc) connectionFactoriesNames[j];
900                         ObjectName JavaDoc onJCAConnectionFactory = new ObjectName JavaDoc(connectionFactoryName);
901                         String JavaDoc managedConnectionFactoryName = (String JavaDoc) mbeanServer.getAttribute(onJCAConnectionFactory, "managedConnectionFactory");
902                         mbeanServer.unregisterMBean(onJCAConnectionFactory);
903                         mbeanServer.unregisterMBean(new ObjectName JavaDoc(managedConnectionFactoryName));
904                     }
905                     String JavaDoc [] adminObjectNames = (String JavaDoc []) mbeanServer.getAttribute(onJCAResource, "adminObjects");
906                     // Unregister the JCA AdminObjects of this JCAResource
907
for (int j = 0; j < adminObjectNames.length; j++) {
908                         String JavaDoc adminObjectName = (String JavaDoc) adminObjectNames[j];
909                         ObjectName JavaDoc onJCAAdminObject = new ObjectName JavaDoc(adminObjectName);
910                         mbeanServer.unregisterMBean(onJCAAdminObject);
911                     }
912                     String JavaDoc [] activationSpecNames = (String JavaDoc []) mbeanServer.getAttribute(onJCAResource, "activationSpecs");
913                     // Unregister the JCA ActivationSpecs of this JCAResource
914
for (int j = 0; j < activationSpecNames.length; j++) {
915                         String JavaDoc activationSpecName = (String JavaDoc) activationSpecNames[j];
916                         ObjectName JavaDoc onJCAActivationSpec = new ObjectName JavaDoc(activationSpecName);
917                         mbeanServer.unregisterMBean(onJCAActivationSpec);
918                     }
919                     mbeanServer.unregisterMBean(onJCAResource);
920                 }
921             } catch (MalformedObjectNameException JavaDoc ma) {
922                 logger.log(BasicLevel.ERROR, "Cannot cleanly unregister RAR: ", ma);
923             } catch (MBeanRegistrationException JavaDoc mr) {
924                 logger.log(BasicLevel.ERROR, "Cannot cleanly unregister RAR: ", mr);
925             } catch (InstanceNotFoundException JavaDoc infe) {
926                 logger.log(BasicLevel.ERROR, "Cannot cleanly unregister RAR: ", infe);
927             } catch (Exception JavaDoc e) {
928                logger.log(BasicLevel.ERROR, "Cannot cleanly unregister RAR: ", e);
929             }
930         }
931
932         // Call Resourceadapter stop
933
if (resAdp != null) {
934             resAdp.stop();
935         }
936
937     }
938
939     //--------------------------------------------------------------
940
// Other Method
941
//--------------------------------------------------------------
942

943     /**
944      * get the ConfigObj matching the jndiname specified
945      *
946      * @param jndiName String of jndi name
947      * @return Object ConfigObj associated with the jndi name
948      */

949     public Object JavaDoc getConfigObj(String JavaDoc jndiName) {
950         synchronized (cfgObjs) {
951             ConfigObj co = (ConfigObj) cfgObjs.get(jndiName);
952             return co;
953         }
954     }
955
956     /**
957      * get the ResourceAdapter Connector object for this Rar
958      *
959      * @return ConnectorDesc associated resource adapter connector object
960      */

961     public ConnectorDesc getConnectorDesc() {
962         return raConn;
963     }
964
965     /**
966      * set the ResourceAdapter Connector object for this Rar
967      *
968      * @param cd ConnectorDesc to associate with
969      */

970     public void setConnectorDesc(ConnectorDesc cd) {
971         raConn = cd;
972     }
973
974     /**
975      * get the Xml Content for this Rar
976      *
977      * @return String Xml content of this RAR
978      */

979     public String JavaDoc getXmlContent() {
980         return xmlContent;
981     }
982
983     /**
984      * get the JonasConnector object for this Rar
985      *
986      * @return JonasConnectorDesc associated JonasConnector
987      */

988     public JonasConnectorDesc getJonasConnectorDesc() {
989         return jonasConn;
990     }
991
992     /**
993      * set the JonasConnector object for this Rar
994      *
995      * @param jcd JonasConnectorDesc to associate with
996      */

997     public void setJonasConnectorDesc(JonasConnectorDesc jcd) {
998         jonasConn = jcd;
999     }
1000
1001    public Object JavaDoc getFactory(String JavaDoc jndiname) {
1002        ConfigObj co = (ConfigObj) cfgObjs.get(jndiname);
1003        return (co == null ? null : co.factory );
1004    }
1005
1006    public String JavaDoc getInterface(String JavaDoc jndiname) {
1007        ConfigObj co = (ConfigObj) cfgObjs.get(jndiname);
1008        return (co == null ? null : co.interfaceStr );
1009    }
1010
1011    public Vector JavaDoc getJndinames() {
1012        return jndinames;
1013    }
1014
1015    public ResourceAdapter getResourceAdapter() {
1016        return resAdp;
1017    }
1018
1019    public void configureAS(ActivationSpec JavaDoc as, List JavaDoc acp, List JavaDoc jacp, String JavaDoc jndiname,
1020                             String JavaDoc ejbName) throws Exception JavaDoc {
1021        ConfigPropertyDesc [] asCp = ru.buildConfigProperty(null, acp, jacp);
1022
1023        // set resource adapter if not already done
1024
if (((ResourceAdapterAssociation JavaDoc) as).getResourceAdapter() == null) {
1025                ((ResourceAdapterAssociation JavaDoc) as).setResourceAdapter(resAdp);
1026        }
1027        ru.processSetters(as.getClass(), as, ejbName, asCp);
1028        validateAS(as, jndiname, acp, jacp);
1029    }
1030
1031    //--------------------------------------------------------------
1032
// Private Methods
1033
//--------------------------------------------------------------
1034

1035    private void validateAS(ActivationSpec JavaDoc as, String JavaDoc jndiname,
1036                             List JavaDoc acp, List JavaDoc jacp) throws Exception JavaDoc {
1037        boolean found = false;
1038        String JavaDoc reqName = null;
1039        RequiredConfigPropertyDesc rcProp = null;
1040        ActivationConfigPropertyDesc acProp = null;
1041        // Check that the req properties have been satisfied
1042
ConfigObj co = (ConfigObj) cfgObjs.get(jndiname);
1043        for (Iterator JavaDoc r = co.reqConfigProps.iterator(); r.hasNext();) {
1044            rcProp = (RequiredConfigPropertyDesc) r.next();
1045            found = false;
1046            reqName = rcProp.getConfigPropertyName();
1047            if (acp != null) {
1048                for (Iterator JavaDoc i = acp.iterator(); i.hasNext();) {
1049                    acProp = (ActivationConfigPropertyDesc) i.next();
1050                    if (reqName.equals(acProp.getActivationConfigPropertyName())) {
1051                        found = true;
1052                        break;
1053                    }
1054                }
1055            }
1056            if (!found && jacp != null) {
1057                for (Iterator JavaDoc i = jacp.iterator(); i.hasNext();) {
1058                    acProp = (ActivationConfigPropertyDesc) i.next();
1059                    if (reqName.equals(acProp.getActivationConfigPropertyName())) {
1060                        found = true;
1061                        break;
1062                    }
1063                }
1064            }
1065            if (!found) {
1066                logger.log(BasicLevel.ERROR, "Required property " + reqName + " not specified ");
1067                throw new ResourceAllocationException JavaDoc("Required property " + reqName + " not specified ");
1068            }
1069        }
1070
1071        // Call validate
1072
try {
1073            as.validate();
1074        } catch (UnsupportedOperationException JavaDoc uoe) {
1075            // treat this as no error from validate
1076
} catch (Exception JavaDoc ex) {
1077            logger.log(BasicLevel.ERROR, "Error from ActivationSpec.validate(). " + ex);
1078            throw new ResourceAllocationException JavaDoc("Error from ActivationSpec.validate(). ", ex);
1079        }
1080
1081    }
1082
1083
1084    // Needs to be implemented
1085
/**
1086     *
1087     */

1088    private void bldSecurityTable(JonasConnectorDesc lnkJCon, JonasConnectorDesc jCon) {
1089    }
1090
1091    /**
1092     *
1093     * @param rarFileName String of rar file
1094     * @param appName the name of the application
1095     * @return String of module name
1096     */

1097    public static String JavaDoc buildModuleName(String JavaDoc rarFileName, String JavaDoc appName) {
1098        String JavaDoc sName = null;
1099        try {
1100            sName = new File JavaDoc(rarFileName).getName();
1101            int iPos = sName.lastIndexOf('.');
1102            if (iPos > -1) {
1103                sName = sName.substring(0, iPos);
1104            }
1105        } catch (NullPointerException JavaDoc e) {
1106            // none action
1107
}
1108        if (appName != null) {
1109            StringBuffer JavaDoc sbName = new StringBuffer JavaDoc(appName);
1110            sbName.append(".");
1111            sbName.append(sName);
1112            sName = sbName.toString();
1113        }
1114
1115        return sName;
1116    }
1117
1118    /* Static methods
1119     *
1120     */

1121
1122    /**
1123     * Create the factory specified
1124     *
1125     * @param jndiName name to bind the factory
1126     * @param rarObjectName unique name to match rar
1127     * @param factoryOffset factory offset in the to create
1128     * @param factoryType factory type to create
1129     * @param conn ConnectionDesc object to use for creation
1130     * @param jConn JonasConnectionDesc object to use for creation
1131     * @return Object factory created
1132     * @throws Exception if an error occurs
1133     */

1134    public Object JavaDoc createFactory(String JavaDoc jndiName, String JavaDoc rarObjectName, int factoryOffset,
1135                                String JavaDoc factoryType, ConnectorDesc conn, JonasConnectorDesc jConn)
1136                 throws Exception JavaDoc {
1137
1138        ResourceUtility ru = new ResourceUtility(null, null, logger, setterLogger, manageLogger);
1139        Object JavaDoc factory = null;
1140        ManagedConnectionFactory JavaDoc mcf = null;
1141        ResourceadapterDesc ra = conn.getResourceadapterDesc();
1142        /**
1143         * Can currently assume Basic Password support since the RAR must have already been
1144         * deployed correctly
1145         */

1146        boolean basicPass = true;
1147        /**
1148         * Needed if a 1.5 rar and ResourceAdapterAssociation is implemented
1149         */

1150        ResourceAdapter resAdp = null;
1151
1152        String JavaDoc logEnabled = null;
1153        if (jConn.getLogEnabled() != null) {
1154            logEnabled = jConn.getLogEnabled().trim();
1155        }
1156        String JavaDoc logTopic = null;
1157        if (jConn.getLogTopic() != null) {
1158            logTopic = jConn.getLogTopic().trim();
1159        }
1160        String JavaDoc specVersion = conn.getSpecVersion();
1161
1162        ConnectionManager JavaDoc cm = null;
1163        String JavaDoc jBase = null;
1164        try {
1165            jBase = System.getProperty("jonas.base");
1166            if (jBase != null) {
1167                // Get a reference to the Transaction service
1168
try {
1169                    ServiceManager sm = ServiceManager.getInstance();
1170                    TransactionService ts = (TransactionService) sm.getTransactionService();
1171                    tm = ts.getTransactionManager();
1172                } catch (Exception JavaDoc e) {
1173                    logger.log(BasicLevel.ERROR, "Cannot get the Transaction service: " + e);
1174                    throw new Exception JavaDoc("Cannot get the Transaction service: ", e);
1175                }
1176
1177                cm = ru.createConnectionManager(ra.getTransactionSupport(), tm,
1178                                                             logger, poolLogger);
1179            }
1180        } catch (Exception JavaDoc ex) {
1181            logger.log(BasicLevel.ERROR, "Use default ConnectionManager: " + rarObjectName);
1182        }
1183
1184        // Build the global config and pool values
1185
ConfigPropertyDesc [] cfgRaJonas =
1186                     ru.buildConfigProperty(ra.getConfigPropertyList(),
1187                                            jConn.getJonasConfigPropertyList(),
1188                                            null);
1189        ConnectionManagerPoolParams cmpp = ru.configurePoolParams(jConn.getPoolParamsDesc(),
1190                                                                  jConn.getJdbcConnParamsDesc(),
1191                                                                  null);
1192        Properties JavaDoc tmProp = new Properties JavaDoc();
1193        if (jConn.getTmParamsDesc() != null) {
1194            List JavaDoc tmParams = jConn.getTmParamsDesc().getTmConfigPropertyList();
1195            if (tmParams != null) {
1196                for (Iterator JavaDoc i = tmParams.iterator(); i.hasNext();) {
1197                    TmConfigPropertyDesc tpd = (TmConfigPropertyDesc) i.next();
1198                    String JavaDoc tpdVal = tpd.getTmConfigPropertyValue();
1199                    if (tpdVal == null) {
1200                        tpdVal = "";
1201                    }
1202                    tmProp.setProperty(tpd.getTmConfigPropertyName(), tpdVal);
1203                }
1204                if (logger.isLoggable(BasicLevel.DEBUG)) {
1205                    logger.log(BasicLevel.DEBUG, "TM Properties: " + tmProp);
1206                }
1207            }
1208        }
1209
1210        if (specVersion.equals("1.0")) {
1211            // Only need to build an MCF for a 1.0 resource adapter
1212
mcf = (ManagedConnectionFactory JavaDoc) ru.processMCF(conn, jConn, cm, curLoader, rarObjectName,
1213                                                           ra.getManagedconnectionfactoryClass(),
1214                                                           jndiName, logEnabled, logTopic,
1215                                                           cfgRaJonas, resAdp, 0);
1216            if (cm != null) {
1217                ((ConnectionManagerImpl) cm).setResourceAdapter(mcf, cmpp);
1218                factory = mcf.createConnectionFactory(cm);
1219            } else {
1220                factory = mcf.createConnectionFactory();
1221            }
1222
1223        } else if (specVersion.equals("1.5")) {
1224            // Need to figure out how to call RA.start() under some circumstances
1225
boolean callStart = false;
1226
1227            String JavaDoc raStr = conn.getResourceadapterDesc().getResourceadapterClass().trim();
1228            if (raStr != null && raStr.length() > 0) {
1229
1230                // Instantiate the resource adapter class
1231
Class JavaDoc raClass = curLoader.loadClass(raStr);
1232                resAdp = (ResourceAdapter) raClass.newInstance();
1233
1234                ru.processSetters(raClass, resAdp, rarObjectName, cfgRaJonas);
1235
1236                // Call Resourceadapter start method
1237
try {
1238                    if (callStart) {
1239                        resAdp.start(bootCtx);
1240                    }
1241                } catch (Exception JavaDoc ex) {
1242                    logger.log(BasicLevel.ERROR, "Rar: Error from resource (" + rarObjectName
1243                                                 + ") start method.");
1244                    throw new Exception JavaDoc("Error from start method. " + ex);
1245                } catch (Throwable JavaDoc th) {
1246                    logger.log(BasicLevel.ERROR, "Rar: Error from resource (" + rarObjectName
1247                                                 + ") start method.");
1248                    throw new Exception JavaDoc("Error from start method. ", th);
1249                }
1250            }
1251
1252            // Determine type
1253
if (factoryType.equals(ru.JCD)) {
1254                OutboundResourceadapterDesc outRa = ra.getOutboundResourceadapterDesc();
1255                List JavaDoc cdList = null;
1256                if (outRa != null) {
1257                    cdList = outRa.getConnectionDefinitionList();
1258                }
1259                ConnectionDefinitionDesc conDef = null;
1260                JonasConnectionDefinitionDesc jConDef = null;
1261                String JavaDoc id = null;
1262                if (cdList != null) {
1263                    conDef = (ConnectionDefinitionDesc) cdList.get(factoryOffset);
1264                    id = conDef.getId();
1265                    jConDef = (JonasConnectionDefinitionDesc)
1266                                  ru.getJonasXML(jConn, id, factoryOffset, ru.JCD);
1267
1268                    if (jConDef.getLogEnabled() != null) {
1269                        logEnabled = jConDef.getLogEnabled().trim();
1270                    }
1271                    if (jConDef.getLogTopic() != null) {
1272                        logTopic = jConDef.getLogTopic().trim();
1273                    }
1274
1275                    // Create Config Property List
1276
ConfigPropertyDesc [] cfgCdDesc =
1277                                 ru.buildConfigProperty(conDef.getConfigPropertyList(),
1278                                                        jConDef.getJonasConfigPropertyList(),
1279                                                        null);
1280
1281                    // Only need to build an MCF for a 1.0 resource adapter
1282
mcf = (ManagedConnectionFactory JavaDoc) ru.processMCF(conn, jConn, cm, curLoader, rarObjectName,
1283                                                                   conDef.getManagedconnectionfactoryClass(),
1284                                                                   jndiName, logEnabled, logTopic,
1285                                                                   cfgCdDesc, resAdp, factoryOffset);
1286                    if (cm != null) {
1287                        ConnectionManagerPoolParams pool =
1288                              ru.configurePoolParams(jConDef.getPoolParamsDesc(),
1289                                                     jConDef.getJdbcConnParamsDesc(),
1290                                                     cmpp);
1291                        ((ConnectionManagerImpl) cm).setResourceAdapter(mcf, pool);
1292                        factory = mcf.createConnectionFactory(cm);
1293                    } else {
1294                        factory = mcf.createConnectionFactory();
1295                    }
1296
1297                }
1298            } else if (factoryType.equals(ru.JAO)) {
1299                if (logger.isLoggable(BasicLevel.DEBUG)) {
1300                    logger.log(BasicLevel.DEBUG, "Cannot lookup remote admin object of " + jndiName);
1301                }
1302                return null;
1303            } else if (factoryType.equals(ru.JAS)) {
1304                if (logger.isLoggable(BasicLevel.DEBUG)) {
1305                    logger.log(BasicLevel.DEBUG, "Cannot lookup remote activationspec of " + jndiName);
1306                }
1307                return null;
1308            }
1309        }
1310
1311        if (logger.isLoggable(BasicLevel.DEBUG)) {
1312            logger.log(BasicLevel.DEBUG, "cf = " + factory);
1313        }
1314        // Need to register the RM with JOTM
1315
if (factoryType.equals(ru.JCD) && cm != null) {
1316            // Call CM to register with JOTM
1317
((ConnectionManagerImpl) cm).setXAName(ru.getJcaMcfName(jndiName));
1318            ((ConnectionManagerImpl) cm).registerXAResource(tmProp);
1319        }
1320        return factory;
1321    }
1322
1323    /**
1324     * add a default AS to the list, the first one deployed is the default
1325     * if others are added then they will become default if this one is undeployed
1326     * @param jndiName jndi name to add
1327     */

1328    public static void addDefaultAS(String JavaDoc jndiName) {
1329        defaultAS.add(jndiName);
1330    }
1331
1332    /**
1333     * return the current default ActivationSpec
1334     * @return String default ActivationSpec name
1335     */

1336    public static String JavaDoc getDefaultAS() {
1337        String JavaDoc ret = null;
1338        try {
1339            ret = (String JavaDoc) defaultAS.firstElement();
1340        } catch (Exception JavaDoc ex) {
1341            if (logger.isLoggable(BasicLevel.DEBUG)) {
1342                logger.log(BasicLevel.DEBUG, "No default activationspec");
1343            }
1344        }
1345        return ret;
1346    }
1347
1348    /**
1349     * remove the specified jndiName from the default AS list
1350     * @param jndiName jndi name to remove
1351     */

1352    public static void removeDefaultAS(String JavaDoc jndiName) {
1353        try {
1354            defaultAS.remove(jndiName);
1355        } catch (Exception JavaDoc ex) {
1356            if (logger.isLoggable(BasicLevel.DEBUG)) {
1357                logger.log(BasicLevel.DEBUG, "Unable to remove default activationspec");
1358            }
1359        }
1360    }
1361
1362    /**
1363     * get the RAR ConnectorDesc object matching the jndiname
1364     * @param jndiName the jndiname to lookup
1365     * @return ConnectorDesc matching ConnectorDesc
1366     */

1367    public static ConnectorDesc getConnectorDesc(String JavaDoc jndiName) {
1368        synchronized (jndiName2RA) {
1369            Rar rar = (Rar) jndiName2RA.get(jndiName);
1370            if (rar != null) {
1371                return (rar.getConnectorDesc());
1372            }
1373            if (logger.isLoggable(BasicLevel.DEBUG)) {
1374                logger.log(BasicLevel.DEBUG, "Can't find " + jndiName + " in " + jndiName2RA);
1375            }
1376            return null;
1377        }
1378    }
1379
1380    /**
1381     * get the RAR JonasConnectorDesc object matching the jndiname
1382     * @param jndiName the jndiname to lookup
1383     * @return JonasConnectorDesc matching JonasConnectorDesc
1384     */

1385    public static JonasConnectorDesc getJonasConnectorDesc(String JavaDoc jndiName) {
1386        synchronized (jndiName2RA) {
1387            Rar rar = (Rar) jndiName2RA.get(jndiName);
1388            if (rar != null) {
1389                return (rar.getJonasConnectorDesc());
1390            }
1391            return null;
1392        }
1393    }
1394
1395    /**
1396     * get the Rar matching the jndiNname
1397     * will be used in EJB container to deploy an MDB
1398     * @param jndiName jndi name to lookup
1399     * @return Rar Rar object for the specified jndi name
1400     */

1401    public static Rar getRar(String JavaDoc jndiName) {
1402        synchronized (jndiName2RA) {
1403            Rar ra = (Rar) jndiName2RA.get(jndiName);
1404            return (ra);
1405        }
1406    }
1407
1408    /**
1409     * get the ResourceAdapter matching the jndiName
1410     * will be used in ResourceObjectJNDIHandler class at lookup time
1411     * @param jndiName to lookup ResourceObject
1412     * @return Object resourceObject corresponding to jndiName
1413     */

1414    public static Object JavaDoc getResourceObject(String JavaDoc jndiName) {
1415        Rar ra = null;
1416        synchronized (jndiName2RA) {
1417            ra = (Rar) jndiName2RA.get(jndiName);
1418        }
1419        if (ra != null) {
1420            return (ra.getFactory(jndiName));
1421        }
1422        Object JavaDoc fact = null;
1423        synchronized (jndiName2Factory) {
1424            fact = jndiName2Factory.get(jndiName);
1425        }
1426        return fact;
1427    }
1428
1429    /* Private Methods
1430     *
1431     */

1432
1433   /**
1434   *
1435   */

1436  private Properties JavaDoc buildProp(ConfigPropertyDesc [] cfgRaJonas) {
1437    Properties JavaDoc ret = new Properties JavaDoc();
1438    if (cfgRaJonas != null) {
1439        for (int i = 0; i < cfgRaJonas.length; i++) {
1440            String JavaDoc val = cfgRaJonas[i].getConfigPropertyValue() != null ?
1441                                   cfgRaJonas[i].getConfigPropertyValue() : "";
1442            ret.setProperty(cfgRaJonas[i].getConfigPropertyName(), val);
1443          }
1444    }
1445    return ret;
1446  }
1447
1448    /**
1449     * Process the specified rar, extracting all the jars files to be included
1450     * in the classloader and all the native files needed by the rar.
1451     * @param resFileName rar file to process
1452     * @param jonasConn the jonas-ra.xml properties
1453     * @throws ResourceServiceException if an error occurs during
1454     * the extracting.
1455     */

1456    private void extractJars(String JavaDoc resFileName, JonasConnectorDesc jonasConn)
1457                 throws ResourceServiceException {
1458
1459        String JavaDoc jarPath = ResourceServiceImpl.WORK_RARS_DIR + File.separator + "jonas" + File.separator;
1460        String JavaDoc binPath = null;
1461        if (jonasConn.getNativeLib() != null && jonasConn.getNativeLib().trim().length() > 0) {
1462            binPath = jonasConn.getNativeLib().trim() + File.separator;
1463            if (binPath.startsWith("/") || binPath.startsWith("\\")
1464                || binPath.charAt(1) == ':') {
1465                ;
1466            } else {
1467                binPath = ResourceServiceImpl.JONAS_BASE + File.separator + binPath;
1468            }
1469
1470        }
1471
1472        //Get RAR name
1473
String JavaDoc rarName = resFileName;
1474        if (rarName.endsWith(".rar")) {
1475            rarName = resFileName.substring(0, resFileName.lastIndexOf('.'));
1476        }
1477
1478        int off = rarName.lastIndexOf(File.separator);
1479        rarName = rarName.substring(++off);
1480        if (File.separatorChar == '\\') {
1481            off = rarName.lastIndexOf("/");
1482            rarName = rarName.substring(++off);
1483        }
1484
1485        JJarFile jjar = null;
1486
1487        try {
1488            jjar = new JJarFile(resFileName);
1489            for (Enumeration JavaDoc ent = jjar.entries(); ent.hasMoreElements();) {
1490                JarEntry JavaDoc je = (JarEntry JavaDoc) ent.nextElement();
1491                if (!je.isDirectory() && je.getName().endsWith(".jar")) {
1492                    File JavaDoc newd = new File JavaDoc(jarPath);
1493                    if (!newd.exists()) {
1494                        newd.mkdirs();
1495                    }
1496
1497                    String JavaDoc fileName = jarPath + "_" + rarName + "_" + je.getName();
1498                    jjar.extract(je, fileName);
1499                    ((org.objectweb.jonas.server.JClassLoader) curLoader).addURL((new File JavaDoc(fileName)).toURL());
1500                } else if (!je.isDirectory() && !je.getName().startsWith("META-INF")
1501                            && binPath != null) {
1502                    File JavaDoc newf = new File JavaDoc(binPath);
1503                    if (!newf.exists()) {
1504                        newf.mkdirs();
1505                    }
1506                    String JavaDoc fileName = binPath + je.getName();
1507                    jjar.extract(je, fileName);
1508                }
1509            }
1510        } catch (Exception JavaDoc ex) {
1511            String JavaDoc err = "Error while extracting the files from " + resFileName;
1512            logger.log(BasicLevel.ERROR, err + ex.getMessage());
1513            throw new ResourceServiceException(err, ex);
1514        }
1515
1516    }
1517
1518    /**
1519     * get the ConfigObj object matching the jndiName
1520     *
1521     * @param jndiName String of jndi name
1522     * @return Object for the jndiName
1523     */

1524    private Object JavaDoc getConfigObject(String JavaDoc jndiName) {
1525        Rar ra = null;
1526        synchronized (jndiName2RA) {
1527            ra = (Rar) jndiName2RA.get(jndiName);
1528        }
1529        if (ra != null) {
1530            return (ra.getConfigObj(jndiName));
1531        }
1532        return null;
1533    }
1534
1535    /**
1536     * get the ResourceAdapter Connector object matching the jndiName
1537     *
1538     * @param jndiName String of jndi name
1539     * @return String for the jndiName
1540     */

1541    private String JavaDoc getXmlContent(String JavaDoc jndiName) {
1542        synchronized (jndiName2RA) {
1543            Rar rar = (Rar) jndiName2RA.get(jndiName);
1544            if (rar != null) {
1545                return (rar.getXmlContent());
1546            }
1547            return null;
1548        }
1549    }
1550
1551    private void processJAO(String JavaDoc rarFilename, AdminobjectDesc aObj, JonasAdminobjectDesc jao,
1552                            ConfigPropertyDesc [] cfgRaJonas, int idOff) throws Exception JavaDoc {
1553
1554        ConfigObj cObj = null;
1555        String JavaDoc jndiName = jao.getJndiName();
1556        String JavaDoc aoDesc = "";
1557        for (Iterator JavaDoc r = jao.getDescriptionList().iterator(); r.hasNext();) {
1558            String JavaDoc desc = (String JavaDoc) r.next();
1559            aoDesc += desc + " ";
1560        }
1561        if (jndiName == null || jndiName.length() == 0) {
1562            logger.log(BasicLevel.ERROR,
1563                  "Rar: jndi-name not set in jonas-ra.xml for Adminobject: " + idOff);
1564            throw new Exception JavaDoc("configuration file incorrect");
1565        }
1566
1567        // Instantiate into the currect loader
1568
String JavaDoc admObj = aObj.getAdminobjectClass();
1569        Class JavaDoc aoClass = curLoader.loadClass(admObj);
1570        Object JavaDoc ao = aoClass.newInstance();
1571
1572        ru.processSetters(aoClass, ao, rarFileName, cfgRaJonas);
1573
1574        jndinames.add(jndiName);
1575        if (logger.isLoggable(BasicLevel.DEBUG)) {
1576            logger.log(BasicLevel.DEBUG, "jndiName=" + jndiName);
1577        }
1578
1579        // Add entry to list of configured objects
1580
cObj = new ConfigObj(JAO, idOff, jndiName, rarFileName, aObj.getAdminobjectInterface(), admObj, ao);
1581
1582        cfgObjs.put(jndiName, cObj);
1583        //
1584
// Register into Jndi
1585
try {
1586            ictx.rebind(jndiName, ao);
1587
1588        } catch (Exception JavaDoc e) {
1589            logger.log(BasicLevel.ERROR, "Rar: Cannot register ResourceAdapter with the name "
1590                                         + jndiName);
1591            logger.log(BasicLevel.ERROR, "Rar: Exception caught : " + e);
1592            throw new Exception JavaDoc("Error binding jndiName: " + jndiName, e.getCause());
1593        }
1594
1595        // --------------------------
1596
// Register MBeans cf. JSR 77
1597
// --------------------------
1598
if (mbeanServer != null) {
1599
1600            // Available Adminobjects
1601
// ------------------------------------------------------------
1602
// Adminobject MBean
1603
// -----------------------
1604
String JavaDoc jcaAdminobjectName = jndiName;
1605            Properties JavaDoc p = buildProp(cfgRaJonas);
1606            ObjectName JavaDoc onJCAAdminobject =
1607                J2eeObjectName.getJCAAdminObject(jDomain,
1608                                                 JCAResourceName,
1609                                                 jServer,
1610                                                 jcaAdminobjectName);
1611            JCAAdminObject jcaAdminobjectMBean = new JCAAdminObject(onJCAAdminobject.toString(), jndiName, aoDesc, p);
1612            ManagedBean oManaged = oRegistry.findManagedBean("JCAAdminObject");
1613            ModelMBean JavaDoc oMBean = oManaged.createMBean(jcaAdminobjectMBean);
1614            if (manageLogger.isLoggable(BasicLevel.DEBUG)) {
1615                manageLogger.log(BasicLevel.DEBUG, "JCAAdminObject created");
1616            }
1617            mbeanServer.registerMBean(oMBean, onJCAAdminobject);
1618
1619            // Update the list of connection factories in the JCAResource MBean with the JCAConnectionFactory
1620
// MBean's OBJECT_NAME
1621
jcaResourceMBean.setAdminObjects(onJCAAdminobject.toString());
1622
1623        } // end JMX registration
1624

1625    }
1626
1627    private void processJAS(String JavaDoc rarFilename, MessagelistenerDesc mlst, JonasActivationspecDesc jas,
1628                             int idOff) throws Exception JavaDoc {
1629
1630        ConfigObj cObj = null;
1631        String JavaDoc jndiName = jas.getJndiName();
1632        String JavaDoc asDesc = "";
1633        for (Iterator JavaDoc r = jas.getDescriptionList().iterator(); r.hasNext();) {
1634            String JavaDoc desc = (String JavaDoc) r.next();
1635            asDesc += desc + " ";
1636        }
1637        if (jndiName == null || jndiName.length() == 0) {
1638            logger.log(BasicLevel.ERROR,
1639                "Rar: jndi-name not set in jonas-ra.xml for Activationspec: " + idOff);
1640            throw new Exception JavaDoc("configuration file incorrect");
1641        }
1642
1643        // Instantiate into the currect loader
1644
String JavaDoc mlIntf = mlst.getMessagelistenerType();
1645        String JavaDoc actSpec = mlst.getActivationspecDesc().getActivationspecClass();
1646        Class JavaDoc asClass = curLoader.loadClass(actSpec);
1647        ActivationSpec JavaDoc as =
1648            (ActivationSpec JavaDoc) asClass.newInstance();
1649
1650        jndinames.add(jndiName);
1651        if (logger.isLoggable(BasicLevel.DEBUG)) {
1652            logger.log(BasicLevel.DEBUG, "jndiName=" + jndiName);
1653        }
1654
1655        // Add entry to list of configured objects
1656
cObj = new ConfigObj(JAS, idOff, jndiName, rarFilename, mlIntf, actSpec, as);
1657        cObj.reqConfigProps = mlst.getActivationspecDesc().getRequiredConfigPropertyList();
1658        if (jas.getDefaultAS() != null && jas.getDefaultAS().equals("true")) {
1659            cObj.defaultAS = true;
1660            addDefaultAS(jndiName);
1661        }
1662
1663        cfgObjs.put(jndiName, cObj);
1664        //
1665
// Register into Jndi
1666
try {
1667            ictx.rebind(jndiName, as);
1668
1669        } catch (Exception JavaDoc e) {
1670            logger.log(BasicLevel.ERROR, "Rar.processJAS: Cannot register ResourceAdapter with the name " + jndiName);
1671            logger.log(BasicLevel.ERROR, "Rar.processJAS: Exception caught : " + e);
1672            throw new Exception JavaDoc("Error binding jndiName: " + jndiName, e.getCause());
1673        }
1674
1675        // --------------------------
1676
// Register MBeans cf. JSR 77
1677
// --------------------------
1678
if (mbeanServer != null) {
1679
1680            // Available ActivationSpecs
1681
// ------------------------------------------------------------
1682
// ActivationSpec MBean
1683
// -----------------------
1684
String JavaDoc jcaActivationSpecName = jndiName;
1685            ObjectName JavaDoc onJCAActivationSpec =
1686                J2eeObjectName.getJCAActivationSpec(jDomain,
1687                                                       JCAResourceName,
1688                                                       jServer,
1689                                                       jcaActivationSpecName);
1690            JCAActivationSpec jcaActivationSpecMBean = new JCAActivationSpec(onJCAActivationSpec.toString(), jndiName, asDesc, cObj.reqConfigProps);
1691            ManagedBean oManaged = oRegistry.findManagedBean("JCAActivationSpec");
1692            ModelMBean JavaDoc oMBean = oManaged.createMBean(jcaActivationSpecMBean);
1693            if (manageLogger.isLoggable(BasicLevel.DEBUG)) {
1694                manageLogger.log(BasicLevel.DEBUG, "JCAActivationSpec created");
1695            }
1696            mbeanServer.registerMBean(oMBean, onJCAActivationSpec);
1697
1698            // Update the list of connection factories in the JCAResource MBean with the JCAConnectionFactory
1699
// MBean's OBJECT_NAME
1700
jcaResourceMBean.setActivationSpecs(onJCAActivationSpec.toString());
1701
1702        } // end JMX registration
1703

1704    }
1705
1706}
1707
1708
1709
Popular Tags