View Javadoc

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      // TODO Auto-generated constructor stub
60    }
61    /*
62     * @see TestCase#setUp()
63     */
64    protected void setUp() throws Exception {
65      super.setUp();
66    }
67  
68    /*
69     * @see TestCase#tearDown()
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       // Mkdir
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       // if it were null a NPE would have occurred at the earlier dereference
142       //if(n != null)
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     // make sure we have a repository
262     if (r == null)
263       return null;
264   
265     // get the generator to use
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     // generate an id in our id space and return it
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;// ignore enums for now.
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()))//BINARY
345     {
346       return null;
347       //                    return generateBinary();
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     // make sure it's not just a boolean value
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 //  private Object generateBinary() {
421 //    byte[] bytes = new byte[100];
422 //    Random random = new Random();
423 //    random.nextBytes(bytes);
424 //    return bytes;
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 }