1 /***
2 * Copyright 2007 ATG DUST Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 *
7 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and limitations under the License.
13 */
14
15 package atg.adapter.gsa;
16
17 import java.io.File;
18 import java.io.FileNotFoundException;
19 import java.io.FileOutputStream;
20 import java.io.FileWriter;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.io.PrintWriter;
25 import java.sql.Connection;
26 import java.sql.PreparedStatement;
27 import java.sql.ResultSet;
28 import java.sql.SQLException;
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Properties;
37
38 import javax.sql.DataSource;
39
40 import junit.framework.Assert;
41
42 import org.apache.log4j.Logger;
43
44 import atg.adapter.gsa.xml.TemplateParser;
45 import atg.adapter.gsa.xml.VersioningContextUtil;
46 import atg.adapter.version.VersionRepository;
47 import atg.naming.NameContext;
48 import atg.nucleus.Configuration;
49 import atg.nucleus.GenericService;
50 import atg.nucleus.Nucleus;
51 import atg.nucleus.NucleusNameResolver;
52 import atg.nucleus.NucleusTestUtils;
53 import atg.nucleus.ServiceEvent;
54 import atg.nucleus.ServiceException;
55 import atg.repository.Repository;
56 import atg.repository.RepositoryException;
57 import atg.test.util.DBUtils;
58 import atg.versionmanager.VersionManager;
59 import atg.versionmanager.Workspace;
60 import atg.versionmanager.exceptions.VersionException;
61
62 /***
63 * A utility class to simplify testing with GSARepositories inside of junit
64 * tests.
65 *
66 * @author adamb
67 * @version $Revision: #28 $
68 */
69 public class GSATestUtils {
70 public static List<File> mFilesCreated = new ArrayList<File>();
71 public static String sClassName = "atg.adapter.gsa.InitializingGSA";
72 public static String sVersionedClassName = "atg.adapter.gsa.InitializingVersionRepository";
73 private boolean mVersioned = false;
74 private static GSATestUtils SINGLETON_DEFAULT = null;
75 private static GSATestUtils SINGLETON_VERSIONED = null;
76
77 private static Logger log = Logger.getLogger(GSATestUtils.class);
78
79 /***
80 * @param pB
81 */
82 public GSATestUtils(boolean pB) {
83 mVersioned = pB;
84
85 }
86 /***
87 * Duplicates the given array of repositories.
88 * This method first binds the repositories into nucleus under the name XXXX-Shadow,
89 * where XXXX is the original name.
90 * After all repositories are bound, then they are started.
91 * This allows for repositories with circular references to each other to be deplicated.
92 * The pRepositories array and pDS array should be in sync. That is the first item in the
93 * repository array, pRepositories, will use the first data source in the pDS array and so on.
94 * @param pRepositories
95 * @param pDS
96 * @return
97 */
98 public static Repository [] duplicateRepositories(GSARepository [] pRepositories, DataSource [] pDS) throws ServiceException {
99 GSARepository [] newReps = new GSARepository[pRepositories.length];
100 for (int i = 0 ; i < pRepositories.length; i++ ) {
101 newReps[i] = (GSARepository)duplicateRepository(pRepositories[i],pDS[i],false);
102 }
103 for (int i = 0 ; i < newReps.length; i++ ) {
104 startRepository(pRepositories[i], pRepositories[i].getServiceConfiguration(), pRepositories[i].getNucleus(), newReps[i]);
105 }
106 return newReps;
107 }
108 public static Repository duplicateRepository(GSARepository pRepository,DataSource pDS) throws ServiceException{
109 return duplicateRepository(pRepository, pDS,true);
110 }
111 /***
112 * Duplicates the given repository, binds it into nucleus with the suffix "-Shadow"
113 * @param pStart If true, also starts the repository
114 */
115 public static Repository duplicateRepository(GSARepository pRepository,DataSource pDS,boolean pStart) throws ServiceException{
116 Configuration c = pRepository.getServiceConfiguration();
117 Nucleus n = pRepository.getNucleus();
118 NucleusNameResolver r = new NucleusNameResolver(n, n,
119 pRepository.getNameContext(), true);
120 GSARepository newRepository = null;
121 if(pRepository instanceof VersionRepository) {
122 newRepository = (GSARepository) c.createNewInstance(((VersionRepository)pRepository).getWrappedRepository());
123 c.configureService(newRepository, r, ((VersionRepository)pRepository).getWrappedRepository());
124 }
125 else {
126 newRepository = (GSARepository) c.createNewInstance(pRepository);
127 c.configureService(newRepository, r, pRepository);
128 }
129 newRepository.setDataSource(pDS);
130 newRepository.setForeignRepositorySuffix("-Shadow");
131
132
133
134
135
136
137
138
139
140
141
142 NameContext nc = ((GenericService) pRepository).getNameContext();
143 nc.putElement(pRepository.getName()+"-Shadow", newRepository);
144
145 if (pStart)
146 startRepository(pRepository, c, n, newRepository);
147 return newRepository;
148 }
149 /***
150 * @param pRepository
151 * @param c
152 * @param n
153 * @param newRepository
154 * @throws ServiceException
155 */
156 private static void startRepository(GSARepository pRepository, Configuration c, Nucleus n, GSARepository newRepository) throws ServiceException {
157 ServiceEvent ev = new ServiceEvent(pRepository, newRepository, n, c);
158
159
160
161
162
163
164
165
166
167
168
169
170 if (newRepository instanceof InitializingGSA)
171 ((InitializingGSA)newRepository).setImportFiles(null);
172
173
174 newRepository.startService(ev);
175 if (newRepository.isRunning()) {
176 synchronized (pRepository) {
177
178 newRepository.invalidateCaches();
179 }
180 }
181 }
182 /***
183 * Given a directory, pRoot, this method creates the minimal .properties files
184 * required to startup a GSA Repository from Nucleus.
185 *
186 * The pJDBCProperties parameter should contain the JDBC properties used to
187 * create a FakeXADataSource. Required Properties are: driver URL user
188 * password
189 *
190 * For example, driver=solid.jdbc.SolidDriver URL=jdbc:solid://localhost:1313
191 * user=admin password=admin
192 *
193 * <BR>
194 * One should call the <code>cleanup()</code> method to remove any files
195 * created by this method call.
196 *
197 * @param pRoot
198 * The root directory of the testing configpath
199 * @param pRepositoryPath
200 * The Nucleus path of your testing repository
201 * @param pDefinitionFiles
202 * Array of Nucleus paths to definition files
203 * @param pJDBCProperties
204 * properties object containing JDBC connection information
205 * @param pImportFile
206 * @throws IOException
207 * @throws Exception
208 * @see GSATestUtils.cleanup
209 */
210 public void initializeMinimalConfigpath(File pRoot,
211 String pRepositoryPath, String[] pDefinitionFiles,
212 Properties pJDBCProperties, String pCreateSQLAbsolutePath, String pDropSQLAbsolutePath, String[] pImportFile) throws IOException, Exception {
213 initializeMinimalConfigpath(pRoot, pRepositoryPath, pDefinitionFiles, pJDBCProperties, pCreateSQLAbsolutePath, pDropSQLAbsolutePath, pImportFile, true);
214 }
215
216 /***
217 * Given a directory, pRoot, this method creates the minimal .properties files
218 * required to startup a GSA Repository from Nucleus.
219 *
220 * The pJDBCProperties parameter should contain the JDBC properties used to
221 * create a FakeXADataSource. Required Properties are: driver URL user
222 * password
223 *
224 * For example, driver=solid.jdbc.SolidDriver URL=jdbc:solid://localhost:1313
225 * user=admin password=admin
226 *
227 * <BR>
228 * One should call the <code>cleanup()</code> method to remove any files
229 * created by this method call.
230 *
231 * @param pRoot
232 * The root directory of the testing configpath
233 * @param pRepositoryPath
234 * The Nucleus path of your testing repository
235 * @param pDefinitionFiles
236 * Array of Nucleus paths to definition files
237 * @param pJDBCProperties
238 * properties object containing JDBC connection information
239 * @param pImportFile
240 * @param pLogging if true log to stdout, else logging is disabled
241 * @throws IOException
242 * @throws Exception
243 * @see GSATestUtils.cleanup
244 */
245 public void initializeMinimalConfigpath(File pRoot,
246 String pRepositoryPath, String[] pDefinitionFiles,
247 Properties pJDBCProperties, String pCreateSQLAbsolutePath, String pDropSQLAbsolutePath, String[] pImportFile, boolean pLogging) throws IOException, Exception {
248 initializeMinimalConfigpath(pRoot, pRepositoryPath, pDefinitionFiles, pJDBCProperties, pCreateSQLAbsolutePath, pDropSQLAbsolutePath, pImportFile, pLogging, null, null);
249
250 }
251
252
253 public void initializeMinimalConfigpath(File pRoot,
254 String pRepositoryPath, String[] pDefinitionFiles,
255 Properties pJDBCProperties, String pCreateSQLAbsolutePath, String pDropSQLAbsolutePath, String[] pImportFile, boolean pLogging, String pFakeXADataSourceComponentName, String pJTDataSourceComponentName) throws IOException, Exception {
256 if (pRepositoryPath != null)
257 createRepositoryPropertiesFile(pRoot, pRepositoryPath,
258 pDefinitionFiles, pCreateSQLAbsolutePath, pDropSQLAbsolutePath, pImportFile, pJTDataSourceComponentName);
259 createTransactionManager(pRoot);
260 createUserTransaction(pRoot);
261 createXMLToolsFactory(pRoot);
262 createIdGenerator(pRoot);
263 createClientLockManager(pRoot);
264 DBUtils.createJTDataSource(pRoot);
265 if(pJDBCProperties != null)
266 GSATestUtils.createFakeXADataSource(pRoot, pJDBCProperties,pFakeXADataSourceComponentName);
267 else
268 GSATestUtils.createFakeXADataSource(pRoot,DBUtils.getHSQLDBInMemoryDBConnection(), pFakeXADataSourceComponentName);
269 if(pFakeXADataSourceComponentName == null && pJTDataSourceComponentName == null)
270 DBUtils.createJTDataSource(pRoot);
271 else
272 DBUtils.createJTDataSource(pRoot, pJTDataSourceComponentName, pFakeXADataSourceComponentName);
273 createGlobal(pRoot);
274 createScreenLog(pRoot, pLogging);
275 createIdSpaces(pRoot);
276 if(pJDBCProperties != null)
277 createIDGeneratorTables(new DBUtils(pJDBCProperties));
278 else
279 createIDGeneratorTables(new DBUtils(DBUtils.getHSQLDBInMemoryDBConnection()));
280 createSQLRepositoryEventServer(pRoot);
281 createNucleus(pRoot);
282
283 }
284
285
286 /***
287 * Deletes any files created by initializing the configpath
288 *
289 */
290 public void cleanup() {
291 Iterator<File> iter = mFilesCreated.iterator();
292 while (iter.hasNext()) {
293 File f = iter.next();
294 f.delete();
295 }
296 mFilesCreated.clear();
297 }
298
299
300 /***
301 * Writes the idspaces.xml file
302 */
303 public File createIdSpaces(File pRoot) throws IOException {
304 String idspaces = "<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE id-spaces SYSTEM \"http://www.atg.com/dtds/idgen/idgenerator_1.0.dtd\"><id-spaces><id-space name=\"__default__\" seed=\"1\" batch-size=\"100000\"/><id-space name=\"jms_msg_ids\" seed=\"0\" batch-size=\"10000\"/><id-space name=\"layer\" seed=\"0\" batch-size=\"100\"/></id-spaces>";
305 File idspacesFile = new File(pRoot.getAbsolutePath()
306 + "/atg/dynamo/service/idspaces.xml");
307 if (idspacesFile.exists())
308 idspacesFile.delete();
309 idspacesFile.getParentFile().mkdirs();
310 idspacesFile.createNewFile();
311 FileWriter out = new FileWriter(idspacesFile);
312 try {
313 out.write(idspaces);
314 out.write("\n");
315 }
316 catch (IOException e) {
317 e.printStackTrace();
318
319 }
320 finally {
321 out.flush();
322 out.close();
323 }
324 return idspacesFile;
325 }
326
327
328 /*** Creates Nucleus' Nucleus.properties
329 *
330 */
331 public File createNucleus(File pRoot) throws IOException {
332 Properties prop = new Properties();
333 prop.put("initialServiceName","/Initial");
334 return NucleusTestUtils.createProperties("Nucleus", pRoot, "atg.nucleus.Nucleus", prop);
335 }
336
337
338
339 public static File createFakeXADataSource(File pRoot,
340 Properties pJDBCProperties, String pName) throws IOException {
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361 String name = pName;
362 if (name == null)
363 name = "FakeXADataSource";
364 pJDBCProperties.put("transactionManager",
365 "/atg/dynamo/transaction/TransactionManager");
366 return NucleusTestUtils.createProperties(name, new File(pRoot
367 .getAbsolutePath()
368 + "/atg/dynamo/service/jdbc"), "atg.service.jdbc.FakeXADataSource",
369 pJDBCProperties);
370 }
371
372
373 /***
374 * @param pRoot
375 * @throws IOException
376 */
377 public static File createJTDataSource(File pRoot) throws IOException {
378 return createJTDataSource(pRoot, null,null);
379 }
380
381
382 /***
383 * Creates a new JTDataSource component. The name of the component may
384 * be specified by passing in a non null value for pName.
385 * Also the name of the FakeXADataSource may be specified by passing in a non null name.
386 * Otherwise the defaults are JTDataSource and FakeXADataSource.
387 *
388 * @param pRoot
389 * @param pName
390 * @param pFakeXAName
391 * @return
392 * @throws IOException
393 */
394 public static File createJTDataSource(File pRoot, String pName, String pFakeXAName)
395 throws IOException {
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423 String name = pName;
424 if (name == null)
425 name = "JTDataSource";
426
427 String fakeXAName = pFakeXAName;
428 if (fakeXAName == null) fakeXAName =
429 "FakeXADataSource";
430
431 Properties props = new Properties();
432 props.put("dataSource", "/atg/dynamo/service/jdbc/" + fakeXAName);
433 props.put("transactionManager",
434 "/atg/dynamo/transaction/TransactionManager");
435 props.put("min", "10");
436 props.put("max", "20");
437 props.put("blocking", "true");
438 props.put("loggingSQLWarning", "false");
439 props.put("loggingSQLInfo", "false");
440 props.put("loggingSQLDebug", "false");
441
442
443 return NucleusTestUtils.createProperties(name, new File(pRoot
444 .getAbsolutePath()
445 + "/atg/dynamo/service/jdbc"), "atg.service.jdbc.MonitoredDataSource",
446 props);
447 }
448
449
450 /***
451 * Creates a SQLRepositoryEventServer
452 *
453 * @param pRoot
454 * @return
455 */
456 public File createSQLRepositoryEventServer(File pRoot)
457 throws IOException {
458
459 Properties prop = new Properties();
460 prop.put("handlerCount", "0");
461 return NucleusTestUtils.createProperties("SQLRepositoryEventServer",
462 new File(pRoot.getAbsolutePath() + "/atg/dynamo/server"),
463 "atg.adapter.gsa.event.GSAEventServer", prop);
464 }
465
466
467 /***
468 * Creates a ScreenLog component
469 *
470 * @param pRoot
471 * @param pLogging TODO
472 * @return
473 * @throws IOException
474 */
475 public File createScreenLog(File pRoot, boolean pLogging) throws IOException {
476 Properties prop = new Properties();
477 prop.put("cropStackTrace", "false");
478 prop.put("loggingEnabled", String.valueOf(pLogging));
479 return NucleusTestUtils.createProperties("ScreenLog", new File(pRoot
480 .getAbsolutePath()
481 + "/atg/dynamo/service/logging"),
482 "atg.nucleus.logging.PrintStreamLogger", prop);
483 }
484
485
486 /***
487 * Creates a GLOBAL.properties
488 *
489 * @param pRoot
490 * @param pJDBCProperties
491 * @return
492 * @throws IOException
493 */
494 public File createGlobal(File pRoot) throws IOException {
495 Properties prop = new Properties();
496 prop.put("logListeners", "atg/dynamo/service/logging/ScreenLog");
497 prop.put("loggingDebug","false");
498 return NucleusTestUtils.createProperties("GLOBAL", new File(pRoot
499 .getAbsolutePath()
500 + "/"), null, prop);
501
502 }
503
504
505 /***
506 * @param pRoot
507 * @throws IOException
508 */
509 public File createClientLockManager(File pRoot) throws IOException {
510
511
512
513
514
515
516
517
518 Properties props = new Properties();
519 props.put("lockServerAddress", "localhost");
520 props.put("lockServerPort", "9010");
521 props.put("useLockServer", "false");
522 return NucleusTestUtils.createProperties("ClientLockManager", new File(
523 pRoot.getAbsolutePath() + "/atg/dynamo/service"),
524 "atg.service.lockmanager.ClientLockManager", props);
525 }
526
527 /***
528 * @param pRoot
529 * @throws IOException
530 */
531 public File createIdGenerator(File pRoot) throws IOException {
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554 Properties props = new Properties();
555 props.put("dataSource", "/atg/dynamo/service/jdbc/JTDataSource");
556 props.put("transactionManager",
557 "/atg/dynamo/transaction/TransactionManager");
558 props.put("XMLToolsFactory", "/atg/dynamo/service/xml/XMLToolsFactory");
559
560 return NucleusTestUtils.createProperties("IdGenerator", new File(pRoot
561 .getAbsolutePath()
562 + "/atg/dynamo/service/"), "atg.service.idgen.SQLIdGenerator", props);
563 }
564
565 /***
566 * @param pRoot
567 * @throws IOException
568 */
569 public File createXMLToolsFactory(File pRoot) throws IOException {
570
571
572
573
574
575
576
577
578
579
580
581 File root = new File(pRoot.getAbsolutePath() + "/atg/dynamo/service/xml");
582 return NucleusTestUtils.createProperties("XMLToolsFactory", root,
583 "atg.xml.tools.apache.ApacheXMLToolsFactory", new Properties());
584 }
585
586 /***
587 * @param pRoot
588 * @throws IOException
589 */
590 public File createTransactionManager(File pRoot) throws IOException {
591
592
593
594
595
596
597
598
599
600
601 Properties props = new Properties();
602 props.put("loggingDebug","false");
603 File root = new File(pRoot, "/atg/dynamo/transaction");
604 root.mkdirs();
605 NucleusTestUtils.createProperties("TransactionDemarcationLogging", root,
606 "atg.dtm.TransactionDemarcationLogging", props);
607
608 return NucleusTestUtils.createProperties("TransactionManager", root,
609 "atg.dtm.TransactionManagerImpl", props);
610 }
611
612 /***
613 * Creates the UserTransaction component
614 */
615 public File createUserTransaction(File pRoot) throws IOException {
616 Properties props = new Properties();
617 props.put("transactionManager","/atg/dynamo/transaction/TransactionManager");
618 return NucleusTestUtils.createProperties("UserTransaction",new File(pRoot,"/atg/dynamo/transaction"),"atg.dtm.UserTransactionImpl",props);
619 }
620
621
622 /***
623 * Creates a .properties file for the given repository.
624 * The actual repository implementation is a
625 * <code>atg.adapter.gsa.InitializingGSA</code> class.
626 * This implementation is used instead because it has the ability
627 * to create tables and import data before the repository starts.
628 * @param pRoot
629 * @param pRepositoryPath
630 * @param pDefinitionFiles
631 * @param pSQLAbsolutePath
632 * @param pDropSQLAbsolutePath
633 * @param pImportFiles
634 * @throws IOException
635 */
636 public File createRepositoryPropertiesFile(File pRoot,
637 String pRepositoryPath, String[] pDefinitionFiles, String pCreateSQLAbsolutePath, String pDropSQLAbsolutePath, String[] pImportFiles) throws IOException {
638 return createRepositoryPropertiesFile(pRoot, pRepositoryPath, pDefinitionFiles, pCreateSQLAbsolutePath, pDropSQLAbsolutePath, pImportFiles, null);
639 }
640
641 /***
642 * Creates a .properties file for the given repository.
643 * The actual repository implementation is a
644 * <code>atg.adapter.gsa.InitializingGSA</code> class.
645 * This implementation is used instead because it has the ability
646 * to create tables and import data before the repository starts.
647 * @param pRoot
648 * @param pRepositoryPath
649 * @param pDefinitionFiles
650 * @param pSQLAbsolutePath
651 * @param pDropSQLAbsolutePath
652 * @param pImportFiles
653 * @throws IOException
654 */
655 public File createRepositoryPropertiesFile(File pRoot,
656 String pRepositoryPath, String[] pDefinitionFiles, String pCreateSQLAbsolutePath, String pDropSQLAbsolutePath, String[] pImportFiles, String pJTDataSourceName) throws IOException {
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672 String clazz = sClassName;
673 if(mVersioned)
674 clazz = sVersionedClassName;
675
676 Properties props = new Properties();
677 props.put("repositoryName", "TestRepository"+System.currentTimeMillis());
678 StringBuffer definitionFiles = new StringBuffer();
679 for (int i = 0; i < pDefinitionFiles.length; i++) {
680 Object obj = this.getClass().getClassLoader().getResource(pDefinitionFiles[i]);
681 if (obj != null) {
682 log.debug("Repository definition file "
683 + pDefinitionFiles[i]
684 + " Does not exist in configpath. But it does in classpath. Copying over to configpath");
685 copyToConfigpath(pRoot, pDefinitionFiles[i]);
686 } else if(obj == null && !new File(pRoot, pDefinitionFiles[i]).exists()){
687 throw new AssertionError("ERROR: Repository definition file "
688 + pDefinitionFiles[i] + " not found in classpath or configpath: " + pRoot);
689 }
690
691 definitionFiles.append("/"+pDefinitionFiles[i]);
692 if (i < (pDefinitionFiles.length - 1))
693 definitionFiles.append(",");
694 }
695 props.put("definitionFiles", definitionFiles.toString());
696 if(pImportFiles != null){
697 StringBuffer importFiles = new StringBuffer();
698 for (int i = 0; i < pImportFiles.length; i++) {
699 Object obj = this.getClass().getClassLoader().getResource(
700 pDefinitionFiles[i]);
701 if (obj != null) {
702 System.out
703 .println("DEBUG: import file "
704 + pDefinitionFiles[i]
705 + " Does not exist in configpath. But it does in classpath. Copying over to configpath");
706 copyToConfigpath(pRoot, pImportFiles[i]);
707 } else if (obj == null && !new File(pRoot, pImportFiles[i]).exists()) {
708 throw new AssertionError("ERROR: Repository definition file "
709 + pDefinitionFiles[i] + " not found in classpath or configpath.");
710 }
711
712 importFiles.append(new File(pRoot, pImportFiles[i]).getAbsolutePath());
713 if (i < (pImportFiles.length - 1))
714 importFiles.append(",");
715 }
716 props.put("importFiles", importFiles.toString());
717 props.put("importEveryStartup", "true");
718 }
719 props.put("XMLToolsFactory", "/atg/dynamo/service/xml/XMLToolsFactory");
720 props.put("transactionManager",
721 "/atg/dynamo/transaction/TransactionManager");
722 props.put("idGenerator", "/atg/dynamo/service/IdGenerator");
723 if(pJTDataSourceName == null)
724 props.put("dataSource", "/atg/dynamo/service/jdbc/JTDataSource");
725 else
726 props.put("dataSource", "/atg/dynamo/service/jdbc/"+pJTDataSourceName);
727 props.put("lockManager", "/atg/dynamo/service/ClientLockManager");
728 props.put("idspaces", "/atg/dynamo/service/idspaces.xml");
729 props.put("groupContainerPath", "/atg/registry/RepositoryGroups");
730 props.put("restartingAfterTableCreation", "false");
731 props.put("createTables", "true");
732 props.put("loggingError", "true");
733 if(pCreateSQLAbsolutePath != null)
734 props.put("sqlCreateFiles","default="+pCreateSQLAbsolutePath);
735
736 if(pDropSQLAbsolutePath != null)
737 props.put("sqlDropFiles","default="+pDropSQLAbsolutePath);
738 props.put("loggingDebug", "false");
739 props.put("loggingCreateTables", "false");
740
741
742
743 props.put("dropTablesIfExist", "true");
744 props.put("dropTablesAtShutdown", "false");
745 props.put("stripReferences","true");
746 int endIndex = pRepositoryPath.lastIndexOf("/");
747 String repositoryDir = pRepositoryPath.substring(0, endIndex);
748 String repositoryName = pRepositoryPath.substring(endIndex + 1,
749 pRepositoryPath.length());
750 File root = new File(pRoot, repositoryDir);
751 root.mkdirs();
752
753 if(mVersioned) props.putAll(additionalVersionProperties(pRoot,pRepositoryPath, repositoryName));
754 return NucleusTestUtils
755 .createProperties(repositoryName, root, clazz, props);
756 }
757
758 /***
759 * @param pRoot
760 * @param pRepositoryPath
761 * @param pRepositoryName
762 * @return
763 * @throws IOException
764 */
765 protected Map<String, String> additionalVersionProperties(File pRoot, String pRepositoryPath, String pRepositoryName) throws IOException {
766
767 copyToConfigpath(pRoot, "atg/adapter/version/versionmanager/versionManagerRepository.xml");
768 GSATestUtils.getGSATestUtils()
769 .createRepositoryPropertiesFile(
770 pRoot,
771 "/atg/adapter/version/versionmanager/VersionManagerRepository",
772 new String[] { "/atg/adapter/version/versionmanager/versionManagerRepository.xml" }, null, null, null);
773
774 NucleusTestUtils
775 .createProperties("/atg/adapter/version/versionmanager/AssetFactory", pRoot, "atg.versionmanager.impl.AssetFactoryRepositoryImpl", null);
776
777 NucleusTestUtils
778 .createProperties("/atg/adapter/version/versionmanager/AssetVersionFactory", pRoot, "atg.versionmanager.impl.AssetVersionFactoryRepositoryImpl", null);
779
780 NucleusTestUtils
781 .createProperties("/atg/adapter/version/versionmanager/BranchFactory", pRoot, "atg.versionmanager.impl.BranchFactoryRepositoryImpl", null);
782
783 NucleusTestUtils
784 .createProperties("/atg/adapter/version/versionmanager/DevelopmentLineFactory", pRoot, "atg.versionmanager.impl.DevelopmentLineFactoryRepositoryImpl", null);
785
786 NucleusTestUtils
787 .createProperties("/atg/adapter/version/versionmanager/SnapshotFactory", pRoot, "atg.versionmanager.impl.SnapshotFactoryRepositoryImpl", null);
788
789 NucleusTestUtils
790 .createProperties("/atg/adapter/version/versionmanager/WorkspaceFactory", pRoot, "atg.versionmanager.impl.WorkspaceFactoryRepositoryImpl", null);
791 Properties props = new Properties();
792
793 props.put("assetFactory","AssetFactory");
794 props.put("repository","VersionManagerRepository");
795 props.put("branchFactory","BranchFactory");
796 props.put("developmentLineFactory","DevelopmentLineFactory");
797 props.put("snapshotFactory","SnapshotFactory");
798 props.put("assetVersionFactory","AssetVersionFactory");
799 props.put("workspaceFactory","WorkspaceFactory");
800 props.put("versionedRepositories",pRepositoryName+"="+pRepositoryPath);
801 props.put("sendCheckinEvents","false");
802 props.put("clientLockManager","/atg/dynamo/service/ClientLockManager");
803
804 NucleusTestUtils
805 .createProperties("/atg/adapter/version/versionmanager/VersionManagerService", pRoot, "atg.versionmanager.VersionManager", props);
806
807
808
809 Map<String, String> extraProps= new HashMap<String, String>();
810 props.put("versionManager", "/atg/adapter/version/versionmanager/VersionManagerService");
811 props.put("versionItemsByDefault", "true");
812 return extraProps;
813 }
814
815 /***
816 * @param prop
817 * @throws FileNotFoundException
818 * @throws IOException
819 */
820 public void copyToConfigpath(File pConfigRoot, String pString) throws FileNotFoundException, IOException {
821 copyToConfigpath(pConfigRoot, pString, null);
822 }
823
824 /***
825 * @param prop
826 * @param configPath where in config path the file must be copied.
827 * @throws FileNotFoundException
828 * @throws IOException
829 */
830 public void copyToConfigpath(File pConfigRoot, String pString, String configPath) throws FileNotFoundException, IOException {
831
832 pConfigRoot.mkdirs();
833 String path = pString;
834 if(configPath == null)
835 configPath = path.substring(0, path.lastIndexOf('/'));
836 File dir = new File(pConfigRoot, configPath);
837 dir.mkdirs();
838 File prop = new File(dir, path.substring(path.lastIndexOf('/')));
839 if (prop.exists()) prop.delete();
840 prop.createNewFile();
841 OutputStream os = new FileOutputStream(prop);
842 InputStream dataStream = this.getClass().getClassLoader().getResourceAsStream(pString);
843 while(dataStream.available() != 0){
844 byte[] buff = new byte[1024];
845 int available = dataStream.available();
846 dataStream.read(buff);
847 os.write(buff, 0, available >= 1024 ? 1024: available);
848 }
849 os.flush();
850 }
851
852
853 /***
854 * Creates a .properties file for the given repository.
855 * The actual repository implementation is a
856 * <code>atg.adapter.gsa.InitializingGSA</code> class.
857 * This implementation is used instead because it has the ability
858 * to create tables and import data before the repository starts.
859 * @param pRoot
860 * @param pRepositoryPath
861 * @param pDefinitionFiles
862 * @throws IOException
863 */
864 public File createVersionRepositoryPropertiesFile(File pRoot,
865 String pRepositoryPath, String[] pDefinitionFiles) throws IOException {
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881 String clazz = "atg.adapter.gsa.InitializingVersionRepository";
882 Properties props = new Properties();
883 props.put("repositoryName", "TestRepository");
884 StringBuffer definitionFiles = new StringBuffer();
885 for (int i = 0; i < pDefinitionFiles.length; i++) {
886 definitionFiles.append(pDefinitionFiles[i]);
887 if (i < (pDefinitionFiles.length - 1))
888 definitionFiles.append(",");
889 }
890 props.put("definitionFiles", definitionFiles.toString());
891 props.put("XMLToolsFactory", "/atg/dynamo/service/xml/XMLToolsFactory");
892 props.put("transactionManager",
893 "/atg/dynamo/transaction/TransactionManager");
894 props.put("idGenerator", "/atg/dynamo/service/IdGenerator");
895 props.put("dataSource", "/atg/dynamo/service/jdbc/JTDataSource");
896 props.put("lockManager", "/atg/dynamo/service/ClientLockManager");
897 props.put("groupContainerPath", "/atg/registry/RepositoryGroups");
898 props.put("versionManager", "/atg/test/version/VersionManager");
899 props.put("versionItemByDefault", "true");
900 props.put("loggingDebug", "true");
901
902
903
904 props.put("dropTablesIfExist", "true");
905 props.put("dropTablesAtShutdown", "false");
906 props.put("stripReferences","true");
907 int endIndex = pRepositoryPath.lastIndexOf("/");
908 String repositoryDir = pRepositoryPath.substring(0, endIndex);
909 String repositoryName = pRepositoryPath.substring(endIndex + 1,
910 pRepositoryPath.length());
911 File root = new File(pRoot, repositoryDir);
912 root.mkdirs();
913
914 ;
915
916 return NucleusTestUtils
917 .createProperties(repositoryName, root, clazz, props);
918 }
919
920
921 /***
922 * Returns all the tables names used for the given repository.
923 */
924 public String [] getTableNames(GSARepository pRepository) throws Exception {
925 ArrayList<String> names = new ArrayList<String>();
926 String[] descriptorNames = pRepository.getItemDescriptorNames();
927
928 GSAItemDescriptor itemDescriptors[];
929
930 int i, length = descriptorNames.length;
931
932 itemDescriptors = new GSAItemDescriptor[length];
933 for (i=0; i<length; i++) {
934 itemDescriptors[i] = (GSAItemDescriptor)pRepository.getItemDescriptor(descriptorNames[i]);
935 }
936
937
938
939 for (i=0; i<length; i++) {
940 GSAItemDescriptor desc = itemDescriptors[i];
941 Table[] tables = desc.getTables();
942 if ( tables != null ) {
943 for (int j = 0; j < tables.length; j++) {
944 String name = tables[j].getName();
945 names.add(name);
946 }
947 }
948 }
949 return (String[])names.toArray(new String[0]);
950 }
951
952 /***
953 * Given a repository, and the DBUtils object used to create the connection for that
954 * Repository, this method asserts that all the tables are empty
955 * @param dbTwo
956 * @param storeRepository
957 * @throws Exception
958 * @throws SQLException
959 */
960 public void assertEmptyRepository(DBUtils dbTwo, GSARepository storeRepository) throws Exception, SQLException {
961 String [] namesAfter = getTableNames(storeRepository);
962 for (int i = 0 ; i < namesAfter.length; i++) {
963 log.info(namesAfter[i] + ":" + dbTwo.getRowCount(namesAfter[i]));
964 Assert.assertEquals(0,dbTwo.getRowCount(namesAfter[i]));
965 }
966 }
967
968 /***
969 * Creates the das_id_generator tables using the given database
970 * @param db
971 * @throws SQLException
972 */
973 public void createIDGeneratorTables(DBUtils db) throws SQLException {
974 try {
975 if(!db.isDB2())
976 db
977 .update(" create table das_id_generator (id_space_name varchar(60) not null,"
978 + "seed numeric(19,0) not null, batch_size integer not null, prefix varchar(10) null,"
979 + " suffix varchar(10) null, primary key (id_space_name)) ");
980 else
981 db
982 .update(" create table das_id_generator (id_space_name varchar(60) not null,"
983 + "seed numeric(19,0) not null, batch_size integer not null, prefix varchar(10) default null,"
984 + " suffix varchar(10) default null, primary key (id_space_name)) ");
985 }
986 catch (SQLException e) {
987
988 log.info("DROPPING DAS_ID_GENERATOR");
989 db.update("drop table das_id_generator");
990 if(!db.isDB2())
991 db
992 .update(" create table das_id_generator (id_space_name varchar(60) not null,"
993 + "seed numeric(19,0) not null, batch_size integer not null, prefix varchar(10) null,"
994 + " suffix varchar(10) null, primary key (id_space_name)) ");
995 else
996 db
997 .update(" create table das_id_generator (id_space_name varchar(60) not null,"
998 + "seed numeric(19,0) not null, batch_size integer not null, prefix varchar(10) default null,"
999 + " suffix varchar(10) default null, primary key (id_space_name)) ");
1000
1001
1002 }
1003 }
1004
1005 /***
1006 * @param pVerRep
1007 * @param pImportFiles
1008 * @param pWorkspaceName
1009 * @param pDoWithoutTransaction
1010 * @param pWorkspaceComment
1011 * @throws VersionException
1012 */
1013 public static void importFiles(VersionRepository pVerRep,
1014 String[] pImportFiles, String pWorkspaceName, boolean pDoWithoutTransaction,
1015 String pWorkspaceComment, boolean pCheckin) throws VersionException {
1016 VersionManager vm = pVerRep.getVersionManager();
1017 Workspace ws = vm.getWorkspaceByName(pWorkspaceName);
1018 if (ws == null)
1019 throw new IllegalArgumentException("No such workspace " + pWorkspaceName);
1020
1021 if(TemplateParser.importFiles(pVerRep, pImportFiles, new PrintWriter(
1022 System.out), pDoWithoutTransaction, VersioningContextUtil.createVersioningContext(ws
1023 .getName(), pWorkspaceComment, pCheckin)) != 0)
1024 throw new AssertionError("Versioned import failed");
1025 }
1026
1027 /***
1028 * @return
1029 */
1030 public static GSATestUtils getGSATestUtils() {
1031 if(SINGLETON_DEFAULT == null)
1032 SINGLETON_DEFAULT = new GSATestUtils(false);
1033 return SINGLETON_DEFAULT;
1034 }
1035
1036 /***
1037 * @return
1038 */
1039 public static GSATestUtils getVersionedGSATestUtils() {
1040 if(SINGLETON_VERSIONED == null)
1041 SINGLETON_VERSIONED = new GSATestUtils(true);
1042 return SINGLETON_VERSIONED;
1043
1044 }
1045
1046
1047 /***
1048 * Dump all the data from a table to the console
1049 * @param pTable
1050 * @throws SQLException
1051 */
1052 public static void dumpTable(Table pTable, Collection<String> pPrintColumnNames) throws SQLException {
1053 GSARepository gsa = pTable.getItemDescriptor().getGSARepository();
1054 Connection c = null;
1055 PreparedStatement st = null;
1056 try {
1057 c = gsa.getConnection();
1058 pTable.loadColumnInfo(c);
1059 Collection<?> colNames = pPrintColumnNames;
1060 Map<?, ?> map = ((Map<?, ?>) gsa.getColumnInfoCache().get(
1061 pTable.mName));
1062 if(map == null)
1063 map = ((Map<?, ?>) gsa.getColumnInfoCache().get(
1064 pTable.mName.toUpperCase()));
1065 if(pPrintColumnNames.isEmpty())
1066 colNames = map.keySet();
1067 Iterator<?> iter0 = colNames.iterator();
1068 String sql = "SELECT ";
1069 while (iter0.hasNext()) {
1070 Object obj = iter0.next();
1071 if (iter0.hasNext())
1072 sql += obj + ",";
1073 else
1074 sql += obj;
1075 }
1076 sql += " FROM " + pTable.getBaseName();
1077 st = c.prepareStatement(sql);
1078 ResultSet rs = st.executeQuery();
1079 System.out.print("DUMP FOR TABLE: " + pTable.getBaseName().toUpperCase()
1080 + "\n");
1081 Iterator<?> iter1 = colNames.iterator();
1082 int truncateThreshold = 20;
1083 while (iter1.hasNext()) {
1084 String colname = (String)iter1.next();
1085 System.out.print( colname.substring(0, colname.length() > 18 ? 18:colname.length()));
1086 for (int i = 0; i < truncateThreshold-colname.length(); i++) {
1087 System.out.print(" ");
1088 }
1089 System.out.print(" ");
1090 }
1091 System.out.print("\n");
1092 while (rs.next()) {
1093 int i = 1;
1094 Iterator<?> iter = colNames.iterator();
1095 while (iter.hasNext()) {
1096
1097 iter.next();
1098 Object obj = rs.getObject(i++);
1099 if(obj == null) obj = "NULL";
1100 System.out.print( obj.toString().substring(0, obj.toString().length() > truncateThreshold ? truncateThreshold:obj.toString().length()));
1101 for (int j = 0; j < truncateThreshold-obj.toString().length(); j++) {
1102 System.out.print(" ");
1103 }
1104 System.out.print(" ");
1105
1106
1107
1108
1109 }
1110 }
1111 } finally {
1112 if (st != null)
1113 st.close();
1114 }
1115 }
1116
1117 /***
1118 * @param pVersionRepository
1119 * @param pString
1120 */
1121 public static void dumpTables(GSARepository pRepository, String pItemDescriptorName) throws RepositoryException, SQLException {
1122 GSAItemDescriptor itemdesc = (GSAItemDescriptor) pRepository.getItemDescriptor(pItemDescriptorName);
1123 Table[] tables = itemdesc.getTables();
1124 HashSet<String> doneTables = new HashSet<String>();
1125 for (int i = 0; tables != null && i < tables.length; i++) {
1126 Table table = tables[i];
1127 if(doneTables.contains(table.getName())) continue;
1128 dumpTable(table, new ArrayList<String>());
1129 doneTables.add(table.getName());
1130 }
1131 }
1132 }