View Javadoc

1   /*
2   
3   nextobjects Copyright (C) 2001-2005 Emmanuel Florent
4   
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by the
7   Free Software Foundation; either version 2 of the License, or (at your
8   option) any later version.
9   
10  This program is distributed in the hope that it will
11  be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
12  of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13  PURPOSE. See the GNU General Public License for more details.
14  
15  You should have received a copy of the GNU General Public License along
16  with this program; if not, write to the Free Software Foundation, Inc., 59
17  Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  
19  */
20  
21  package org.devaki.nextobjects.util;
22  
23  import java.io.BufferedInputStream;
24  import java.io.BufferedOutputStream;
25  import java.io.File;
26  import java.io.FileInputStream;
27  import java.io.FileNotFoundException;
28  import java.io.FileOutputStream;
29  import java.io.IOException;
30  import java.util.Enumeration;
31  import java.util.Properties;
32  import java.util.Vector;
33  import java.util.zip.ZipEntry;
34  import java.util.zip.ZipException;
35  import java.util.zip.ZipFile;
36  import java.awt.Dimension;
37  import java.awt.Point;
38  import java.awt.Color;
39  import javax.swing.ImageIcon;
40  import javax.swing.JProgressBar;
41  import org.devaki.nextobjects.NextObjects;
42  import org.devaki.nextobjects.workspace.models.ConceptualModel;
43  import org.devaki.nextobjects.workspace.models.Database;
44  import org.devaki.nextobjects.workspace.models.columns.ColumnType;
45  import org.devaki.nextobjects.workspace.models.objects.Association;
46  import org.devaki.nextobjects.workspace.models.objects.AssociationLink;
47  import java.util.StringTokenizer;
48  
49  /***
50   * This class containts all properties load-dump plus some usefull functions
51   * @author eflorent
52   */
53  
54  public class NOTools
55  {
56      /*** Do we save properties whille quitting */
57      public static boolean save= true;
58  
59      /*** Torque Version */
60      public static final String TORQUE_VERSION= "3.1";
61  
62      /*** Directory of nextObjects */
63      public static final String APP_HOME= System.getProperty("nextobjects.home");
64  
65      /*** Home directory of the user currently using nextObjects */
66      public static final String USER_HOME= System.getProperty("user.home");
67  
68      /*** Directory of nextObjects in the user home directory */
69      public static final String NEXTOBJECT_USER_HOME=
70          new StringBuffer().append(USER_HOME).append(File.separator).append(".nextobjects").toString();
71  
72      /*** Directory of Torque in the user home directory */
73      public static final String TORQUE_HOME=
74          new StringBuffer()
75              .append(USER_HOME)
76              .append(File.separator)
77              .append("torque-gen-")
78              .append(TORQUE_VERSION)
79              .toString();
80  
81      /*** Location of the preferences file */
82      private static final String NO_PREFS=
83          new StringBuffer().append(NEXTOBJECT_USER_HOME).append(File.separator).append("nextobjects.pro").toString();
84  
85      /***Temporary Directory */
86      public static final String TMP_DIR= System.getProperty("java.io.tmpdir");
87      /*** Properties of nextObjects */
88      public static Properties NO_PROPS= new Properties();
89  
90      /*** List of supported database engines */
91      public static final Vector TORQUE_DB= new Vector(14);
92  
93      /*** List of supported datatypes */
94      public static final Vector TORQUE_TYPES= new Vector(28);
95  
96      /*** Logger window foreground color */
97      public static final Color NO_LOG_FOREGROUND= Color.GREEN;
98  
99      /*** Logger window background color */
100     public static final Color NO_LOG_BACKGROUND= Color.BLACK;
101 
102     /*** Logger window log pattern */
103     public static final String NO_LOG_PATTERN= "[%p] %m%n";
104 
105     /***
106      * Construct a 'NOHelper' object.
107      * Fill in vectors TORQUE_DB and TORQUE_TYPES
108      */
109     public NOTools()
110     {
111         // init variables nextobjects
112         loadProperties();
113         loadTorqueType();
114     }
115 
116     /***
117      * Load torque types.
118      */
119     public void loadTorqueType()
120     {
121         // Database Type
122         TORQUE_DB.addElement(new Database("Postgres", "postgresql", "org.postgresql.Driver", "No known problems"));
123         TORQUE_DB.addElement(new Database("Oracle", "oracle", "oracle.jdbc.driver.OracleDriver", "No known problems"));
124         TORQUE_DB.addElement(new Database("MySQL", "mysql", "org.gjt.mm.mysql.Driver", "No known problems"));
125         TORQUE_DB.addElement(new Database("DB2", "db2", "COM.ibm.db2.jdbc.{app|net}.DB2Driver", "Untested"));
126         TORQUE_DB.addElement(
127             new Database(
128                 "DB2/AS400",
129                 "db2400",
130                 "com.ibm.as400.access.AS400JDBCDriver",
131                 "Possible case-insensitivity issues"));
132         TORQUE_DB.addElement(
133             new Database("MS SQL", "mssql", "com.microsoft.jdbc.sqlserver.SQLServerDriver", "Untested"));
134         TORQUE_DB.addElement(new Database("SapDB", "sapdb", "com.sap.dbtech.jdbc.DriverSapDB", "Untested"));
135         TORQUE_DB.addElement(new Database("Cloudscape", "cloudscape", "COM.cloudscape.core.JDBCDriver", "Untested"));
136         TORQUE_DB.addElement(new Database("Hypersonic", "hypersonic", "org.hsql.jdbcDriver", "Untested"));
137         TORQUE_DB.addElement(new Database("Interbase", "interbase", "interbase.interclient.Driver", "Untested"));
138         TORQUE_DB.addElement(new Database("Sybase", "sybase", "com.sybase.jdbc2.jdbc.SybDriver", "Untested"));
139         TORQUE_DB.addElement(new Database("Axion", "axion", "org.axiondb.jdbc.AxionDriver", "alpha"));
140         //TORQUE_DB.addElement(new Database("MS Access", "msaccess", "sun.jdbc.odbc.JdbcOdbcDriver", ""));
141         //TORQUE_DB.addElement(new Database("Instant DB", "instantdb", "org.enhydra.instantdb.jdbc.idbDriver", ""));
142         //TORQUE_DB.addElement(new Database("Informix", "informix", "com.informix.jdbc.IfxDriver", ""));
143         //TORQUE_DB.addElement(new Database("Weblogic", "weblogic", "weblogic.jdbc.pool.Driver", ""));
144 
145         // Field Type
146         TORQUE_TYPES.addElement(new ColumnType("VARCHAR", "255", ""));
147         TORQUE_TYPES.addElement(new ColumnType("INTEGER", "", ""));
148         TORQUE_TYPES.addElement(new ColumnType("NUMERIC", "4", ""));
149         TORQUE_TYPES.addElement(new ColumnType("DATE", "", ""));
150         TORQUE_TYPES.addElement(new ColumnType("FLOAT", "2", ""));
151         TORQUE_TYPES.addElement(new ColumnType("CHAR", "", ""));
152         TORQUE_TYPES.addElement(new ColumnType("BLOB", "", ""));
153         TORQUE_TYPES.addElement(new ColumnType("CLOB", "", ""));
154         TORQUE_TYPES.addElement(new ColumnType("BIGINT", "", ""));
155         TORQUE_TYPES.addElement(new ColumnType("BINARY", "", ""));
156         TORQUE_TYPES.addElement(new ColumnType("BIT", "", ""));
157         TORQUE_TYPES.addElement(new ColumnType("BOOLEANINT", "1", ""));
158         TORQUE_TYPES.addElement(new ColumnType("BOOLEANCHAR", "1", ""));
159         TORQUE_TYPES.addElement(new ColumnType("DECIMAL", "2", ""));
160         TORQUE_TYPES.addElement(new ColumnType("LONGVARCHAR", "8192", ""));
161         TORQUE_TYPES.addElement(new ColumnType("REAL", "8", ""));
162         TORQUE_TYPES.addElement(new ColumnType("SMALLINT", "", ""));
163         TORQUE_TYPES.addElement(new ColumnType("TINYINT", "2", ""));
164         TORQUE_TYPES.addElement(new ColumnType("TIME", "4", ""));
165         TORQUE_TYPES.addElement(new ColumnType("TIMESTAMP", "4", ""));
166         TORQUE_TYPES.addElement(new ColumnType("VARBINARY", "1024", ""));
167 
168         // thie following type have been removed because they cause
169         // sql-generator to crash (torque 3.0)
170         /*
171         TORQUE_TYPES.addElement(new ColumnType("DISTINCT", "", ""));
172         TORQUE_TYPES.addElement(new ColumnType("JAVA_OBJECT", "", ""));
173         TORQUE_TYPES.addElement(new ColumnType("NULL", "", ""));
174         TORQUE_TYPES.addElement(new ColumnType("ARRAY", "", ""));
175         TORQUE_TYPES.addElement(new ColumnType("OTHER", "", ""));
176         TORQUE_TYPES.addElement(new ColumnType("REF", "", ""));
177         TORQUE_TYPES.addElement(new ColumnType("STRUC", "", ""));
178         */
179     }
180 
181     /***
182      * Load an icon
183      * @param pImgName the name of the image
184      * @return the image icon
185      */
186     public final static ImageIcon loadIconResource(final String pImgName)
187     {
188         try
189         {
190             return new ImageIcon(
191                 org.devaki.nextobjects.NextObjects.class.getResource("/org/devaki/nextobjects/icons/" + pImgName));
192         }
193         catch (Throwable t)
194         {
195             System.err.println("Image_Load_Error : " + pImgName);
196             return null;
197         }
198     }
199 
200     /***
201      * Load preferences from the 'NO_PREFS' properties file
202      */
203     public void loadProperties()
204     {
205 
206         // to be buffered for faster startup
207         // Try loading the preferences
208         try
209         {
210             NO_PROPS.load(new FileInputStream(NO_PREFS));
211         }
212         // The file does not exist, create it
213         catch (Exception ioex)
214         {
215             NO_PROPS.put("width", "1024");
216             NO_PROPS.put("heigth", "768");
217             NO_PROPS.put("torque", "0");
218 
219             NO_PROPS.put("log4j.rootCategory", "DEBUG, Default, Chainsaw");
220             NO_PROPS.put("log4j.appender.Default", "org.apache.log4j.FileAppender");
221             NO_PROPS.put("log4j.appender.Default.file", "nextobjects.log");
222             NO_PROPS.put("log4j.appender.Default.layout", "org.apache.log4j.xml.XMLLayout");
223             NO_PROPS.put("log4j.appender.Default.append", "false");
224 
225             NO_PROPS.put("log4j.appender.Chainsaw", "org.apache.log4j.net.SocketAppender");
226             NO_PROPS.put("log4j.appender.Chainsaw.remoteHost", "localhost");
227             NO_PROPS.put("log4j.appender.Chainsaw.port", "4445");
228             NO_PROPS.put("log4j.appender.Chainsaw.locationInfo", "true");
229 
230             // Try saving the properties
231             try
232             {
233                 FileOutputStream file= new FileOutputStream(NO_PREFS);
234                 NO_PROPS.store(file, "NextObjects preferences");
235                 file.flush();
236                 file.close();
237             }
238             catch (IOException exc)
239             {
240                 System.out.println("preparing first execution ...");
241             }
242         }
243 
244         NORecentFile.load();
245     }
246 
247     /***
248      * Save preferences to the 'NO_PREFS' properties file
249      */
250     public static void saveProperties()
251     {
252         // Retrieve actual dimensions of the application and save them
253         Dimension dim= NextObjects.getReference().getSize();
254         NO_PROPS.put("width", Integer.toString(dim.width));
255         NO_PROPS.put("heigth", Integer.toString(dim.height));
256         // Try writing the properties file
257         try
258         {
259             FileOutputStream file= new FileOutputStream(NO_PREFS);
260             NO_PROPS.store(file, "nextObjects preferences");
261             file.flush(); // ??
262             file.close();
263         }
264         catch (Exception exc)
265         {
266             System.out.println(exc.toString());
267         }
268     }
269 
270     /***
271      * Deletes a file or a directory along with all files and directories
272      * it contains.
273      *
274      * @param file the file or directory to delete
275      * @return whether delete was successful
276      */
277     public static final boolean deleteFile(File file)
278     {
279         if (file == null)
280         {
281             return false;
282         }
283 
284         if (file.isDirectory())
285         {
286             String[] dirListing= file.list();
287 
288             // For each file/directory in listing, make recursive call.
289             int len= dirListing.length;
290             for (int i= 0; i < len; i++)
291             {
292                 if (!deleteFile(new File(file.getAbsolutePath() + File.separator + dirListing[i])))
293                 {
294                     // Break and return an error.
295                     return false;
296                 }
297             }
298         }
299 
300         // Delete file or directory.
301         if (!file.delete())
302         {
303             // Display message and return an error.
304             System.out.println("Could not delete: " + file.getAbsolutePath());
305             return false;
306         }
307 
308         return true;
309     }
310 
311     /***
312      * Given a path string create all the directories in the path. For example,
313      * if the path string is "java/applet", the method will create directory
314      * "java" and then "java/applet" if they don't exist. The file separator
315      * string "/" is platform dependent system property.
316      * @param path Directory path string.
317      */
318     public static void createDirectory(String path)
319     {
320         File dir= new File(path);
321         if (dir.exists())
322         {
323             return;
324         }
325         else
326         {
327             if (dir.mkdirs())
328             {
329                 return;
330             }
331             else
332             {
333                 throw (new SecurityException());
334             }
335         }
336 
337     }
338     /*** 
339      * Calcultate distance
340      * @param p1 the A point
341      * @param p2 the B point
342      * @return the distance
343      */
344     public static int distance(Point p1, Point p2)
345     {
346         return (int) Math.sqrt(Math.pow(p1.getX() - p2.getX(), 2) + Math.pow(p1.getY() - p2.getY(), 2));
347     }
348     /***
349      * Calculate middle
350      * @param pA the A point
351      * @param pB the B point
352      * @return the point at the middle
353      */
354     public static Point getMiddle(Point pA, Point pB)
355     {
356         double x= Math.abs(pA.getX() - pB.getX());
357         x= x / 2;
358         x= x + Math.min(pA.getX(), pB.getX());
359         double y= Math.abs(pA.getY() - pB.getY());
360         y= y / 2;
361         y= y + Math.min(pA.getY(), pB.getY());
362         return new Point((int) x, (int) y);
363     }
364 
365     /***
366      * Unzip a fie
367      * @param file the file
368      * @param dest the destination directory
369      * @param jProgressBar the load advance
370      * @throws ZipException
371      * @throws IOException
372      */
373 
374     public static void unzip(String file, String dest, JProgressBar jProgressBar) throws ZipException, IOException
375     {
376         int s= 0;
377         ZipFile zipFile= new ZipFile(file);
378         Enumeration enum= zipFile.entries();
379         try
380         {
381             while (enum.hasMoreElements())
382             {
383 
384                 ZipEntry target= new ZipEntry((ZipEntry) enum.nextElement());
385                 jProgressBar.setValue((int) (++s * 100) / 459);
386                 getEntry(zipFile, target, dest);
387             }
388         }
389         catch (FileNotFoundException e)
390         {
391             System.err.println("zipfile not found");
392         }
393         catch (ZipException e)
394         {
395             throw e;
396         }
397         catch (IOException e)
398         {
399             throw e;
400         }
401     }
402 
403     /***
404      * Get an entry of a zip file
405      * @param zipFile the zip file
406      * @param target the target
407      * @param dest the destination
408      * @throws ZipException
409      * @throws IOException
410      */
411     private static void getEntry(ZipFile zipFile, ZipEntry target, String dest) throws ZipException, IOException
412     {
413 
414         try
415         {
416             File file= new File(dest + File.separator + target.getName());
417 
418             if (target.isDirectory())
419             {
420                 file.mkdirs(); //
421             }
422             else
423             {
424                 BufferedInputStream bis= new BufferedInputStream(zipFile.getInputStream(target));
425 
426                 String parentName;
427                 if ((parentName= file.getParent()) != null)
428                 {
429                     File dir= new File(parentName);
430                     dir.mkdirs(); //
431                 }
432                 BufferedOutputStream bos= new BufferedOutputStream(new FileOutputStream(file), 2048);
433 
434                 int c;
435                 // while EOF
436                 while ((c= bis.read()) != -1)
437                 {
438                     bos.write((byte) c);
439                 }
440                 bos.close();
441             }
442         }
443         catch (ZipException e)
444         {
445             throw e;
446         }
447         catch (IOException e)
448         {
449             throw e;
450         }
451     }
452 
453     /***
454      * return the type of the relation (11,1N,1N) 
455      * so we know wich Merise rule to apply for 
456      * a given association (cardinalities)
457      *  
458     *    card_is  01      11      0N      1N (right)
459     * is_card --------------------------------
460     * 01  | 11      11      1N      1N
461     * 11  | 11      11      1N      1N
462     * 0N  | 1N     1N      NM     NM
463     * 1N   | 1N     1N      NM     NM
464     *  (left)
465      * @param theAssociation the association to indentify
466      * @return the card type
467      */
468 
469     public static int getCardType(Association theAssociation)
470     {
471         int card_is= ((AssociationLink) theAssociation.getAssociationLinks().elementAt(0)).getCard();
472         int is_card= ((AssociationLink) theAssociation.getAssociationLinks().elementAt(1)).getCard();
473 
474         int[][] results=
475             { { ConceptualModel.ASSO_11, ConceptualModel.ASSO_11, ConceptualModel.ASSO_1N, ConceptualModel.ASSO_1N }, {
476                 ConceptualModel.ASSO_11, ConceptualModel.ASSO_11, ConceptualModel.ASSO_1N, ConceptualModel.ASSO_1N }, {
477                 ConceptualModel.ASSO_1N, ConceptualModel.ASSO_1N, ConceptualModel.ASSO_NM, ConceptualModel.ASSO_NM }, {
478                 ConceptualModel.ASSO_1N, ConceptualModel.ASSO_1N, ConceptualModel.ASSO_NM, ConceptualModel.ASSO_NM }
479         };
480 
481         int cardType= results[card_is][is_card];
482 
483         // In any case overwrite previous switch
484         if (theAssociation.getAssociationLinks().size() > 2)
485         {
486             cardType= ConceptualModel.ASSO_NM;
487         }
488         return cardType;
489     }
490 
491     /***
492      * Converts a database schema name to java object name.  Operates
493      * same as underscoreMethod but does not convert anything to
494      * lowercase.
495      *
496      * @param schemaName name to be converted.
497      * @return converted name.
498      * @see org.apache.torque.engine.database.model.NameGenerator
499      * @see #underscoreMethod(String)
500      */
501     public static String getJavaName(String schemaName)
502     {
503         StringBuffer name= new StringBuffer();
504         StringTokenizer tok= new StringTokenizer(schemaName, String.valueOf("_"));
505         while (tok.hasMoreTokens())
506         {
507             String namePart= (String) tok.nextElement();
508             name.append(
509                 new StringBuffer(namePart.length())
510                     .append(Character.toTitleCase(namePart.charAt(0)))
511                     .append(namePart.substring(1))
512                     .toString());
513         }
514         return name.toString();
515     }
516     /***
517      * Give a reference to the app Properties.
518      * @return the java.util.properties for this app
519      */
520     public static Properties getNOProperties()
521     {
522         return NO_PROPS;
523     }
524 
525 }