Source Code Cross Referenced for MatchingObject.java in  » IDE-Netbeans » utilities » org » netbeans » modules » search » 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 » IDE Netbeans » utilities » org.netbeans.modules.search 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003:         *
004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005:         *
006:         * The contents of this file are subject to the terms of either the GNU
007:         * General Public License Version 2 only ("GPL") or the Common
008:         * Development and Distribution License("CDDL") (collectively, the
009:         * "License"). You may not use this file except in compliance with the
010:         * License. You can obtain a copy of the License at
011:         * http://www.netbeans.org/cddl-gplv2.html
012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013:         * specific language governing permissions and limitations under the
014:         * License.  When distributing the software, include this License Header
015:         * Notice in each file and include the License file at
016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
017:         * particular file as subject to the "Classpath" exception as provided
018:         * by Sun in the GPL Version 2 section of the License file that
019:         * accompanied this code. If applicable, add the following below the
020:         * License Header, with the fields enclosed by brackets [] replaced by
021:         * your own identifying information:
022:         * "Portions Copyrighted [year] [name of copyright owner]"
023:         *
024:         * Contributor(s):
025:         *
026:         * The Original Software is NetBeans. The Initial Developer of the Original
027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028:         * Microsystems, Inc. All Rights Reserved.
029:         *
030:         * If you wish your version of this file to be governed by only the CDDL
031:         * or only the GPL Version 2, indicate your decision by adding
032:         * "[Contributor] elects to include this software in this distribution
033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
034:         * single choice of license, a recipient has the option to distribute
035:         * your version of this file under either the CDDL, the GPL Version 2 or
036:         * to extend the choice of license to its licensees as provided above.
037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
038:         * Version 2 license, then the option applies only if the new code is
039:         * made subject to such option by the copyright holder.
040:         */
041:
042:        package org.netbeans.modules.search;
043:
044:        import java.awt.EventQueue;
045:        import java.beans.PropertyChangeEvent;
046:        import java.beans.PropertyChangeListener;
047:        import java.io.File;
048:        import java.io.FileInputStream;
049:        import java.io.IOException;
050:        import java.io.OutputStreamWriter;
051:        import java.io.Writer;
052:        import java.nio.ByteBuffer;
053:        import java.nio.CharBuffer;
054:        import java.nio.channels.ClosedByInterruptException;
055:        import java.nio.channels.FileChannel;
056:        import java.nio.charset.CharacterCodingException;
057:        import java.nio.charset.Charset;
058:        import java.nio.charset.CharsetDecoder;
059:        import java.nio.charset.CoderResult;
060:        import java.nio.charset.CodingErrorAction;
061:        import java.util.Arrays;
062:        import java.util.List;
063:        import java.util.logging.Level;
064:        import java.util.logging.Logger;
065:        import java.util.regex.Matcher;
066:        import java.util.regex.Pattern;
067:        import org.openide.filesystems.FileLock;
068:        import org.openide.filesystems.FileObject;
069:        import org.openide.filesystems.FileUtil;
070:        import org.openide.loaders.DataObject;
071:        import org.openide.util.NbBundle;
072:        import static java.util.logging.Level.FINER;
073:        import static java.util.logging.Level.FINEST;
074:        import static java.util.logging.Level.SEVERE;
075:
076:        /**
077:         * Data structure holding a reference to the found object and information
078:         * whether occurences in the found object should be replaced or not.
079:         * 
080:         * @author  Marian Petras
081:         * @author  Tim Boudreau
082:         */
083:        final class MatchingObject implements  PropertyChangeListener {
084:
085:            /** */
086:            private final Logger LOG = Logger.getLogger(getClass().getName());
087:            /** */
088:            private final ResultModel resultModel;
089:            /** */
090:            private final File file;
091:            /** */
092:            private final long timestamp;
093:
094:            /**
095:             * matching object as returned by the {@code SearchGroup}
096:             * (usually a {@code DataObject})
097:             */
098:            final Object object;
099:
100:            /**
101:             * holds information on whether the {@code object} is selected
102:             * to be replaced or not.
103:             * Unless {@link #selectedMatches} is non-{@code null}, this field's
104:             * value also applies to the object's subnodes (if any).
105:             * 
106:             * @see  #selectedMatches
107:             */
108:            private boolean selected = true;
109:            /**
110:             * holds information on whether the node representing this object
111:             * is expanded or collapsed
112:             * 
113:             * @see  #markExpanded(boolean)
114:             */
115:            private boolean expanded = false;
116:            /**
117:             * holds information about which matches should be replaced and which
118:             * should not be replaced.
119:             * Value {@code null} means that either all or none matches are selected,
120:             * depending on the value of field {@link #selected}.
121:             * 
122:             * @see  #selected
123:             */
124:            private boolean[] selectedMatches;
125:            /**
126:             * flag that indicates that the tree was not notified of this
127:             * {@code MatchingObject}'s children's selection change and that
128:             * it must be notified before the children nodes are made visible
129:             * 
130:             * @see  #markChildrenSelectionDirty()
131:             */
132:            private boolean childrenSelectionDirty;
133:            /** */
134:            private boolean valid = true;
135:            /** */
136:            private StringBuilder text;
137:
138:            /**
139:             * {@code true} if the file's line terminator is other than {@code "\\n"}
140:             */
141:            boolean wasCrLf = false;
142:
143:            /**
144:             * Creates a new {@code MatchingObject} with a reference to the found
145:             * object (returned by {@code SearchGroup}).
146:             * 
147:             * @param  object  found object returned by the {@code SearchGroup}
148:             *                 (usually a {@code DataObject}) - must not be {@code null}
149:             * @exception  java.lang.IllegalArgumentException
150:             *             if the passed {@code object} is {@code null}
151:             */
152:            MatchingObject(ResultModel resultModel, Object object) {
153:                if (resultModel == null) {
154:                    throw new IllegalArgumentException("resultModel = null"); //NOI18N
155:                }
156:                if (object == null) {
157:                    throw new IllegalArgumentException("object = null"); //NOI18N
158:                }
159:
160:                this .resultModel = resultModel;
161:                this .object = object;
162:
163:                FileObject fileObject = getFileObject();
164:                file = FileUtil.toFile(fileObject);
165:                timestamp = (file != null) ? file.lastModified() : 0L;
166:                valid = (timestamp != 0L);
167:
168:                setUpDataObjValidityChecking();
169:            }
170:
171:            /**
172:             */
173:            private void setUpDataObjValidityChecking() {
174:                final DataObject dataObj = (DataObject) object;
175:                if (dataObj.isValid()) {
176:                    dataObj.addPropertyChangeListener(this );
177:                }
178:            }
179:
180:            /**
181:             */
182:            void cleanup() {
183:                final DataObject dataObj = (DataObject) object;
184:                dataObj.removePropertyChangeListener(this );
185:            }
186:
187:            public void propertyChange(PropertyChangeEvent e) {
188:                if (DataObject.PROP_VALID.equals(e.getPropertyName())
189:                        && Boolean.FALSE.equals(e.getNewValue())) {
190:                    assert e.getSource() == (DataObject) object;
191:
192:                    final DataObject dataObj = (DataObject) object;
193:                    dataObj.removePropertyChangeListener(this );
194:
195:                    resultModel.objectBecameInvalid(this );
196:                }
197:            }
198:
199:            /**
200:             * Is the {@code DataObject} encapsulated by this {@code MatchingObject}
201:             * valid?
202:             * 
203:             * @return  {@code true} if the {@code DataObject} is valid, false otherwise
204:             * @see  DataObject#isValid
205:             */
206:            boolean isObjectValid() {
207:                return ((DataObject) object).isValid();
208:            }
209:
210:            private FileObject getFileObject() {
211:                return ((DataObject) object).getPrimaryFile();
212:            }
213:
214:            /**
215:             */
216:            void setSelected(boolean selected) {
217:                if (selected == this .selected) {
218:                    return;
219:                }
220:
221:                this .selected = selected;
222:                selectedMatches = null;
223:            }
224:
225:            /**
226:             */
227:            boolean isSelected() {
228:                return selected;
229:            }
230:
231:            /**
232:             */
233:            boolean isUniformSelection() {
234:                return selectedMatches == null;
235:            }
236:
237:            /**
238:             * Checks selection of this object's subnodes.
239:             * 
240:             * @return  {@code Boolean.TRUE}  if all subnodes are selected,
241:             *          {@code Boolean.FALSE}  if all subnodes are unselected,
242:             *          {@code null} if some subnodes are selected and some are
243:             *                       unselected
244:             */
245:            Boolean checkSubnodesSelection() {
246:                if (selectedMatches == null) {
247:                    return Boolean.valueOf(selected);
248:                }
249:
250:                final boolean firstMatchSelection = selectedMatches[0];
251:                for (int i = 1; i < selectedMatches.length; i++) {
252:                    if (selectedMatches[i] != firstMatchSelection) {
253:                        return null;
254:                    }
255:                }
256:                return Boolean.valueOf(firstMatchSelection);
257:            }
258:
259:            /**
260:             */
261:            void toggleSubnodeSelection(ResultModel resultModel, int index) {
262:                if (selectedMatches == null) {
263:                    selectedMatches = new boolean[resultModel
264:                            .getDetailsCount(this )];
265:                    Arrays.fill(selectedMatches, this .selected);
266:                }
267:                selectedMatches[index] = !selectedMatches[index];
268:            }
269:
270:            /**
271:             */
272:            void setSubnodeSelected(int index, boolean selected,
273:                    ResultModel resultModel) {
274:                if (selectedMatches == null) {
275:                    if (selected == this .selected) {
276:                        return;
277:                    }
278:                    selectedMatches = new boolean[resultModel
279:                            .getDetailsCount(this )];
280:                    Arrays.fill(selectedMatches, this .selected);
281:                }
282:
283:                assert (index >= 0) && (index < selectedMatches.length);
284:                selectedMatches[index] = selected;
285:            }
286:
287:            /**
288:             */
289:            boolean isSubnodeSelected(int index) {
290:                assert (selectedMatches == null)
291:                        || ((index >= 0) && (index < selectedMatches.length));
292:                return (selectedMatches == null) ? selected
293:                        : selectedMatches[index];
294:            }
295:
296:            @Override
297:            public boolean equals(Object anotherObject) {
298:                return (anotherObject != null)
299:                        && (anotherObject.getClass() == MatchingObject.class)
300:                        && (((MatchingObject) anotherObject).object == this .object);
301:            }
302:
303:            @Override
304:            public int hashCode() {
305:                return object.hashCode() + 1;
306:            }
307:
308:            /**
309:             * Sets the {@link #childrenSelectionDirty} flag.
310:             * 
311:             * @see  #markChildrenSelectionClean
312:             */
313:            void markChildrenSelectionDirty() {
314:                childrenSelectionDirty = true;
315:            }
316:
317:            /**
318:             * Clears the {@link #childrenSelectionDirty} flag.
319:             * 
320:             * @see  #markChildrenSelectionDirty()
321:             */
322:            void markChildrenSelectionClean() {
323:                childrenSelectionDirty = false;
324:            }
325:
326:            /**
327:             * Is the {@link #childrenSelectionDirty} flag set?
328:             * 
329:             * @return  {@code true} if the flag is set, {@code false} otherwise
330:             * @see  #markChildrenSelectionDirty()
331:             */
332:            boolean isChildrenSelectionDirty() {
333:                return childrenSelectionDirty;
334:            }
335:
336:            /**
337:             * Stores information whether the node representing this object is expanded
338:             * or collapsed.
339:             * 
340:             * @param  expanded  {@code true} if the node is expanded,
341:             *                   {@code false} if the node is collapsed
342:             * @see  #isExpanded()
343:             */
344:            void markExpanded(boolean expanded) {
345:                this .expanded = expanded;
346:            }
347:
348:            /**
349:             * Provides information whether the node representing this object
350:             * is expanded or collapsed.
351:             * 
352:             * @return  {@code true} if the node is expanded,
353:             *          {@code false} if the node is collapsed
354:             * @see  #markExpanded
355:             */
356:            boolean isExpanded() {
357:                return expanded;
358:            }
359:
360:            /**
361:             */
362:            File getFile() {
363:                return file;
364:            }
365:
366:            /** Get the name (not the path) of the file */
367:            String getName() {
368:                return getFile().getName();
369:            }
370:
371:            /**
372:             */
373:            long getTimestamp() {
374:                return timestamp;
375:            }
376:
377:            /**
378:             */
379:            String getDescription() {
380:                return getFile().getParent();
381:            }
382:
383:            /**
384:             */
385:            String getText() throws IOException {
386:                StringBuilder txt = text();
387:                if (txt != null) {
388:                    return txt.toString();
389:                } else {
390:                    return null;
391:                }
392:            }
393:
394:            /**
395:             */
396:            FileLock lock() throws IOException {
397:                return getFileObject().lock();
398:            }
399:
400:            /**
401:             * Reads the file if it has not been read already.
402:             * 
403:             * @author  TimBoudreau
404:             * @author  Marian Petras
405:             */
406:            private StringBuilder text() throws IOException {
407:                return text(false);
408:            }
409:
410:            private StringBuilder text(boolean refreshCache) throws IOException {
411:                assert !EventQueue.isDispatchThread();
412:
413:                if (refreshCache || (text == null)) {
414:                    text = readText();
415:                }
416:                return text == null ? new StringBuilder() : text;
417:            }
418:
419:            /**
420:             * Reads the text from the file.
421:             * 
422:             * @return  {@code StringBuilder} containing the text file's content,
423:             *          or {@code null} if reading was interrupted
424:             * @exception  java.io.IOException  if some error occured while reading
425:             *                                  the file
426:             */
427:            private StringBuilder readText() throws IOException {
428:                StringBuilder ret = null;
429:
430:                ByteBuffer buf = getByteBuffer();
431:                if (buf != null) {
432:                    Charset charset = BasicSearchCriteria
433:                            .getCharset(getFileObject());
434:                    CharBuffer cbuf = decodeByteBuffer(buf, charset);
435:                    String terminator = System.getProperty("line.separator"); //NOI18N
436:
437:                    if (!terminator.equals("\n")) { //NOI18N
438:                        Matcher matcher = Pattern.compile(terminator).matcher(
439:                                cbuf);
440:                        if (matcher.find()) {
441:                            wasCrLf = true;
442:                            matcher.reset();
443:                            ret = new StringBuilder(matcher.replaceAll("\n")); //NOI18N
444:                        }
445:                    }
446:                    if (ret == null) {
447:                        ret = new StringBuilder(cbuf);
448:                    }
449:                }
450:                return ret;
451:            }
452:
453:            /**
454:             * 
455:             * @author  Tim Boudreau
456:             */
457:            private ByteBuffer getByteBuffer() throws IOException {
458:                assert !EventQueue.isDispatchThread();
459:
460:                File file = getFile();
461:                //XXX optimize with a single shared bytebuffer if performance
462:                //problems noted
463:                FileInputStream str = new FileInputStream(file);
464:
465:                ByteBuffer buffer = ByteBuffer.allocate((int) file.length());
466:                FileChannel channel = str.getChannel();
467:                try {
468:                    channel.read(buffer, 0);
469:                } catch (ClosedByInterruptException cbie) {
470:                    return null; //this is actually okay
471:                } finally {
472:                    channel.close();
473:                }
474:                buffer.rewind();
475:                return buffer;
476:            }
477:
478:            /**
479:             * Describes invalidity status of this item.
480:             */
481:            enum InvalidityStatus {
482:
483:                DELETED(true, "Inv_status_Err_deleted"), //NOI18N
484:                BECAME_DIR(true, "Inv_status_Err_became_dir"), //NOI18N
485:                CHANGED(false, "Inv_status_Err_changed"), //NOI18N
486:                TOO_BIG(false, "Inv_status_Err_too_big"), //NOI18N
487:                CANT_READ(false, "Inv_status_Err_cannot_read"); //NOI18N
488:
489:                /**
490:                 * Is this invalidity the fatal one?
491:                 * 
492:                 * @see  #isFatal()
493:                 */
494:                private final boolean fatal;
495:                /**
496:                 * resource bundle key for the description
497:                 * 
498:                 * @see  #getDescription(String)
499:                 */
500:                private final String descrBundleKey;
501:
502:                /**
503:                 * Creates an invalidity status.
504:                 * 
505:                 * @param  fatal  whether this status means that the invalidity is fatal
506:                 * @see  #isFatal()
507:                 */
508:                private InvalidityStatus(boolean fatal, String descrBundleKey) {
509:                    this .fatal = fatal;
510:                    this .descrBundleKey = descrBundleKey;
511:                }
512:
513:                /**
514:                 * Is this invalidity fatal such that the item should be removed
515:                 * from the search results?
516:                 */
517:                boolean isFatal() {
518:                    return fatal;
519:                }
520:
521:                /**
522:                 * Provides human-readable description of this invalidity status.
523:                 * 
524:                 * @param  path  path or name of file that has this invalidity status
525:                 * @return  description of the invalidity status with the given path
526:                 *          or name embedded
527:                 */
528:                String getDescription(String path) {
529:                    return NbBundle
530:                            .getMessage(getClass(), descrBundleKey, path);
531:                }
532:
533:            }
534:
535:            /**
536:             */
537:            InvalidityStatus checkValidity() {
538:                InvalidityStatus status = getInvalidityStatus();
539:                if (status != null) {
540:                    valid = false;
541:                }
542:                return status;
543:            }
544:
545:            /**
546:             */
547:            String getInvalidityDescription() {
548:                String descr;
549:
550:                InvalidityStatus status = getInvalidityStatus();
551:                if (status != null) {
552:                    descr = status.getDescription(getFile().getPath());
553:                } else {
554:                    descr = null;
555:                }
556:                return descr;
557:            }
558:
559:            /**
560:             * Check validity status of this item.
561:             * 
562:             * @return  an invalidity status of this item if it is invalid,
563:             *          or {@code null} if this item is valid
564:             * @author  Tim Boudreau
565:             * @author  Marian Petras
566:             */
567:            private InvalidityStatus getInvalidityStatus() {
568:                log(FINER, "getInvalidityStatus()"); //NOI18N
569:                File f = getFile();
570:                if (!f.exists()) {
571:                    log(FINEST, " - DELETED");
572:                    return InvalidityStatus.DELETED;
573:                }
574:
575:                if (f.isDirectory()) {
576:                    log(FINEST, " - BECAME_DIR");
577:                    return InvalidityStatus.BECAME_DIR;
578:                }
579:
580:                long stamp = f.lastModified();
581:                if (stamp > resultModel.getCreationTime()) {
582:                    log(SEVERE,
583:                            "file's timestamp changed since start of the search");
584:                    if (LOG.isLoggable(FINEST)) {
585:                        final java.util.Calendar cal = java.util.Calendar
586:                                .getInstance();
587:                        cal.setTimeInMillis(stamp);
588:                        log(FINEST, " - file stamp:           " + stamp + " ("
589:                                + cal.getTime() + ')');
590:                        cal.setTimeInMillis(resultModel.getCreationTime());
591:                        log(FINEST, " - result model created: "
592:                                + resultModel.getCreationTime() + " ("
593:                                + cal.getTime() + ')');
594:                    }
595:                    return InvalidityStatus.CHANGED;
596:                }
597:
598:                if (f.length() > Integer.MAX_VALUE) {
599:                    return InvalidityStatus.TOO_BIG;
600:                }
601:
602:                if (!f.canRead()) {
603:                    return InvalidityStatus.CANT_READ;
604:                }
605:
606:                return null;
607:            }
608:
609:            /**
610:             */
611:            boolean isValid() {
612:                return valid;
613:            }
614:
615:            /**
616:             */
617:            public InvalidityStatus replace() throws IOException {
618:                assert !EventQueue.isDispatchThread();
619:                assert isSelected();
620:
621:                Boolean uniformSelection = checkSubnodesSelection();
622:                final boolean shouldReplaceAll = (uniformSelection == Boolean.TRUE);
623:                final boolean shouldReplaceNone = (uniformSelection == Boolean.FALSE);
624:
625:                if (shouldReplaceNone) {
626:                    return null;
627:                }
628:
629:                StringBuilder content = text(true); //refresh the cache, reads the file
630:
631:                List<TextDetail> textMatches = resultModel.basicCriteria
632:                        .getTextDetails(object);
633:                int matchIndex = 0;
634:
635:                int currLineOffset = 0;
636:                int currLine = 1;
637:
638:                int inlineMatchNumber = 0; //order of a match in a line
639:                int inlineOffsetShift = 0; //shift of offsets caused by replacements
640:
641:                mainloop: for (TextDetail textDetail : textMatches) {
642:                    int matchLine = textDetail.getLine();
643:
644:                    while (currLine < matchLine) {
645:                        int lfOffset = content.indexOf("\n", currLineOffset);//NOI18N
646:                        if (lfOffset == -1) {
647:                            assert false; //PENDING - should notify user
648:                            break mainloop;
649:                        }
650:
651:                        currLineOffset = lfOffset + 1; //skips "\n"
652:                        currLine++;
653:                        inlineMatchNumber = 0;
654:                        inlineOffsetShift = 0;
655:                    }
656:
657:                    if (!isSubnodeSelected(matchIndex++)) {
658:                        continue;
659:                    }
660:
661:                    if (++inlineMatchNumber == 1) { //first selected match on a line
662:                        boolean check = false;
663:                        assert check = true; //side-effect - turns the check on
664:                        if (check) {
665:                            int lineEndOffset = content.indexOf("\n", //NOI18N
666:                                    currLineOffset);
667:                            String fileLine = (lineEndOffset != -1) ? content
668:                                    .substring(currLineOffset, lineEndOffset)
669:                                    : content.substring(currLineOffset);
670:                            if (!fileLine.equals(textDetail.getLineText())) {
671:                                log(SEVERE,
672:                                        "file line differs from the expected line");
673:                                if (LOG.isLoggable(FINEST)) {
674:                                    log(SEVERE, " - expected line: \""
675:                                            + textDetail.getLineText() + '"');
676:                                    log(SEVERE, " - file line:     \""
677:                                            + fileLine + '"');
678:                                }
679:                                return InvalidityStatus.CHANGED;
680:                            }
681:                        }
682:                    }
683:
684:                    int matchLength = textDetail.getMarkLength();
685:                    int matchOffset = currLineOffset + inlineOffsetShift
686:                            + (textDetail.getColumn() - 1);
687:                    int matchEndOffset = matchOffset + matchLength;
688:                    if (!content.substring(matchOffset, matchEndOffset).equals(
689:                            textDetail.getLineText().substring(
690:                                    textDetail.getColumn() - 1,
691:                                    textDetail.getColumn() - 1 + matchLength))) {
692:                        log(SEVERE,
693:                                "file match part differs from the expected match");
694:                        if (LOG.isLoggable(FINEST)) {
695:                            log(SEVERE, " - expected line: \""
696:                                    + textDetail.getLineText().substring(
697:                                            textDetail.getColumn() - 1,
698:                                            textDetail.getColumn() - 1
699:                                                    + matchLength) + '"');
700:                            log(SEVERE, " - file line:     \""
701:                                    + content.substring(matchOffset,
702:                                            matchEndOffset) + '"');
703:                        }
704:                        return InvalidityStatus.CHANGED;
705:                    }
706:
707:                    content.replace(matchOffset, matchEndOffset,
708:                            resultModel.replaceString);
709:                    inlineOffsetShift += resultModel.replaceString.length()
710:                            - matchLength;
711:                }
712:                return null;
713:            }
714:
715:            /** debug flag */
716:            private static final boolean REALLY_WRITE = true;
717:
718:            /**
719:             */
720:            void write(final FileLock fileLock) throws IOException {
721:                if (text == null) {
722:                    throw new IllegalStateException("Buffer is gone"); //NOI18N
723:                }
724:
725:                if (REALLY_WRITE) {
726:                    if (wasCrLf) {
727:                        String terminator = System
728:                                .getProperty("line.separator"); //NOI18N
729:                        //XXX use constant - i.e. on mac, only \r, etc.
730:                        text = new StringBuilder(text.toString().replace("\n",
731:                                terminator)); //NOI18N
732:                    }
733:                    final FileObject fileObject = getFileObject();
734:                    Writer writer = null;
735:                    try {
736:                        writer = new OutputStreamWriter(fileObject
737:                                .getOutputStream(fileLock), BasicSearchCriteria
738:                                .getCharset(fileObject));
739:                        writer.write(text.toString());
740:                    } finally {
741:                        if (writer != null) {
742:                            writer.close();
743:                        }
744:                    }
745:                } else {
746:                    System.err.println("Would write to " + getFile().getPath());//NOI18N
747:                    System.err.println(text);
748:                }
749:            }
750:
751:            /**
752:             * Decodes a given {@code ByteBuffer} with a given charset decoder.
753:             * This is a workaround for a broken
754:             * {@link Charset.decode(ByteBuffer) Charset#decode(java.nio.ByteBuffer}
755:             * method in JDK 1.5.x.
756:             * 
757:             * @param  in  {@code ByteBuffer} to be decoded
758:             * @param  charset  charset whose decoder will be used for decoding
759:             * @return  {@code CharBuffer} containing chars produced by the decoder
760:             * @see  <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/nio/charset/Charset.html#decode(java.nio.ByteBuffer)">Charset.decode(ByteBuffer)</a>
761:             * @see  <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6221056">JDK bug #6221056</a>
762:             * @see  <a href="http://www.netbeans.org/issues/show_bug.cgi?id=103193">NetBeans bug #103193</a>
763:             * @see  <a href="http://www.netbeans.org/issues/show_bug.cgi?id=103067">NetBeans bug #103067</a>
764:             */
765:            private CharBuffer decodeByteBuffer(final ByteBuffer in,
766:                    final Charset charset) throws CharacterCodingException {
767:
768:                final CharsetDecoder decoder = charset.newDecoder()
769:                        .onMalformedInput(CodingErrorAction.REPLACE)
770:                        .onUnmappableCharacter(CodingErrorAction.REPLACE);
771:
772:                int remaining = in.remaining();
773:                if (remaining == 0) {
774:                    return CharBuffer.allocate(0);
775:                }
776:
777:                int n = (int) (remaining * decoder.averageCharsPerByte());
778:                if (n < 16) {
779:                    n = 16; //make sure some CharBuffer is allocated
780:                    //even when decoding small number of bytes
781:                    //and averageCharsPerByte() is less than 1
782:                }
783:                CharBuffer out = CharBuffer.allocate(n);
784:
785:                decoder.reset();
786:                for (;;) {
787:                    CoderResult cr = in.hasRemaining() ? decoder.decode(in,
788:                            out, true) : CoderResult.UNDERFLOW;
789:                    if (cr.isUnderflow()) {
790:                        cr = decoder.flush(out);
791:                    }
792:                    if (cr.isUnderflow()) {
793:                        break;
794:                    }
795:                    if (cr.isOverflow()) {
796:                        CharBuffer o = CharBuffer.allocate(n <<= 1);
797:                        out.flip();
798:                        o.put(out);
799:                        out = o;
800:                        continue;
801:                    }
802:                    cr.throwException();
803:                }
804:                out.flip();
805:                return out;
806:            }
807:
808:            /**
809:             *
810:             */
811:            private void log(Level logLevel, String msg) {
812:                String id = (object instanceof  DataObject) ? ((DataObject) object)
813:                        .getName()
814:                        : object.toString();
815:                if (LOG.isLoggable(logLevel)) {
816:                    LOG.log(logLevel, id + ": " + msg); //NO1I8N:w
817:                }
818:            }
819:
820:            /** Returns name of this node.
821:             * @return name of this node.
822:             */
823:            @Override
824:            public String toString() {
825:                return super .toString() + "[" + getName() + "]"; // NOI18N
826:            }
827:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.