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 package atg.adapter.gsa;
15
16 import java.beans.PropertyEditor;
17 import java.io.File;
18 import java.net.URL;
19 import java.sql.SQLException;
20 import java.sql.Timestamp;
21 import java.util.Date;
22 import java.util.HashMap;
23 import java.util.Properties;
24 import java.util.Random;
25
26 import junit.framework.TestCase;
27
28 import org.apache.log4j.Logger;
29
30 import atg.beans.DynamicPropertyDescriptor;
31 import atg.core.util.StringUtils;
32 import atg.nucleus.Nucleus;
33 import atg.nucleus.servlet.NucleusServlet;
34 import atg.repository.MutableRepositoryItem;
35 import atg.repository.RepositoryException;
36 import atg.repository.RepositoryPropertyDescriptor;
37 import atg.service.idgen.IdGenerator;
38 import atg.service.idgen.IdGeneratorException;
39 import atg.test.util.DBUtils;
40
41 /***
42 * A basic GSA test which is expected to be extended than used directly.
43 * Has several utility methods.
44 * @author adwivedi
45 *
46 */
47 public class GSATest extends TestCase {
48
49 private final transient Random random = new Random();
50
51 private static Logger log = Logger.getLogger(GSATest.class);
52
53 private HashMap<String, File> mConfigDir = new HashMap<String, File>();
54 /***
55 *
56 */
57 public GSATest() {
58 super();
59
60 }
61
62
63
64 protected void setUp() throws Exception {
65 super.setUp();
66 }
67
68
69
70
71 protected void tearDown() throws Exception {
72 super.tearDown();
73 }
74
75 /***
76 * Constructor for GSATest.
77 * @param arg0
78 */
79 public GSATest(String arg0) {
80 super(arg0);
81 }
82 public File getConfigpath() {
83 return getConfigpath(null);
84 }
85 /***
86 * Returns the configpath for tests
87 *
88 * @return
89 */
90 public File getConfigpath(String pConfigDirectory) {
91 if (mConfigDir.get(pConfigDirectory) == null) {
92 String configdirname = "config";
93 String packageName = StringUtils.replace(this.getClass().getPackage()
94 .getName(), '.', "/");
95 if (pConfigDirectory != null)
96 configdirname = pConfigDirectory;
97
98 String configFolder = packageName + "/data/" + configdirname;
99
100 URL dataURL = this.getClass().getClassLoader().getResource(configFolder);
101
102 if (dataURL == null) {
103 URL root = this.getClass().getClassLoader().getResource(packageName);
104
105 File f = new File(root.getFile());
106 File f2 = new File(f, "/data/" + configdirname);
107 f2.mkdirs();
108 dataURL = this.getClass().getClassLoader().getResource(configFolder);
109 }
110
111 mConfigDir.put(pConfigDirectory ,new File(dataURL.getFile()));
112 }
113 System.setProperty("atg.configpath",((File) mConfigDir.get(pConfigDirectory)).getAbsolutePath());
114 return (File) mConfigDir.get(pConfigDirectory);
115 }
116
117 /***
118 * Create a repository in the given configpath using the given repository definitions (Absolute paths)
119 * connecting to the db whose properties are specified in pDBProperties @see DBUtils
120 * Method pMethodName is invoked with the GSARepository passed to it as a parameter.
121 * @param pConfigPathWhereToCreateTheRepository
122 * @param definitionFiles
123 * @param pDBProperties
124 * @param pMethodName
125 * @throws Exception
126 * @throws Exception
127 */
128 protected void setUpAndTest(File pConfigPathWhereToCreateTheRepository, String[] definitionFiles, Properties pDBProperties, String pMethodName) throws Exception{
129 String repositoryComponentPath = "/"+getName()+"Repository";
130 GSATestUtils.getGSATestUtils().initializeMinimalConfigpath(pConfigPathWhereToCreateTheRepository,
131 repositoryComponentPath, definitionFiles, pDBProperties, null, null, null, true);
132 Nucleus n = startNucleus(pConfigPathWhereToCreateTheRepository);
133 GSARepository r = (GSARepository) n.resolveName(repositoryComponentPath);
134 try {
135 getClass().getMethod(pMethodName, new Class[] { GSARepository.class })
136 .invoke(this, new Object[] { r });
137 } catch (NoSuchMethodError e) {
138 throw new AssertionError("Please declare a method with name "+pMethodName + " in your class. It must take an atg.adapter.gsa.GSARepository as the only parameter.");
139 }
140 finally{
141
142
143 n.stopService();
144 }
145 }
146
147
148 /***
149 * Createa a file using reasonable defaults.
150 * Your definition file should exist in the same package as the test and should be
151 * names <test_name>Repository.xml. Configpath is assumed to be what is returned
152 *
153 * @param pMethodName
154 * @throws Exception
155 * @throws Exception
156 */
157 protected void setUpAndTest(String pMethodName) throws Exception{
158 File configPathWhereToCreateTheRepository = getConfigpath(null);
159 String packageName = StringUtils.replace(this.getClass().getPackage()
160 .getName(), '.', "/");
161 String fileName = packageName+"/"+getName()+"Repository.xml";
162 URL defaultDefinitionFile = getClass().getResource("/"+fileName);
163 if(defaultDefinitionFile == null )throw new AssertionError("DUDE, I need a file called : "+ fileName +" to start a GSA repository from. ");
164 String[] definitionFiles = new String[]{fileName};
165 Properties DBProperties = DBUtils.getHSQLDBInMemoryDBConnection();
166 setUpAndTest(configPathWhereToCreateTheRepository,
167 definitionFiles, DBProperties,pMethodName);
168 }
169
170 /***
171 * Starts Nucleus using the given config directory
172 * @param configpath
173 * @return
174 */
175 public static Nucleus startNucleus(File configpath) {
176
177 return startNucleus(configpath.getAbsolutePath());
178 }
179 /***
180 * Starts Nucleus given an array of configpath entries
181 * @param configpathStr
182 * @return
183 */
184 public static Nucleus startNucleus(String configpathStr) {
185 System.setProperty("atg.dynamo.license.read", "true");
186 System.setProperty("atg.license.read", "true");
187 NucleusServlet.addNamingFactoriesAndProtocolHandlers();
188 return Nucleus.startNucleus(new String[] {configpathStr});
189 }
190 /***
191 * @param dbName
192 * @return
193 * @throws Exception
194 * @throws SQLException
195 */
196 protected DBUtils initDB(Properties props) throws Exception, SQLException {
197 DBUtils db = new DBUtils(props.getProperty("URL"),props.getProperty("driver"),props.getProperty("user"),props.getProperty("password"));
198 return db;
199 }
200
201 /***
202 * A Dummy test so smokestack won't report this
203 * class as a failure.
204 * It expects that all *Test.class files have
205 * at least one test.
206 *
207 */
208 public final void testDummy() {
209
210 }
211 /***
212 * @param pGSARepository
213 * @param descName
214 * @return
215 * @throws RepositoryException
216 */
217 protected MutableRepositoryItem createDummyItem(GSARepository pGSARepository, String descName, String pID) throws RepositoryException {
218 GSAItemDescriptor descriptor = (GSAItemDescriptor) pGSARepository
219 .getItemDescriptor(descName);
220 MutableRepositoryItem item = null;
221 boolean compoundPrimaryKey = descriptor.getPrimaryTable().getIdColumnCount() > 1;
222 if(pID == null || pID.trim().length() == 0){
223 if(compoundPrimaryKey){
224 item = pGSARepository.createItem(getNewCompoundId(pGSARepository, descriptor), descName);
225 }
226 else
227 item = pGSARepository.createItem(descName);
228 }
229 else{
230 item= pGSARepository.createItem(pID, descName);
231 }
232 RepositoryPropertyDescriptor[] propDescriptors = (RepositoryPropertyDescriptor[]) descriptor
233 .getPropertyDescriptors();
234 for (int j = 0; j < propDescriptors.length; j++) {
235 RepositoryPropertyDescriptor propertyDescriptor = propDescriptors[j];
236 if (propertyDescriptor.isWritable()
237 && !propertyDescriptor.isIdProperty()
238 && propertyDescriptor.isRequired()) {
239 if (propertyDescriptor.isCollectionOrMap()) {
240 } else {
241
242 Object dummyPropertyValue = generateDummyValue(propertyDescriptor);
243 if (dummyPropertyValue != null) {
244 item.setPropertyValue(propertyDescriptor.getName(),
245 dummyPropertyValue);
246 }
247 }
248 }
249 }
250 return item;
251 }
252 /***
253 * Get a id suitable for creating items of this type. We use out
254 * <code>Repository</code>'s <code>IdGenerator</code>.
255 *
256 * @return a new id, which is unique across all items in this
257 * repository with this item descriptor.
258 * @exception RepositoryException if there is trouble creating the id
259 **/
260 protected GSAId getNewCompoundId(GSARepository r, GSAItemDescriptor desc) throws RepositoryException {
261
262 if (r == null)
263 return null;
264
265
266 IdGenerator gen = r.getIdGenerator();
267 if (gen == null)
268 return null;
269
270 Class<?>[] types = desc.getIdTypes();
271 String[] idSpaceNames = desc.getIdSpaceNames();
272 Object[] newId = new Object[types.length];
273
274 if (idSpaceNames.length != types.length)
275 throw new RepositoryException("No ID SPACES ! "+ desc.getItemDescriptorName());
276
277
278 try
279 {
280 for (int i=0;i<types.length;i++) {
281 if (types[i] == String.class) {
282 if(i > 0)
283 newId[i] = "dummyIdPart";
284 else
285 newId[i] = gen.generateStringId(idSpaceNames[i]);
286 }
287 else
288 {
289 long val = gen.generateLongId(idSpaceNames[i]);
290 if (types[i] == Long.class)
291 newId[i] = Long.valueOf(val);
292 else if (types[i] == Float.class)
293 newId[i] = Float.valueOf((float) val);
294 else if (types[i] == Double.class)
295 newId[i] = Double.valueOf((float) val);
296 else if (types[i] == java.sql.Timestamp.class)
297 newId[i] = new java.sql.Timestamp(val);
298 else if (types[i] == java.util.Date.class)
299 newId[i] = new java.util.Date(val);
300 else
301 newId[i] = Integer.valueOf((int)val);
302 }
303 }
304 }
305 catch (IdGeneratorException ie)
306 {
307 throw new RepositoryException(ie);
308 }
309
310 return desc.generateGSAId(newId);
311 }
312
313 @SuppressWarnings("unchecked")
314 protected Object generateDummyValue(RepositoryPropertyDescriptor propertyDescriptor) {
315 if (getEnumeratedValues(propertyDescriptor) != null) {
316 return null;
317 }
318
319 if (propertyDescriptor.getPropertyType().isAssignableFrom(
320 java.lang.String.class)) {
321 return generateString();
322 } else if (propertyDescriptor.getPropertyType().isAssignableFrom(
323 java.lang.Integer.class)) {
324 return generateInteger();
325 } else if (propertyDescriptor.getPropertyType().isAssignableFrom(
326 java.lang.Boolean.class)) {
327 return generateBoolean();
328 } else if (propertyDescriptor.getPropertyType().isAssignableFrom(
329 java.lang.Byte.class)) {
330 return generateByte();
331 } else if (propertyDescriptor.getPropertyType().isAssignableFrom(
332 java.lang.Short.class)) {
333 return generateShort();
334 } else if (propertyDescriptor.getPropertyType().isAssignableFrom(
335 java.lang.Long.class)) {
336 return generateLong();
337 } else if (propertyDescriptor.getPropertyType().isAssignableFrom(
338 java.lang.Float.class)) {
339 return generateFloat();
340 } else if (propertyDescriptor.getPropertyType().isAssignableFrom(
341 java.lang.Double.class)) {
342 return generateDouble();
343 } else if (propertyDescriptor.getPropertyType().isAssignableFrom(
344 (new byte[0]).getClass()))
345 {
346 return null;
347
348 } else if (propertyDescriptor.getPropertyType().isAssignableFrom(
349 java.sql.Timestamp.class)) {
350 return generateTimestamp();
351 } else if (propertyDescriptor.getPropertyType().isAssignableFrom(
352 java.sql.Date.class)) {
353 return generateDate();
354 }
355 return null;
356
357 }
358 /***
359 *
360 * Returns the set of enumerated values, or null if there are none
361 **/
362 String[] getEnumeratedValues(DynamicPropertyDescriptor pDescriptor) {
363 if(pDescriptor == null) return null;
364 PropertyEditor pe = getPropertyEditor(pDescriptor);
365 String[] ret = (pe == null) ? null : pe.getTags();
366
367
368 Class<?> type = pDescriptor.getPropertyType();
369 if ((type == Boolean.class || type == Boolean.TYPE)
370 && ret != null
371 && ret.length == 2
372 && (("true".equals(ret[0]) && "false".equals(ret[1])) || ("false"
373 .equals(ret[0]) && "true".equals(ret[1])))) {
374 return null;
375 } else {
376 return ret;
377 }
378 }
379 /***
380 *
381 * Returns an instance of the property editor, null if there is no
382 * property editor
383 **/
384 PropertyEditor getPropertyEditor(DynamicPropertyDescriptor pDescriptor) {
385 if(pDescriptor == null ) return null;
386 Class<?> peclass = pDescriptor.getPropertyEditorClass();
387 if (peclass == null) {
388 return pDescriptor.getUIPropertyEditor();
389 } else {
390 Object peinst = null;
391 try {
392 peinst = peclass.newInstance();
393 } catch (InstantiationException e) {
394 log.error("Error: ", e);
395 } catch (IllegalAccessException e) {
396 log.error("Error: ", e);
397 }
398 if (peinst instanceof PropertyEditor) {
399 return (PropertyEditor) peinst;
400 } else {
401 return null;
402 }
403 }
404 }
405 /***
406 * @return
407 */
408 private Object generateDate() {
409 return new Date(System.currentTimeMillis());
410 }
411 /***
412 * @return
413 */
414 private Object generateTimestamp() {
415 return new Timestamp(System.currentTimeMillis());
416 }
417 /***
418 // * @return
419 // */
420
421
422
423
424
425
426 /***
427 * @return
428 */
429 private Object generateDouble() {
430 return new Double(random.nextDouble());
431 }
432 /***
433 * @return
434 */
435 private Object generateInteger() {
436 return Integer.valueOf(random.nextInt(32768));
437 }
438 /***
439 * @return
440 */
441 private Object generateFloat() {
442 return new Float(random.nextFloat());
443 }
444 /***
445 * @return
446 */
447 private Object generateLong() {
448 return Long.valueOf(random.nextInt(32278));
449 }
450 /***
451 * @return
452 */
453 private Object generateShort() {
454 return Short.valueOf((short) (random.nextInt(100)));
455 }
456 /***
457 * @return
458 */
459 private Object generateByte() {
460 byte[] bytes = new byte[1];
461 random.nextBytes(bytes);
462 return Byte.valueOf(bytes[0]);
463 }
464 /***
465 * @return
466 */
467 private Object generateBoolean() {
468 return Boolean.valueOf(random.nextBoolean());
469 }
470 /***
471 * @return
472 */
473 private Object generateString() {
474
475 return "DUMMY STRING " + generateInteger();
476 }
477
478
479 }