001: package com.bm.utils;
002:
003: import java.io.ByteArrayInputStream;
004: import java.io.ByteArrayOutputStream;
005: import java.io.File;
006: import java.io.FileOutputStream;
007: import java.io.IOException;
008: import java.io.InputStream;
009: import java.io.OutputStream;
010: import java.io.UnsupportedEncodingException;
011: import java.lang.annotation.Annotation;
012: import java.lang.reflect.Constructor;
013: import java.lang.reflect.Field;
014: import java.lang.reflect.InvocationTargetException;
015: import java.lang.reflect.Method;
016: import java.net.URL;
017: import java.net.URLDecoder;
018: import java.util.ArrayList;
019: import java.util.Collection;
020: import java.util.HashSet;
021: import java.util.LinkedList;
022: import java.util.List;
023: import java.util.Set;
024: import java.util.StringTokenizer;
025: import java.util.Vector;
026: import java.util.jar.JarInputStream;
027: import java.util.zip.ZipEntry;
028:
029: import javax.ejb.Local;
030: import javax.ejb.Remote;
031:
032: import com.bm.datagen.Generator;
033: import com.bm.datagen.annotations.GeneratorType;
034: import com.bm.introspectors.Property;
035:
036: /**
037: * Util class for ejb3unit.
038: *
039: * @author Daniel Wiese
040: */
041: public final class Ejb3Utils {
042:
043: private static final org.apache.log4j.Logger log = org.apache.log4j.Logger
044: .getLogger(Ejb3Utils.class);
045:
046: /**
047: * This field is used to OSTYPE_WINDOWS.
048: */
049: public static final int OSTYPE_WINDOWS = 1;
050:
051: /**
052: * This field is used to OSTYPE_WINNT.
053: */
054: public static final int OSTYPE_WINNT = 2;
055:
056: /**
057: * This field is used to OSTYPE_WINCE.
058: */
059: public static final int OSTYPE_WINCE = 3;
060:
061: /**
062: * This field is used to OSTYPE_LINUX.
063: */
064: public static final int OSTYPE_LINUX = 4;
065:
066: /**
067: * This field is used to OSTYPE_MAC.
068: */
069: public static final int OSTYPE_MAC = 5;
070:
071: /**
072: * This field is used to OSTYPE_SOLARIS.
073: */
074: public static final int OSTYPE_SOLARIS = 6;
075:
076: /**
077: * This field is used to OSTYPE_SUN.
078: */
079: public static final int OSTYPE_SUN = 7;
080:
081: /**
082: * This field is used to OSTYPE_NETWARE.
083: */
084: public static final int OSTYPE_NETWARE = 8;
085:
086: /**
087: * This field is used to OSTYPE_OS2.
088: */
089: public static final int OSTYPE_OS2 = 9;
090:
091: /**
092: * This field is used to OSTYPE_UNKNOWN.
093: */
094: public static final int OSTYPE_UNKNOWN = 10;
095:
096: /** default type * */
097: private static int type = OSTYPE_UNKNOWN;
098:
099: private Ejb3Utils() {
100: // intentionally left blank
101: }
102:
103: /**
104: * Isolates a jar file when a file was found inside a jar.
105: *
106: * @param fileInJar -
107: * the path to the file inside the jar file
108: * @return - the name of the jar file
109: */
110: public static String isolateJarName(URL fileInJar) {
111: String urlSt = getDecodedFilename(fileInJar);
112: urlSt = urlSt.substring("file:/".length(), urlSt.indexOf("!"));
113: // under linux, solaris we need an absolute path
114: int os = getOs();
115: if (os == OSTYPE_LINUX || os == OSTYPE_SOLARIS
116: || os == OSTYPE_SUN || os == OSTYPE_MAC) {
117: urlSt = "/" + urlSt;
118: }
119: return urlSt;
120: }
121:
122: /**
123: * Decodes an encoded file name in url
124: *
125: * @param url
126: * the file name
127: * @return the decoded version
128: */
129: public static String getDecodedFilename(URL url) {
130: String decoded = null;
131: try {
132: decoded = URLDecoder.decode(url.getFile(), "UTF-8");
133: } catch (UnsupportedEncodingException e) {
134: throw new IllegalArgumentException(e);
135: }
136: return decoded;
137: }
138:
139: /**
140: * Creates a new instance of a bean, even if it's protected constructor.
141: * (chapter 2.1 page 17), "The entity class must have a no-arg constructor.
142: * The entity class may have other constructors as well. The no-arg
143: * constructor must be public or protected."
144: *
145: * @author Daniel Wiese
146: * @since 28.03.2007
147: * @param <T>
148: * @param forClass
149: * for which class
150: * @return the instrance
151: */
152: @SuppressWarnings("unchecked")
153: public static <T> T getNewInstance(Class<T> forClass) {
154: Constructor<T>[] parameterlessConstructors = (Constructor<T>[]) forClass
155: .getDeclaredConstructors();
156: if (parameterlessConstructors == null) {
157: throw new RuntimeException(
158: "The session/entity bean ("
159: + forClass.getName()
160: + ") has no public/protected parameterles constructor");
161: }
162:
163: for (Constructor<T> current : parameterlessConstructors) {
164: final Class[] params = current.getParameterTypes();
165: if (params == null || params.length == 0) {
166: current.setAccessible(true);
167: T back = null;
168: try {
169: back = current.newInstance((Object[]) null);
170: } catch (InstantiationException e) {
171: log
172: .error(
173: "Canīt create the session/entity bean",
174: e);
175: throw new RuntimeException(
176: "Canīt create the session/entity bean", e);
177:
178: } catch (IllegalArgumentException e) {
179: log.error("Canīt create the entity bean", e);
180: throw new RuntimeException(
181: "Canīt create the session/entity bean", e);
182: } catch (InvocationTargetException e) {
183: log.error("Canīt create the entity bean", e);
184: throw new RuntimeException(
185: "Canīt create the session/entity bean", e);
186: } catch (SecurityException e) {
187: throw new RuntimeException(
188: "Insufficient access rights to create the session/entity bean ("
189: + forClass.getName() + ")");
190: } catch (IllegalAccessException e) {
191: throw new RuntimeException(
192: "Insufficient access rights to create the session/entity bean ("
193: + forClass.getName() + ")");
194: }
195: return back;
196: }
197: }
198:
199: throw new RuntimeException("The session/entity bean ("
200: + forClass.getName()
201: + ") has no public/protected parameterles constructor");
202: }
203:
204: /**
205: * Determines the OS.
206: *
207: * @return an integer identifying the OS (one of the OSTYPE constants)
208: */
209: public static int getOs() {
210: if (type == OSTYPE_UNKNOWN) {
211:
212: final String osname = System.getProperty("os.name")
213: .toLowerCase();
214: log.info("OS was found to be: " + osname);
215: if (osname.indexOf("windows") != -1) {
216: if (osname.indexOf("nt") != -1
217: || osname.indexOf("2000") != -1
218: || osname.indexOf("xp") != -1) {
219: type = OSTYPE_WINNT;
220: } else if (osname.indexOf("ce") != -1) {
221: type = OSTYPE_WINCE;
222: } else {
223: type = OSTYPE_WINDOWS;
224: }
225: } else if (osname.indexOf("linux") != -1
226: || osname.indexOf("bsd") != -1) {
227: type = OSTYPE_LINUX;
228: } else if (osname.indexOf("mac os") != -1
229: || osname.indexOf("macos") != -1
230: // SoyLatte JDK returns "darwin" on Mac OSX
231: || osname.indexOf("darwin") != -1) {
232: type = OSTYPE_MAC;
233: } else if (osname.indexOf("solaris") != -1) {
234: type = OSTYPE_SOLARIS; // could also be old freebsd version
235: } else if (osname.indexOf("sun") != -1) {
236: type = OSTYPE_SUN;
237: } else if (osname.indexOf("netware") != -1) {
238: type = OSTYPE_NETWARE;
239: } else if (osname.indexOf("os/2") != -1) {
240: type = OSTYPE_OS2;
241: } else {
242: type = OSTYPE_UNKNOWN;
243: }
244: }
245:
246: return type;
247: }
248:
249: /**
250: * Dump the contents of a JarArchive to the specified destination.
251: *
252: * @param in -
253: * the jar archive as input stream
254: * @param dest -
255: * the destination (to extract the content)
256: * @return - a list with all extracted files
257: * @throws IOException -
258: * in an error case
259: */
260: public static List<File> unjar(InputStream in, File dest)
261: throws IOException {
262:
263: final List<File> back = new ArrayList<File>();
264: if (!dest.exists()) {
265: dest.mkdirs();
266: }
267:
268: if (!dest.isDirectory()) {
269: throw new IOException("Destination must be a directory.");
270: }
271:
272: JarInputStream jin = new JarInputStream(in);
273: final byte[] buffer = new byte[1024];
274: ZipEntry entry = jin.getNextEntry();
275: while (entry != null) {
276:
277: String fileName = entry.getName();
278: if (fileName.charAt(fileName.length() - 1) == '/') {
279: fileName = fileName.substring(0, fileName.length() - 1);
280: }
281:
282: if (fileName.charAt(0) == '/') {
283: fileName = fileName.substring(1);
284: }
285:
286: if (File.separatorChar != '/') {
287: fileName = fileName.replace('/', File.separatorChar);
288: }
289:
290: final File file = new File(dest, fileName);
291: if (entry.isDirectory()) {
292: // make sure the directory exists
293: file.mkdirs();
294: jin.closeEntry();
295: } else {
296: // make sure the directory exists
297: final File parent = file.getParentFile();
298: if (parent != null && !parent.exists()) {
299: parent.mkdirs();
300: }
301:
302: // dump the file
303:
304: final OutputStream out = new FileOutputStream(file);
305: int len = 0;
306: while ((len = jin.read(buffer, 0, buffer.length)) != -1) {
307: out.write(buffer, 0, len);
308: }
309:
310: out.flush();
311: out.close();
312: jin.closeEntry();
313: back.add(file);
314:
315: }
316:
317: entry = jin.getNextEntry();
318: }
319: jin.close();
320: return back;
321: }
322:
323: /**
324: * Extract the first entry in the jar file to an output stream.
325: *
326: * @param in -
327: * the jar archive as input stream
328: * @throws IOException -
329: * in an error case
330: */
331: public static InputStream unjar(InputStream in) throws IOException {
332:
333: JarInputStream jin = new JarInputStream(in);
334: final byte[] buffer = new byte[2048];
335: ZipEntry entry = jin.getNextEntry();
336: InputStream toReturn = null;
337: while (entry != null) {
338: if (!entry.isDirectory()) {
339: // make sure the directory exists
340:
341: // dump the file
342:
343: final ByteArrayOutputStream out = new ByteArrayOutputStream();
344: int len = 0;
345: while ((len = jin.read(buffer, 0, buffer.length)) != -1) {
346: out.write(buffer, 0, len);
347: }
348:
349: out.flush();
350: out.close();
351: jin.closeEntry();
352: toReturn = new ByteArrayInputStream(out.toByteArray());
353: break;
354: }
355:
356: entry = jin.getNextEntry();
357: }
358: jin.close();
359:
360: return toReturn;
361: }
362:
363: /**
364: * Scan for files in jar file.
365: *
366: * @param in -
367: * the jar archive as input stream
368: *
369: * @return - a list with all extracted files
370: * @throws IOException -
371: * in an error case
372: */
373: public static List<String> scanFileNamesInArchive(InputStream in)
374: throws IOException {
375:
376: final List<String> back = new ArrayList<String>();
377:
378: JarInputStream jin = new JarInputStream(in);
379: ZipEntry entry = jin.getNextEntry();
380: while (entry != null) {
381:
382: String fileName = entry.getName();
383: if (fileName.charAt(fileName.length() - 1) == '/') {
384: fileName = fileName.substring(0, fileName.length() - 1);
385: }
386:
387: if (fileName.charAt(0) == '/') {
388: fileName = fileName.substring(1);
389: }
390:
391: if (File.separatorChar != '/') {
392: fileName = fileName.replace('/', File.separatorChar);
393: }
394:
395: if (!entry.isDirectory()) {
396: back.add(fileName);
397: }
398:
399: entry = jin.getNextEntry();
400: }
401: jin.close();
402: return back;
403: }
404:
405: /**
406: * Returns all business (local, remote) interfaces of the class.
407: *
408: * @author Daniel Wiese
409: * @since 05.02.2006
410: * @param toAnalyse -
411: * the session bean /service to analyse
412: * @return - the interfaces
413: */
414: public static List<Class> getLocalRemoteInterfaces(Class toAnalyse) {
415: final List<Class> back = new ArrayList<Class>();
416: if (toAnalyse != null) {
417: Class[] interfaces = toAnalyse.getInterfaces();
418: if (interfaces != null) {
419: for (Class<Object> interf : interfaces) {
420: if (interf.getAnnotation(Local.class) != null
421: || interf.getAnnotation(Remote.class) != null) {
422: back.add(interf);
423: }
424: }
425: }
426: }
427:
428: return back;
429: }
430:
431: /**
432: * This method will do the transformation of primitive types if necessary.
433: *
434: * @param aktField -
435: * the field to inspect
436: * @return the declaring type (or primitive representant)
437: */
438: public static Class getNonPrimitiveType(Property aktField) {
439: return getNonPrimitiveType(aktField.getType());
440:
441: }
442:
443: /**
444: * This method will do the transformation of primitive types if necessary.
445: * It also transform all collection types (List, etc to Collection)
446: *
447: * @param aktField -
448: * the field to inspect
449: * @return the declaring type (or primitive representant)
450: */
451: public static Class getNonPrimitiveType(Class aktField) {
452: if (aktField == double.class) {
453: return Double.class;
454: } else if (aktField == float.class) {
455: return Float.class;
456: } else if (aktField == int.class) {
457: return Integer.class;
458: } else if (aktField == boolean.class) {
459: return Boolean.class;
460: } else if (aktField == char.class) {
461: return Character.class;
462: } else if (aktField == byte[].class) {
463: return Byte.class;
464: } else if (aktField == long.class) {
465: return Long.class;
466: } else if (aktField == short.class) {
467: return Short.class;
468: } else if (hasSuperclassOrInterface(aktField, Collection.class)) {
469: return Collection.class;
470: }
471:
472: return aktField;
473:
474: }
475:
476: /**
477: * Checks if the current class inherits form the specified class.
478: *
479: * @param toCheck
480: * the class to check
481: * @param superclassOrInterface
482: * the superclass
483: * @return true if a supeclass or interface
484: */
485: public static boolean hasSuperclassOrInterface(Class toCheck,
486: Class super classOrInterface) {
487: if (toCheck == null) {
488: return false;
489: } else if (super classOrInterface.equals(toCheck)) {
490: return true;
491: } else if (toCheck.equals(Object.class)) {
492: return false;
493: } else {
494: Class[] interfaces = toCheck.getInterfaces();
495: if (interfaces != null) {
496: for (Class current : interfaces) {
497: if (hasSuperclassOrInterface(current,
498: super classOrInterface)) {
499: return true;
500: }
501: }
502: }
503: return hasSuperclassOrInterface(toCheck.getSuperclass(),
504: super classOrInterface);
505: }
506: }
507:
508: /**
509: * Returns a generator type for a given generator.
510: *
511: * @author Daniel Wiese
512: * @since 17.04.2006
513: * @param actGenerator -
514: * given generator
515: * @return returns a given generator type
516: */
517: public static GeneratorType getGeneratorTypeAnnotation(
518: Generator actGenerator) {
519: Annotation[] classAnnotations = actGenerator.getClass()
520: .getAnnotations();
521: // iterate over the annotations
522: for (Annotation a : classAnnotations) {
523: if (a instanceof GeneratorType) {
524: final GeneratorType gT = (GeneratorType) a;
525: return gT;
526: }
527: }
528: return null;
529: }
530:
531: /**
532: * Returns the right collection type for the given property.
533: *
534: * @param forProperty -
535: * for which property
536: * @return - the right collection type
537: */
538: public static Collection getRightCollectionType(Property forProperty) {
539: if (forProperty.getType().equals(List.class)) {
540: return new ArrayList();
541: } else if (forProperty.getType().equals(Set.class)) {
542: return new HashSet();
543: } else if (forProperty.getType().equals(LinkedList.class)) {
544: return new LinkedList();
545: } else if (forProperty.getType().equals(Vector.class)) {
546: return new Vector();
547: } else if (forProperty.getType().equals(Set.class)) {
548: return new HashSet();
549: } else {
550: return new ArrayList();
551: }
552: }
553:
554: /**
555: * Returns all fields (including fields from all superclasses) of a class.
556: *
557: * @param forClass -
558: * for which class
559: * @return - all fields
560: */
561: public static Field[] getAllFields(Class forClass) {
562: final List<Field> fields = new ArrayList<Field>();
563: Class aktClass = forClass;
564: while (!aktClass.equals(Object.class)) {
565: Field[] tmp = aktClass.getDeclaredFields();
566: for (Field akt : tmp) {
567: fields.add(akt);
568: }
569: aktClass = aktClass.getSuperclass();
570: }
571: return fields.toArray(new Field[fields.size()]);
572: }
573:
574: /**
575: * Returns a parameterless method.
576: *
577: * @param name
578: * the name of the method
579: * @param inClass
580: * in which class
581: * @return the method if found or IllegalArgument exception
582: */
583: public static Method getParameterlessMethodByName(String name,
584: Class inClass) {
585: final Method[] all = getAllMethods(inClass);
586: for (Method current : all) {
587: if (current.getName().equals(name)) {
588: return current;
589: }
590: }
591:
592: throw new IllegalArgumentException("Method (" + name
593: + ") with name not fould in class ("
594: + inClass.getName() + ")");
595: }
596:
597: /**
598: * Returns all fields (including fields from all superclasses) of a class.
599: *
600: * @param forClass -
601: * for which class
602: * @return - all fields
603: */
604: public static Method[] getAllMethods(Class forClass) {
605: final List<Method> methods = new ArrayList<Method>();
606: Class aktClass = forClass;
607: while (!aktClass.equals(Object.class)) {
608: Method[] tmp = aktClass.getDeclaredMethods();
609: for (Method akt : tmp) {
610: methods.add(akt);
611: }
612: aktClass = aktClass.getSuperclass();
613: }
614: return methods.toArray(new Method[methods.size()]);
615: }
616:
617: /**
618: * Return a short class name. E.g. java.util.StringTokenizer will be
619: * StringTokenizer
620: *
621: * @param longClassName -
622: * the long fully qualified calss name
623: * @return - short class name
624: */
625: public static String getShortClassName(String longClassName) {
626: final StringTokenizer tk = new StringTokenizer(longClassName,
627: ".");
628: String last = longClassName;
629: while (tk.hasMoreTokens()) {
630: last = tk.nextToken();
631: }
632:
633: return last;
634: }
635:
636: /**
637: * Return a short class name. E.g. java.util.StringTokenizer will be
638: * StringTokenizer
639: *
640: * @param longClassName -
641: * the long fully qualified class name
642: * @return - short class name
643: */
644: public static String getPackageName(String longClassName) {
645: final StringTokenizer tk = new StringTokenizer(longClassName,
646: ".");
647: final StringBuilder sb = new StringBuilder();
648: String last = longClassName;
649: while (tk.hasMoreTokens()) {
650: last = tk.nextToken();
651: if (tk.hasMoreTokens()) {
652: sb.append(last);
653: sb.append(".");
654: }
655: }
656:
657: return sb.toString().substring(0, sb.toString().length() - 1);
658: }
659:
660: /**
661: * Returns the root package directory e.g com.ejb3unit.eg --> returns com.
662: *
663: * @param location -
664: * the location of the package
665: *
666: * @param longPackageName -
667: * the long fully qualified class name
668: * @return - root file name
669: */
670: public static File getRootPackageDir(File location,
671: String longPackageName) {
672: final StringTokenizer tk = new StringTokenizer(longPackageName,
673: ".");
674: File back = location;
675: while (tk.hasMoreTokens()) {
676: tk.nextToken();
677: back = back.getParentFile();
678: }
679: return back;
680: }
681:
682: /**
683: * Return a short class name. E.g. java.util.StringTokenizer will be
684: * StringTokenizer
685: *
686: * @param clazz -
687: * for class
688: * @return - short class name
689: */
690: public static String getShortClassName(Class clazz) {
691: return getShortClassName(clazz.getName());
692: }
693:
694: /**
695: * Returns a path to an temp directory.
696: *
697: * @author Daniel Wiese
698: * @since 29.06.2006
699: * @return - a path to a temp directory.
700: */
701: public static File getTempDirectory() {
702: File tempdir = new File(System.getProperty("java.io.tmpdir"));
703: return tempdir;
704: }
705:
706: }
|