Source Code Cross Referenced for Attributes.java in  » 6.0-JDK-Core » Collections-Jar-Zip-Logging-regex » java » util » jar » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » Collections Jar Zip Logging regex » java.util.jar 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        package java.util.jar;
027
028        import java.io.DataInputStream;
029        import java.io.DataOutputStream;
030        import java.io.IOException;
031        import java.util.HashMap;
032        import java.util.Map;
033        import java.util.Set;
034        import java.util.Collection;
035        import java.util.AbstractSet;
036        import java.util.Iterator;
037        import java.util.logging.Logger;
038        import java.util.Comparator;
039        import sun.misc.ASCIICaseInsensitiveComparator;
040
041        /**
042         * The Attributes class maps Manifest attribute names to associated string
043         * values. Valid attribute names are case-insensitive, are restricted to 
044         * the ASCII characters in the set [0-9a-zA-Z_-], and cannot exceed 70 
045         * characters in length. Attribute values can contain any characters and 
046         * will be UTF8-encoded when written to the output stream.  See the 
047         * <a href="../../../../technotes/guides/jar/jar.html">JAR File Specification</a> 
048         * for more information about valid attribute names and values.
049         *
050         * @author  David Connelly
051         * @version 1.60, 05/05/07
052         * @see	    Manifest
053         * @since   1.2
054         */
055        public class Attributes implements  Map<Object, Object>, Cloneable {
056            /**
057             * The attribute name-value mappings.
058             */
059            protected Map<Object, Object> map;
060
061            /**
062             * Constructs a new, empty Attributes object with default size.
063             */
064            public Attributes() {
065                this (11);
066            }
067
068            /**
069             * Constructs a new, empty Attributes object with the specified
070             * initial size.
071             *
072             * @param size the initial number of attributes
073             */
074            public Attributes(int size) {
075                map = new HashMap(size);
076            }
077
078            /**
079             * Constructs a new Attributes object with the same attribute name-value
080             * mappings as in the specified Attributes.
081             *
082             * @param attr the specified Attributes
083             */
084            public Attributes(Attributes attr) {
085                map = new HashMap(attr);
086            }
087
088            /**
089             * Returns the value of the specified attribute name, or null if the
090             * attribute name was not found.
091             *
092             * @param name the attribute name
093             * @return the value of the specified attribute name, or null if
094             *         not found.
095             */
096            public Object get(Object name) {
097                return map.get(name);
098            }
099
100            /**
101             * Returns the value of the specified attribute name, specified as
102             * a string, or null if the attribute was not found. The attribute
103             * name is case-insensitive.
104             * <p>
105             * This method is defined as:
106             * <pre>
107             *	    return (String)get(new Attributes.Name((String)name));
108             * </pre>
109             *
110             * @param name the attribute name as a string
111             * @return the String value of the specified attribute name, or null if
112             *         not found.
113             * @throws IllegalArgumentException if the attribute name is invalid
114             */
115            public String getValue(String name) {
116                return (String) get(new Attributes.Name((String) name));
117            }
118
119            /**
120             * Returns the value of the specified Attributes.Name, or null if the
121             * attribute was not found.
122             * <p>
123             * This method is defined as:
124             * <pre>
125             *     return (String)get(name);
126             * </pre>
127             *
128             * @param name the Attributes.Name object
129             * @return the String value of the specified Attribute.Name, or null if
130             *         not found.
131             */
132            public String getValue(Name name) {
133                return (String) get(name);
134            }
135
136            /**
137             * Associates the specified value with the specified attribute name
138             * (key) in this Map. If the Map previously contained a mapping for
139             * the attribute name, the old value is replaced.
140             *
141             * @param name the attribute name
142             * @param value the attribute value
143             * @return the previous value of the attribute, or null if none
144             * @exception ClassCastException if the name is not a Attributes.Name
145             *            or the value is not a String
146             */
147            public Object put(Object name, Object value) {
148                return map.put((Attributes.Name) name, (String) value);
149            }
150
151            /**
152             * Associates the specified value with the specified attribute name,
153             * specified as a String. The attributes name is case-insensitive.
154             * If the Map previously contained a mapping for the attribute name,
155             * the old value is replaced.
156             * <p>
157             * This method is defined as:
158             * <pre>
159             *	    return (String)put(new Attributes.Name(name), value);
160             * </pre>
161             *
162             * @param name the attribute name as a string
163             * @param value the attribute value
164             * @return the previous value of the attribute, or null if none
165             * @exception IllegalArgumentException if the attribute name is invalid
166             */
167            public String putValue(String name, String value) {
168                return (String) put(new Name(name), value);
169            }
170
171            /**
172             * Removes the attribute with the specified name (key) from this Map.
173             * Returns the previous attribute value, or null if none.
174             *
175             * @param name attribute name
176             * @return the previous value of the attribute, or null if none
177             */
178            public Object remove(Object name) {
179                return map.remove(name);
180            }
181
182            /**
183             * Returns true if this Map maps one or more attribute names (keys)
184             * to the specified value.
185             *
186             * @param value the attribute value
187             * @return true if this Map maps one or more attribute names to
188             *         the specified value
189             */
190            public boolean containsValue(Object value) {
191                return map.containsValue(value);
192            }
193
194            /**
195             * Returns true if this Map contains the specified attribute name (key).
196             *
197             * @param name the attribute name
198             * @return true if this Map contains the specified attribute name
199             */
200            public boolean containsKey(Object name) {
201                return map.containsKey(name);
202            }
203
204            /**
205             * Copies all of the attribute name-value mappings from the specified
206             * Attributes to this Map. Duplicate mappings will be replaced.
207             *
208             * @param attr the Attributes to be stored in this map
209             * @exception ClassCastException if attr is not an Attributes
210             */
211            public void putAll(Map<?, ?> attr) {
212                // ## javac bug?
213                if (!Attributes.class.isInstance(attr))
214                    throw new ClassCastException();
215                for (Map.Entry<?, ?> me : (attr).entrySet())
216                    put(me.getKey(), me.getValue());
217            }
218
219            /**
220             * Removes all attributes from this Map.
221             */
222            public void clear() {
223                map.clear();
224            }
225
226            /**
227             * Returns the number of attributes in this Map.
228             */
229            public int size() {
230                return map.size();
231            }
232
233            /**
234             * Returns true if this Map contains no attributes.
235             */
236            public boolean isEmpty() {
237                return map.isEmpty();
238            }
239
240            /**
241             * Returns a Set view of the attribute names (keys) contained in this Map.
242             */
243            public Set<Object> keySet() {
244                return map.keySet();
245            }
246
247            /**
248             * Returns a Collection view of the attribute values contained in this Map.
249             */
250            public Collection<Object> values() {
251                return map.values();
252            }
253
254            /**
255             * Returns a Collection view of the attribute name-value mappings
256             * contained in this Map.
257             */
258            public Set<Map.Entry<Object, Object>> entrySet() {
259                return map.entrySet();
260            }
261
262            /**
263             * Compares the specified Attributes object with this Map for equality.
264             * Returns true if the given object is also an instance of Attributes
265             * and the two Attributes objects represent the same mappings.
266             *
267             * @param o the Object to be compared
268             * @return true if the specified Object is equal to this Map
269             */
270            public boolean equals(Object o) {
271                return map.equals(o);
272            }
273
274            /**
275             * Returns the hash code value for this Map.
276             */
277            public int hashCode() {
278                return map.hashCode();
279            }
280
281            /**
282             * Returns a copy of the Attributes, implemented as follows:
283             * <pre>
284             *     public Object clone() { return new Attributes(this); }
285             * </pre>
286             * Since the attribute names and values are themselves immutable,
287             * the Attributes returned can be safely modified without affecting
288             * the original.
289             */
290            public Object clone() {
291                return new Attributes(this );
292            }
293
294            /*
295             * Writes the current attributes to the specified data output stream.
296             * XXX Need to handle UTF8 values and break up lines longer than 72 bytes
297             */
298            void write(DataOutputStream os) throws IOException {
299                Iterator it = entrySet().iterator();
300                while (it.hasNext()) {
301                    Map.Entry e = (Map.Entry) it.next();
302                    StringBuffer buffer = new StringBuffer(((Name) e.getKey())
303                            .toString());
304                    buffer.append(": ");
305
306                    String value = (String) e.getValue();
307                    if (value != null) {
308                        byte[] vb = value.getBytes("UTF8");
309                        value = new String(vb, 0, 0, vb.length);
310                    }
311                    buffer.append(value);
312
313                    buffer.append("\r\n");
314                    Manifest.make72Safe(buffer);
315                    os.writeBytes(buffer.toString());
316                }
317                os.writeBytes("\r\n");
318            }
319
320            /*
321             * Writes the current attributes to the specified data output stream,
322             * make sure to write out the MANIFEST_VERSION or SIGNATURE_VERSION
323             * attributes first.
324             *
325             * XXX Need to handle UTF8 values and break up lines longer than 72 bytes
326             */
327            void writeMain(DataOutputStream out) throws IOException {
328                // write out the *-Version header first, if it exists
329                String vername = Name.MANIFEST_VERSION.toString();
330                String version = getValue(vername);
331                if (version == null) {
332                    vername = Name.SIGNATURE_VERSION.toString();
333                    version = getValue(vername);
334                }
335
336                if (version != null) {
337                    out.writeBytes(vername + ": " + version + "\r\n");
338                }
339
340                // write out all attributes except for the version
341                // we wrote out earlier
342                Iterator it = entrySet().iterator();
343                while (it.hasNext()) {
344                    Map.Entry e = (Map.Entry) it.next();
345                    String name = ((Name) e.getKey()).toString();
346                    if ((version != null) && !(name.equalsIgnoreCase(vername))) {
347
348                        StringBuffer buffer = new StringBuffer(name);
349                        buffer.append(": ");
350
351                        String value = (String) e.getValue();
352                        if (value != null) {
353                            byte[] vb = value.getBytes("UTF8");
354                            value = new String(vb, 0, 0, vb.length);
355                        }
356                        buffer.append(value);
357
358                        buffer.append("\r\n");
359                        Manifest.make72Safe(buffer);
360                        out.writeBytes(buffer.toString());
361                    }
362                }
363                out.writeBytes("\r\n");
364            }
365
366            /*
367             * Reads attributes from the specified input stream.
368             * XXX Need to handle UTF8 values.
369             */
370            void read(Manifest.FastInputStream is, byte[] lbuf)
371                    throws IOException {
372                String name = null, value = null;
373                byte[] lastline = null;
374
375                int len;
376                while ((len = is.readLine(lbuf)) != -1) {
377                    boolean lineContinued = false;
378                    if (lbuf[--len] != '\n') {
379                        throw new IOException("line too long");
380                    }
381                    if (len > 0 && lbuf[len - 1] == '\r') {
382                        --len;
383                    }
384                    if (len == 0) {
385                        break;
386                    }
387                    int i = 0;
388                    if (lbuf[0] == ' ') {
389                        // continuation of previous line
390                        if (name == null) {
391                            throw new IOException("misplaced continuation line");
392                        }
393                        lineContinued = true;
394                        byte[] buf = new byte[lastline.length + len - 1];
395                        System.arraycopy(lastline, 0, buf, 0, lastline.length);
396                        System
397                                .arraycopy(lbuf, 1, buf, lastline.length,
398                                        len - 1);
399                        if (is.peek() == ' ') {
400                            lastline = buf;
401                            continue;
402                        }
403                        value = new String(buf, 0, buf.length, "UTF8");
404                        lastline = null;
405                    } else {
406                        while (lbuf[i++] != ':') {
407                            if (i >= len) {
408                                throw new IOException("invalid header field");
409                            }
410                        }
411                        if (lbuf[i++] != ' ') {
412                            throw new IOException("invalid header field");
413                        }
414                        name = new String(lbuf, 0, 0, i - 2);
415                        if (is.peek() == ' ') {
416                            lastline = new byte[len - i];
417                            System.arraycopy(lbuf, i, lastline, 0, len - i);
418                            continue;
419                        }
420                        value = new String(lbuf, i, len - i, "UTF8");
421                    }
422                    try {
423                        if ((putValue(name, value) != null) && (!lineContinued)) {
424                            Logger
425                                    .getLogger("java.util.jar")
426                                    .warning(
427                                            "Duplicate name in Manifest: "
428                                                    + name
429                                                    + ".\n"
430                                                    + "Ensure that the manifest does not "
431                                                    + "have duplicate entries, and\n"
432                                                    + "that blank lines separate "
433                                                    + "individual sections in both your\n"
434                                                    + "manifest and in the META-INF/MANIFEST.MF "
435                                                    + "entry in the jar file.");
436                        }
437                    } catch (IllegalArgumentException e) {
438                        throw new IOException("invalid header field name: "
439                                + name);
440                    }
441                }
442            }
443
444            /**
445             * The Attributes.Name class represents an attribute name stored in
446             * this Map. Valid attribute names are case-insensitive, are restricted 
447             * to the ASCII characters in the set [0-9a-zA-Z_-], and cannot exceed 
448             * 70 characters in length. Attribute values can contain any characters 
449             * and will be UTF8-encoded when written to the output stream.  See the 
450             * <a href="../../../../technotes/guides/jar/jar.html">JAR File Specification</a> 
451             * for more information about valid attribute names and values.
452             */
453            public static class Name {
454                private String name;
455                private int hashCode = -1;
456
457                /**
458                 * Constructs a new attribute name using the given string name.
459                 *
460                 * @param name the attribute string name
461                 * @exception IllegalArgumentException if the attribute name was
462                 *            invalid
463                 * @exception NullPointerException if the attribute name was null
464                 */
465                public Name(String name) {
466                    if (name == null) {
467                        throw new NullPointerException("name");
468                    }
469                    if (!isValid(name)) {
470                        throw new IllegalArgumentException(name);
471                    }
472                    this .name = name.intern();
473                }
474
475                private static boolean isValid(String name) {
476                    int len = name.length();
477                    if (len > 70 || len == 0) {
478                        return false;
479                    }
480                    for (int i = 0; i < len; i++) {
481                        if (!isValid(name.charAt(i))) {
482                            return false;
483                        }
484                    }
485                    return true;
486                }
487
488                private static boolean isValid(char c) {
489                    return isAlpha(c) || isDigit(c) || c == '_' || c == '-';
490                }
491
492                private static boolean isAlpha(char c) {
493                    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
494                }
495
496                private static boolean isDigit(char c) {
497                    return c >= '0' && c <= '9';
498                }
499
500                /**
501                 * Compares this attribute name to another for equality.
502                 * @param o the object to compare
503                 * @return true if this attribute name is equal to the
504                 *         specified attribute object
505                 */
506                public boolean equals(Object o) {
507                    if (o instanceof  Name) {
508                        Comparator c = ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER;
509                        return c.compare(name, ((Name) o).name) == 0;
510                    } else {
511                        return false;
512                    }
513                }
514
515                /**
516                 * Computes the hash value for this attribute name.
517                 */
518                public int hashCode() {
519                    if (hashCode == -1) {
520                        hashCode = ASCIICaseInsensitiveComparator
521                                .lowerCaseHashCode(name);
522                    }
523                    return hashCode;
524                }
525
526                /**
527                 * Returns the attribute name as a String.
528                 */
529                public String toString() {
530                    return name;
531                }
532
533                /**
534                 * <code>Name</code> object for <code>Manifest-Version</code> 
535                 * manifest attribute. This attribute indicates the version number 
536                 * of the manifest standard to which a JAR file's manifest conforms.
537                 * @see <a href="../../../../technotes/guides/jar/jar.html#JAR Manifest">
538                 *      Manifest and Signature Specification</a>
539                 */
540                public static final Name MANIFEST_VERSION = new Name(
541                        "Manifest-Version");
542
543                /**
544                 * <code>Name</code> object for <code>Signature-Version</code> 
545                 * manifest attribute used when signing JAR files.
546                 * @see <a href="../../../../technotes/guides/jar/jar.html#JAR Manifest">
547                 *      Manifest and Signature Specification</a>
548                 */
549                public static final Name SIGNATURE_VERSION = new Name(
550                        "Signature-Version");
551
552                /**
553                 * <code>Name</code> object for <code>Content-Type</code> 
554                 * manifest attribute.
555                 */
556                public static final Name CONTENT_TYPE = new Name("Content-Type");
557
558                /**
559                 * <code>Name</code> object for <code>Class-Path</code> 
560                 * manifest attribute. Bundled extensions can use this attribute 
561                 * to find other JAR files containing needed classes.
562                 * @see <a href="../../../../technotes/guides/extensions/spec.html#bundled">
563                 *      Extensions Specification</a>
564                 */
565                public static final Name CLASS_PATH = new Name("Class-Path");
566
567                /**
568                 * <code>Name</code> object for <code>Main-Class</code> manifest 
569                 * attribute used for launching applications packaged in JAR files. 
570                 * The <code>Main-Class</code> attribute is used in conjunction 
571                 * with the <code>-jar</code> command-line option of the 
572                 * <tt>java</tt> application launcher.
573                 */
574                public static final Name MAIN_CLASS = new Name("Main-Class");
575
576                /**
577                 * <code>Name</code> object for <code>Sealed</code> manifest attribute 
578                 * used for sealing.
579                 * @see <a href="../../../../technotes/guides/extensions/spec.html#sealing">
580                 *      Extension Sealing</a>
581                 */
582                public static final Name SEALED = new Name("Sealed");
583
584                /**
585                 * <code>Name</code> object for <code>Extension-List</code> manifest attribute 
586                 * used for declaring dependencies on installed extensions.
587                 * @see <a href="../../../../technotes/guides/extensions/spec.html#dependency">
588                 *      Installed extension dependency</a>
589                 */
590                public static final Name EXTENSION_LIST = new Name(
591                        "Extension-List");
592
593                /**
594                 * <code>Name</code> object for <code>Extension-Name</code> manifest attribute 
595                 * used for declaring dependencies on installed extensions.
596                 * @see <a href="../../../../technotes/guides/extensions/spec.html#dependency">
597                 *      Installed extension dependency</a>
598                 */
599                public static final Name EXTENSION_NAME = new Name(
600                        "Extension-Name");
601
602                /**
603                 * <code>Name</code> object for <code>Extension-Name</code> manifest attribute 
604                 * used for declaring dependencies on installed extensions.
605                 * @see <a href="../../../../technotes/guides/extensions/spec.html#dependency">
606                 *      Installed extension dependency</a>
607                 */
608                public static final Name EXTENSION_INSTALLATION = new Name(
609                        "Extension-Installation");
610
611                /**
612                 * <code>Name</code> object for <code>Implementation-Title</code> 
613                 * manifest attribute used for package versioning.
614                 * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
615                 *      Java Product Versioning Specification</a>
616                 */
617                public static final Name IMPLEMENTATION_TITLE = new Name(
618                        "Implementation-Title");
619
620                /**
621                 * <code>Name</code> object for <code>Implementation-Version</code> 
622                 * manifest attribute used for package versioning.
623                 * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
624                 *      Java Product Versioning Specification</a>
625                 */
626                public static final Name IMPLEMENTATION_VERSION = new Name(
627                        "Implementation-Version");
628
629                /**
630                 * <code>Name</code> object for <code>Implementation-Vendor</code> 
631                 * manifest attribute used for package versioning.
632                 * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
633                 *      Java Product Versioning Specification</a>
634                 */
635                public static final Name IMPLEMENTATION_VENDOR = new Name(
636                        "Implementation-Vendor");
637
638                /**
639                 * <code>Name</code> object for <code>Implementation-Vendor-Id</code> 
640                 * manifest attribute used for package versioning.
641                 * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
642                 *      Java Product Versioning Specification</a>
643                 */
644                public static final Name IMPLEMENTATION_VENDOR_ID = new Name(
645                        "Implementation-Vendor-Id");
646
647                /**
648                 * <code>Name</code> object for <code>Implementation-Vendor-URL</code> 
649                 * manifest attribute used for package versioning.
650                 * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
651                 *      Java Product Versioning Specification</a>
652                 */
653                public static final Name IMPLEMENTATION_URL = new Name(
654                        "Implementation-URL");
655
656                /**
657                 * <code>Name</code> object for <code>Specification-Title</code> 
658                 * manifest attribute used for package versioning.
659                 * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
660                 *      Java Product Versioning Specification</a>
661                 */
662                public static final Name SPECIFICATION_TITLE = new Name(
663                        "Specification-Title");
664
665                /**
666                 * <code>Name</code> object for <code>Specification-Version</code> 
667                 * manifest attribute used for package versioning.
668                 * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
669                 *      Java Product Versioning Specification</a>
670                 */
671                public static final Name SPECIFICATION_VERSION = new Name(
672                        "Specification-Version");
673
674                /**
675                 * <code>Name</code> object for <code>Specification-Vendor</code> 
676                 * manifest attribute used for package versioning.
677                 * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
678                 *      Java Product Versioning Specification</a>
679                 */
680                public static final Name SPECIFICATION_VENDOR = new Name(
681                        "Specification-Vendor");
682            }
683        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.