Source Code Cross Referenced for XMLProperties.java in  » Net » openfire » org » jivesoftware » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

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 geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Net » openfire » org.jivesoftware.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * $RCSfile$
003:         * $Revision: 9782 $
004:         * $Date: 2008-01-19 09:43:30 -0800 (Sat, 19 Jan 2008) $
005:         *
006:         * Copyright (C) 2004 Jive Software. All rights reserved.
007:         *
008:         * This software is published under the terms of the GNU Public License (GPL),
009:         * a copy of which is included in this distribution.
010:         */package org.jivesoftware.util;
011:
012:        import org.dom4j.CDATA;
013:        import org.dom4j.Document;
014:        import org.dom4j.Element;
015:        import org.dom4j.Node;
016:        import org.dom4j.io.OutputFormat;
017:        import org.dom4j.io.SAXReader;
018:        import org.apache.commons.lang.StringEscapeUtils;
019:
020:        import java.io.*;
021:        import java.util.*;
022:
023:        /**
024:         * Provides the the ability to use simple XML property files. Each property is
025:         * in the form X.Y.Z, which would map to an XML snippet of:
026:         * <pre>
027:         * &lt;X&gt;
028:         *     &lt;Y&gt;
029:         *         &lt;Z&gt;someValue&lt;/Z&gt;
030:         *     &lt;/Y&gt;
031:         * &lt;/X&gt;
032:         * </pre>
033:         * <p/>
034:         * The XML file is passed in to the constructor and must be readable and
035:         * writtable. Setting property values will automatically persist those value
036:         * to disk. The file encoding used is UTF-8.
037:         *
038:         * @author Derek DeMoro
039:         * @author Iain Shigeoka
040:         */
041:        public class XMLProperties {
042:
043:            private File file;
044:            private Document document;
045:
046:            /**
047:             * Parsing the XML file every time we need a property is slow. Therefore,
048:             * we use a Map to cache property values that are accessed more than once.
049:             */
050:            private Map<String, String> propertyCache = new HashMap<String, String>();
051:
052:            /**
053:             * Creates a new XMLPropertiesTest object.
054:             *
055:             * @param fileName the full path the file that properties should be read from
056:             *                 and written to.
057:             * @throws IOException if an error occurs loading the properties.
058:             */
059:            public XMLProperties(String fileName) throws IOException {
060:                this (new File(fileName));
061:            }
062:
063:            /**
064:             * Loads XML properties from a stream.
065:             *
066:             * @param in the input stream of XML.
067:             * @throws IOException if an exception occurs when reading the stream.
068:             */
069:            public XMLProperties(InputStream in) throws IOException {
070:                Reader reader = new BufferedReader(new InputStreamReader(in));
071:                buildDoc(reader);
072:            }
073:
074:            /**
075:             * Creates a new XMLPropertiesTest object.
076:             *
077:             * @param file the file that properties should be read from and written to.
078:             * @throws IOException if an error occurs loading the properties.
079:             */
080:            public XMLProperties(File file) throws IOException {
081:                this .file = file;
082:                if (!file.exists()) {
083:                    // Attempt to recover from this error case by seeing if the
084:                    // tmp file exists. It's possible that the rename of the
085:                    // tmp file failed the last time Jive was running,
086:                    // but that it exists now.
087:                    File tempFile;
088:                    tempFile = new File(file.getParentFile(), file.getName()
089:                            + ".tmp");
090:                    if (tempFile.exists()) {
091:                        Log
092:                                .error("WARNING: "
093:                                        + file.getName()
094:                                        + " was not found, but temp file from "
095:                                        + "previous write operation was. Attempting automatic recovery."
096:                                        + " Please check file for data consistency.");
097:                        tempFile.renameTo(file);
098:                    }
099:                    // There isn't a possible way to recover from the file not
100:                    // being there, so throw an error.
101:                    else {
102:                        throw new FileNotFoundException(
103:                                "XML properties file does not exist: "
104:                                        + file.getName());
105:                    }
106:                }
107:                // Check read and write privs.
108:                if (!file.canRead()) {
109:                    throw new IOException(
110:                            "XML properties file must be readable: "
111:                                    + file.getName());
112:                }
113:                if (!file.canWrite()) {
114:                    throw new IOException(
115:                            "XML properties file must be writable: "
116:                                    + file.getName());
117:                }
118:
119:                FileReader reader = new FileReader(file);
120:                buildDoc(reader);
121:            }
122:
123:            /**
124:             * Returns the value of the specified property.
125:             *
126:             * @param name the name of the property to get.
127:             * @return the value of the specified property.
128:             */
129:            public synchronized String getProperty(String name) {
130:                String value = propertyCache.get(name);
131:                if (value != null) {
132:                    return value;
133:                }
134:
135:                String[] propName = parsePropertyName(name);
136:                // Search for this property by traversing down the XML heirarchy.
137:                Element element = document.getRootElement();
138:                for (String aPropName : propName) {
139:                    element = element.element(aPropName);
140:                    if (element == null) {
141:                        // This node doesn't match this part of the property name which
142:                        // indicates this property doesn't exist so return null.
143:                        return null;
144:                    }
145:                }
146:                // At this point, we found a matching property, so return its value.
147:                // Empty strings are returned as null.
148:                value = element.getTextTrim();
149:                if ("".equals(value)) {
150:                    return null;
151:                } else {
152:                    // Add to cache so that getting property next time is fast.
153:                    propertyCache.put(name, value);
154:                    return value;
155:                }
156:            }
157:
158:            /**
159:             * Return all values who's path matches the given property
160:             * name as a String array, or an empty array if the if there
161:             * are no children. This allows you to retrieve several values
162:             * with the same property name. For example, consider the
163:             * XML file entry:
164:             * <pre>
165:             * &lt;foo&gt;
166:             *     &lt;bar&gt;
167:             *         &lt;prop&gt;some value&lt;/prop&gt;
168:             *         &lt;prop&gt;other value&lt;/prop&gt;
169:             *         &lt;prop&gt;last value&lt;/prop&gt;
170:             *     &lt;/bar&gt;
171:             * &lt;/foo&gt;
172:             * </pre>
173:             * If you call getProperties("foo.bar.prop") will return a string array containing
174:             * {"some value", "other value", "last value"}.
175:             *
176:             * @param name the name of the property to retrieve
177:             * @return all child property values for the given node name.
178:             */
179:            public String[] getProperties(String name) {
180:                String[] propName = parsePropertyName(name);
181:                // Search for this property by traversing down the XML heirarchy,
182:                // stopping one short.
183:                Element element = document.getRootElement();
184:                for (int i = 0; i < propName.length - 1; i++) {
185:                    element = element.element(propName[i]);
186:                    if (element == null) {
187:                        // This node doesn't match this part of the property name which
188:                        // indicates this property doesn't exist so return empty array.
189:                        return new String[] {};
190:                    }
191:                }
192:                // We found matching property, return names of children.
193:                Iterator iter = element
194:                        .elementIterator(propName[propName.length - 1]);
195:                List<String> props = new ArrayList<String>();
196:                String value;
197:                while (iter.hasNext()) {
198:                    // Empty strings are skipped.
199:                    value = ((Element) iter.next()).getTextTrim();
200:                    if (!"".equals(value)) {
201:                        props.add(value);
202:                    }
203:                }
204:                String[] childrenNames = new String[props.size()];
205:                return props.toArray(childrenNames);
206:            }
207:
208:            /**
209:             * Return all values who's path matches the given property
210:             * name as a String array, or an empty array if the if there
211:             * are no children. This allows you to retrieve several values
212:             * with the same property name. For example, consider the
213:             * XML file entry:
214:             * <pre>
215:             * &lt;foo&gt;
216:             *     &lt;bar&gt;
217:             *         &lt;prop&gt;some value&lt;/prop&gt;
218:             *         &lt;prop&gt;other value&lt;/prop&gt;
219:             *         &lt;prop&gt;last value&lt;/prop&gt;
220:             *     &lt;/bar&gt;
221:             * &lt;/foo&gt;
222:             * </pre>
223:             * If you call getProperties("foo.bar.prop") will return a string array containing
224:             * {"some value", "other value", "last value"}.
225:             *
226:             * @param name the name of the property to retrieve
227:             * @return all child property values for the given node name.
228:             */
229:            public Iterator getChildProperties(String name) {
230:                String[] propName = parsePropertyName(name);
231:                // Search for this property by traversing down the XML heirarchy,
232:                // stopping one short.
233:                Element element = document.getRootElement();
234:                for (int i = 0; i < propName.length - 1; i++) {
235:                    element = element.element(propName[i]);
236:                    if (element == null) {
237:                        // This node doesn't match this part of the property name which
238:                        // indicates this property doesn't exist so return empty array.
239:                        return Collections.EMPTY_LIST.iterator();
240:                    }
241:                }
242:                // We found matching property, return values of the children.
243:                Iterator iter = element
244:                        .elementIterator(propName[propName.length - 1]);
245:                ArrayList<String> props = new ArrayList<String>();
246:                while (iter.hasNext()) {
247:                    props.add(((Element) iter.next()).getText());
248:                }
249:                return props.iterator();
250:            }
251:
252:            /**
253:             * Returns the value of the attribute of the given property name or <tt>null</tt>
254:             * if it doesn't exist. Note, this
255:             *
256:             * @param name the property name to lookup - ie, "foo.bar"
257:             * @param attribute the name of the attribute, ie "id"
258:             * @return the value of the attribute of the given property or <tt>null</tt> if
259:             *      it doesn't exist.
260:             */
261:            public String getAttribute(String name, String attribute) {
262:                if (name == null || attribute == null) {
263:                    return null;
264:                }
265:                String[] propName = parsePropertyName(name);
266:                // Search for this property by traversing down the XML heirarchy.
267:                Element element = document.getRootElement();
268:                for (String child : propName) {
269:                    element = element.element(child);
270:                    if (element == null) {
271:                        // This node doesn't match this part of the property name which
272:                        // indicates this property doesn't exist so return empty array.
273:                        break;
274:                    }
275:                }
276:                if (element != null) {
277:                    // Get its attribute values
278:                    return element.attributeValue(attribute);
279:                }
280:                return null;
281:            }
282:
283:            /**
284:             * Sets a property to an array of values. Multiple values matching the same property
285:             * is mapped to an XML file as multiple elements containing each value.
286:             * For example, using the name "foo.bar.prop", and the value string array containing
287:             * {"some value", "other value", "last value"} would produce the following XML:
288:             * <pre>
289:             * &lt;foo&gt;
290:             *     &lt;bar&gt;
291:             *         &lt;prop&gt;some value&lt;/prop&gt;
292:             *         &lt;prop&gt;other value&lt;/prop&gt;
293:             *         &lt;prop&gt;last value&lt;/prop&gt;
294:             *     &lt;/bar&gt;
295:             * &lt;/foo&gt;
296:             * </pre>
297:             *
298:             * @param name the name of the property.
299:             * @param values the values for the property (can be empty but not null).
300:             */
301:            public void setProperties(String name, List<String> values) {
302:                String[] propName = parsePropertyName(name);
303:                // Search for this property by traversing down the XML heirarchy,
304:                // stopping one short.
305:                Element element = document.getRootElement();
306:                for (int i = 0; i < propName.length - 1; i++) {
307:                    // If we don't find this part of the property in the XML heirarchy
308:                    // we add it as a new node
309:                    if (element.element(propName[i]) == null) {
310:                        element.addElement(propName[i]);
311:                    }
312:                    element = element.element(propName[i]);
313:                }
314:                String childName = propName[propName.length - 1];
315:                // We found matching property, clear all children.
316:                List<Element> toRemove = new ArrayList<Element>();
317:                Iterator iter = element.elementIterator(childName);
318:                while (iter.hasNext()) {
319:                    toRemove.add((Element) iter.next());
320:                }
321:                for (iter = toRemove.iterator(); iter.hasNext();) {
322:                    element.remove((Element) iter.next());
323:                }
324:                // Add the new children.
325:                for (String value : values) {
326:                    Element childElement = element.addElement(childName);
327:                    if (value.startsWith("<![CDATA[")) {
328:                        Iterator it = childElement.nodeIterator();
329:                        while (it.hasNext()) {
330:                            Node node = (Node) it.next();
331:                            if (node instanceof  CDATA) {
332:                                childElement.remove(node);
333:                                break;
334:                            }
335:                        }
336:                        childElement.addCDATA(value.substring(9,
337:                                value.length() - 3));
338:                    } else {
339:                        childElement
340:                                .setText(StringEscapeUtils.escapeXml(value));
341:                    }
342:                }
343:                saveProperties();
344:
345:                // Generate event.
346:                Map<String, Object> params = new HashMap<String, Object>();
347:                params.put("value", values);
348:                PropertyEventDispatcher.dispatchEvent(name,
349:                        PropertyEventDispatcher.EventType.xml_property_set,
350:                        params);
351:            }
352:
353:            /**
354:             * Return all children property names of a parent property as a String array,
355:             * or an empty array if the if there are no children. For example, given
356:             * the properties <tt>X.Y.A</tt>, <tt>X.Y.B</tt>, and <tt>X.Y.C</tt>, then
357:             * the child properties of <tt>X.Y</tt> are <tt>A</tt>, <tt>B</tt>, and
358:             * <tt>C</tt>.
359:             *
360:             * @param parent the name of the parent property.
361:             * @return all child property values for the given parent.
362:             */
363:            public String[] getChildrenProperties(String parent) {
364:                String[] propName = parsePropertyName(parent);
365:                // Search for this property by traversing down the XML heirarchy.
366:                Element element = document.getRootElement();
367:                for (String aPropName : propName) {
368:                    element = element.element(aPropName);
369:                    if (element == null) {
370:                        // This node doesn't match this part of the property name which
371:                        // indicates this property doesn't exist so return empty array.
372:                        return new String[] {};
373:                    }
374:                }
375:                // We found matching property, return names of children.
376:                List children = element.elements();
377:                int childCount = children.size();
378:                String[] childrenNames = new String[childCount];
379:                for (int i = 0; i < childCount; i++) {
380:                    childrenNames[i] = ((Element) children.get(i)).getName();
381:                }
382:                return childrenNames;
383:            }
384:
385:            /**
386:             * Sets the value of the specified property. If the property doesn't
387:             * currently exist, it will be automatically created.
388:             *
389:             * @param name  the name of the property to set.
390:             * @param value the new value for the property.
391:             */
392:            public synchronized void setProperty(String name, String value) {
393:                if (!StringEscapeUtils.escapeXml(name).equals(name)) {
394:                    throw new IllegalArgumentException(
395:                            "Property name cannot contain XML entities.");
396:                }
397:                if (name == null) {
398:                    return;
399:                }
400:                if (value == null) {
401:                    value = "";
402:                }
403:
404:                // Set cache correctly with prop name and value.
405:                propertyCache.put(name, value);
406:
407:                String[] propName = parsePropertyName(name);
408:                // Search for this property by traversing down the XML heirarchy.
409:                Element element = document.getRootElement();
410:                for (String aPropName : propName) {
411:                    // If we don't find this part of the property in the XML heirarchy
412:                    // we add it as a new node
413:                    if (element.element(aPropName) == null) {
414:                        element.addElement(aPropName);
415:                    }
416:                    element = element.element(aPropName);
417:                }
418:                // Set the value of the property in this node.
419:                if (value.startsWith("<![CDATA[")) {
420:                    Iterator it = element.nodeIterator();
421:                    while (it.hasNext()) {
422:                        Node node = (Node) it.next();
423:                        if (node instanceof  CDATA) {
424:                            element.remove(node);
425:                            break;
426:                        }
427:                    }
428:                    element.addCDATA(value.substring(9, value.length() - 3));
429:                } else {
430:                    element.setText(value);
431:                }
432:                // Write the XML properties to disk
433:                saveProperties();
434:
435:                // Generate event.
436:                Map<String, Object> params = new HashMap<String, Object>();
437:                params.put("value", value);
438:                PropertyEventDispatcher.dispatchEvent(name,
439:                        PropertyEventDispatcher.EventType.xml_property_set,
440:                        params);
441:            }
442:
443:            /**
444:             * Deletes the specified property.
445:             *
446:             * @param name the property to delete.
447:             */
448:            public synchronized void deleteProperty(String name) {
449:                // Remove property from cache.
450:                propertyCache.remove(name);
451:
452:                String[] propName = parsePropertyName(name);
453:                // Search for this property by traversing down the XML heirarchy.
454:                Element element = document.getRootElement();
455:                for (int i = 0; i < propName.length - 1; i++) {
456:                    element = element.element(propName[i]);
457:                    // Can't find the property so return.
458:                    if (element == null) {
459:                        return;
460:                    }
461:                }
462:                // Found the correct element to remove, so remove it...
463:                element.remove(element.element(propName[propName.length - 1]));
464:                // .. then write to disk.
465:                saveProperties();
466:
467:                // Generate event.
468:                Map<String, Object> params = Collections.emptyMap();
469:                PropertyEventDispatcher.dispatchEvent(name,
470:                        PropertyEventDispatcher.EventType.xml_property_deleted,
471:                        params);
472:            }
473:
474:            /**
475:             * Builds the document XML model up based the given reader of XML data.
476:             * @param in the input stream used to build the xml document
477:             * @throws java.io.IOException thrown when an error occurs reading the input stream.
478:             */
479:            private void buildDoc(Reader in) throws IOException {
480:                try {
481:                    SAXReader xmlReader = new SAXReader();
482:                    xmlReader.setEncoding("UTF-8");
483:                    document = xmlReader.read(in);
484:                } catch (Exception e) {
485:                    Log.error("Error reading XML properties", e);
486:                    throw new IOException(e.getMessage());
487:                } finally {
488:                    if (in != null) {
489:                        in.close();
490:                    }
491:                }
492:            }
493:
494:            /**
495:             * Saves the properties to disk as an XML document. A temporary file is
496:             * used during the writing process for maximum safety.
497:             */
498:            private synchronized void saveProperties() {
499:                boolean error = false;
500:                // Write data out to a temporary file first.
501:                File tempFile = null;
502:                Writer writer = null;
503:                try {
504:                    tempFile = new File(file.getParentFile(), file.getName()
505:                            + ".tmp");
506:                    writer = new BufferedWriter(new OutputStreamWriter(
507:                            new FileOutputStream(tempFile), "UTF-8"));
508:                    OutputFormat prettyPrinter = OutputFormat
509:                            .createPrettyPrint();
510:                    XMLWriter xmlWriter = new XMLWriter(writer, prettyPrinter);
511:                    xmlWriter.write(document);
512:                } catch (Exception e) {
513:                    Log.error(e);
514:                    // There were errors so abort replacing the old property file.
515:                    error = true;
516:                } finally {
517:                    if (writer != null) {
518:                        try {
519:                            writer.close();
520:                        } catch (IOException e1) {
521:                            Log.error(e1);
522:                            error = true;
523:                        }
524:                    }
525:                }
526:
527:                // No errors occured, so delete the main file.
528:                if (!error) {
529:                    // Delete the old file so we can replace it.
530:                    if (!file.delete()) {
531:                        Log.error("Error deleting property file: "
532:                                + file.getAbsolutePath());
533:                        return;
534:                    }
535:                    // Copy new contents to the file.
536:                    try {
537:                        copy(tempFile, file);
538:                    } catch (Exception e) {
539:                        Log.error(e);
540:                        // There were errors so abort replacing the old property file.
541:                        error = true;
542:                    }
543:                    // If no errors, delete the temp file.
544:                    if (!error) {
545:                        tempFile.delete();
546:                    }
547:                }
548:            }
549:
550:            /**
551:             * Returns an array representation of the given Jive property. Jive
552:             * properties are always in the format "prop.name.is.this" which would be
553:             * represented as an array of four Strings.
554:             *
555:             * @param name the name of the Jive property.
556:             * @return an array representation of the given Jive property.
557:             */
558:            private String[] parsePropertyName(String name) {
559:                List<String> propName = new ArrayList<String>(5);
560:                // Use a StringTokenizer to tokenize the property name.
561:                StringTokenizer tokenizer = new StringTokenizer(name, ".");
562:                while (tokenizer.hasMoreTokens()) {
563:                    propName.add(tokenizer.nextToken());
564:                }
565:                return propName.toArray(new String[propName.size()]);
566:            }
567:
568:            public void setProperties(Map<String, String> propertyMap) {
569:                for (String propertyName : propertyMap.keySet()) {
570:                    String propertyValue = propertyMap.get(propertyName);
571:                    setProperty(propertyName, propertyValue);
572:                }
573:            }
574:
575:            /**
576:             * Copies the inFile to the outFile.
577:             *
578:             * @param inFile  The file to copy from
579:             * @param outFile The file to copy to
580:             * @throws IOException If there was a problem making the copy
581:             */
582:            private static void copy(File inFile, File outFile)
583:                    throws IOException {
584:                FileInputStream fin = null;
585:                FileOutputStream fout = null;
586:                try {
587:                    fin = new FileInputStream(inFile);
588:                    fout = new FileOutputStream(outFile);
589:                    copy(fin, fout);
590:                } finally {
591:                    try {
592:                        if (fin != null)
593:                            fin.close();
594:                    } catch (IOException e) {
595:                        // do nothing
596:                    }
597:                    try {
598:                        if (fout != null)
599:                            fout.close();
600:                    } catch (IOException e) {
601:                        // do nothing
602:                    }
603:                }
604:            }
605:
606:            /**
607:             * Copies data from an input stream to an output stream
608:             *
609:             * @param in the stream to copy data from.
610:             * @param out the stream to copy data to.
611:             * @throws IOException if there's trouble during the copy.
612:             */
613:            private static void copy(InputStream in, OutputStream out)
614:                    throws IOException {
615:                // Do not allow other threads to intrude on streams during copy.
616:                synchronized (in) {
617:                    synchronized (out) {
618:                        byte[] buffer = new byte[256];
619:                        while (true) {
620:                            int bytesRead = in.read(buffer);
621:                            if (bytesRead == -1)
622:                                break;
623:                            out.write(buffer, 0, bytesRead);
624:                        }
625:                    }
626:                }
627:            }
628:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.