This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 138973
Collapse All | Expand All

(-)959c4114681e (+362 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2008 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.templates;
41
42
import java.util.Enumeration;
43
import org.openide.loaders.*;
44
import java.io.BufferedReader;
45
import java.io.BufferedWriter;
46
import java.io.ByteArrayInputStream;
47
import java.io.IOException;
48
import java.io.InputStream;
49
import java.io.InputStreamReader;
50
import java.io.OutputStream;
51
import java.io.OutputStreamWriter;
52
import java.io.Reader;
53
import java.io.Writer;
54
import java.nio.ByteBuffer;
55
import java.nio.CharBuffer;
56
import java.nio.charset.Charset;
57
import java.nio.charset.CharsetDecoder;
58
import java.nio.charset.CharsetEncoder;
59
import java.nio.charset.CoderResult;
60
import java.util.Map;
61
import org.netbeans.api.queries.FileEncodingQuery;
62
import org.netbeans.junit.MockServices;
63
import org.netbeans.junit.NbTestCase;
64
import org.netbeans.modules.openide.loaders.DataObjectEncodingQueryImplementation;
65
import org.netbeans.spi.queries.FileEncodingQueryImplementation;
66
import org.openide.filesystems.FileObject;
67
import org.openide.filesystems.FileUtil;
68
import org.openide.util.Enumerations;
69
import org.openide.util.Lookup;
70
import org.openide.util.lookup.Lookups;
71
72
/**
73
 *
74
 * @author  Marian Petras
75
 */
76
public class Bug138973Test extends NbTestCase {
77
78
    private static final String TESTING_TEXT = "This is a testing text.";
79
    private static final TestCharset TEST_CHARSET = new TestCharset();
80
    private static final String EXT = ".txt";
81
    private static final String TEMPLATE_NAME = "Bug138973TestTemplate";
82
    private static final String TEMPLATE_NAME_EXT = TEMPLATE_NAME + EXT;
83
    private static final String TESTFILE_NAME = "testfile";
84
    private static final String TESTFILE_NAME_EXT = TESTFILE_NAME + EXT;
85
86
    public Bug138973Test() {
87
        super("Bug138973Test");
88
    }
89
90
    public void testBug() throws Exception {
91
        MockServices.setServices(Pool.class, DataObjectEncodingQueryImplementation.class);
92
93
        FileObject root = FileUtil.createMemoryFileSystem().getRoot();
94
        FileObject templatesFolder = root.createFolder("templates");
95
        assert templatesFolder != null;
96
        FileObject templateFile = FileUtil.createData(templatesFolder,
97
                                                      TEMPLATE_NAME_EXT);
98
        templateFile.setAttribute ("template", Boolean.TRUE);
99
        templateFile.setAttribute("javax.script.ScriptEngine", "freemarker");
100
        byte[] templateBytes = TESTING_TEXT.getBytes("ISO-8859-1");
101
        InputStream source = new ByteArrayInputStream(templateBytes);
102
        OutputStream target = templateFile.getOutputStream();
103
        FileUtil.copy(source, target);
104
        target.close();
105
        source.close();
106
        assert templateFile.getSize() != 0L;
107
        templateFile.setAttribute("template", Boolean.TRUE);
108
109
        DataObject templateDataObj = DataObject.find(templateFile);
110
        DataObject newDataObj= templateDataObj.createFromTemplate(
111
                                                    DataFolder.findFolder(root),
112
                                                    TESTFILE_NAME);
113
        FileObject newFile = newDataObj.getPrimaryFile();
114
115
        byte[] expectedBytes = new byte[TESTING_TEXT.length() * 4];
116
        TEST_CHARSET.encode(TESTING_TEXT).get(expectedBytes);
117
118
        byte[] actualBytes = new byte[(int) (newFile.getSize())];
119
        InputStream is = null;
120
        try {
121
            is = newFile.getInputStream();
122
            newFile.getInputStream().read(actualBytes);
123
        } finally {
124
            if (is != null) {
125
                is.close();
126
            }
127
        }
128
        assertEquals(expectedBytes, actualBytes);
129
    }
130
131
    private void assertEquals(byte[] expected, byte[] actual) throws Exception {
132
        if ((expected == null) && (actual == null)) {
133
            return;
134
        }
135
        if ((expected == null) || (actual == null)) {
136
            if (actual == null) {
137
                fail("actual is null");
138
            } else{
139
                fail("expected is null");
140
            }
141
        }
142
        if (expected.length != actual.length) {
143
            fail("array lengths differ - expected: "
144
                 + expected.length + ", actual: " + actual.length);
145
        }
146
        for (int i = 0; i < actual.length; i++) {
147
            if (actual[i] != expected[i]) {
148
                String expectedStr = new String(expected, "ISO-8859-1");
149
                String actualStr = new String(actual, "ISO-8859-1");
150
                fail("expected: \"" + expectedStr
151
                     + "\", actual: \"" + actualStr + '"');
152
            }
153
        }
154
    }
155
156
    public static final class SimpleTemplateHandler extends CreateFromTemplateHandler {
157
        @Override
158
        protected boolean accept(FileObject orig) {
159
            return true;
160
        }
161
        @Override
162
        protected FileObject createFromTemplate(FileObject template,
163
                                                FileObject targetFolder,
164
                                                String name,
165
                                                Map<String, Object> parameters) throws IOException {
166
            String nameUniq = FileUtil.findFreeFileName(targetFolder, name, template.getExt());
167
            FileObject newFile = FileUtil.createData(targetFolder, nameUniq + '.' + template.getExt());
168
169
            Charset templateEnc = FileEncodingQuery.getEncoding(template);
170
            Charset newFileEnc = FileEncodingQuery.getEncoding(newFile);
171
172
            InputStream is = template.getInputStream();
173
            Reader reader = new BufferedReader(new InputStreamReader(is, templateEnc));
174
            OutputStream os = newFile.getOutputStream();
175
            Writer writer = new BufferedWriter(new OutputStreamWriter(os, newFileEnc));
176
            int cInt;
177
            while ((cInt = reader.read()) != -1) {
178
                writer.write(cInt);
179
            }
180
            writer.close();
181
            reader.close();
182
183
            return newFile;
184
        }
185
    }
186
187
    public static final class SimpleLoader extends MultiFileLoader {
188
        public SimpleLoader() {
189
            super(SimpleObject.class.getName());
190
        }
191
        protected String displayName() {
192
            return "SimpleLoader";
193
        }
194
        protected FileObject findPrimaryFile(FileObject fo) {
195
            if (fo.getNameExt().equals(TEMPLATE_NAME_EXT)) {
196
                return fo;
197
            }
198
            if (fo.getNameExt().equals(TESTFILE_NAME_EXT)) {
199
                return fo;
200
            }
201
            return null;
202
        }
203
        protected MultiDataObject createMultiObject(FileObject primaryFile)
204
                                            throws DataObjectExistsException,
205
                                                   IOException {
206
            return new SimpleObject(this, primaryFile, isTestingFile(primaryFile));
207
        }
208
        protected MultiDataObject.Entry createPrimaryEntry(MultiDataObject obj,
209
                                                           FileObject primaryFile) {
210
            return new FE(obj, primaryFile);
211
        }
212
        protected MultiDataObject.Entry createSecondaryEntry(MultiDataObject obj,
213
                                                             FileObject secondaryFile) {
214
            return new FE(obj, secondaryFile);
215
        }
216
        private static boolean isTestingFile(FileObject fileObj) {
217
            return fileObj.getNameExt().equals(TESTFILE_NAME_EXT);
218
        }
219
    }
220
221
    private static final class FE extends FileEntry {
222
        public FE(MultiDataObject mo, FileObject fo) {
223
            super(mo, fo);
224
        }
225
        @Override
226
        public FileObject createFromTemplate(FileObject f, String name) throws IOException {
227
            fail("FileEntry.createFromTemplate() should not be called");
228
            return null;
229
        }
230
    }
231
232
    public static final class SimpleObject extends MultiDataObject {
233
        private final Lookup lookup;
234
        public SimpleObject(SimpleLoader l,
235
                            FileObject fo,
236
                            boolean useSpecialEncoding)
237
                                              throws DataObjectExistsException {
238
            super(fo, l);
239
            lookup = useSpecialEncoding
240
                     ? Lookups.fixed(this, new TestEncoding())
241
                     : Lookups.singleton(this);
242
        }
243
        @Override
244
        public String getName() {
245
            return getPrimaryFile().getNameExt();
246
        }
247
        @Override
248
        public Lookup getLookup() {
249
            return lookup;
250
        }
251
    }
252
253
    static final class TestEncoding extends FileEncodingQueryImplementation {
254
        @Override
255
        public Charset getEncoding(FileObject file) {
256
            return TEST_CHARSET;
257
        }
258
    }
259
260
    static final class TestCharset extends Charset {
261
        TestCharset() {
262
            super("test_charset", null);
263
        }
264
        public boolean contains(Charset charset) {
265
            return true;
266
        }
267
        public CharsetDecoder newDecoder() {
268
            return new TestCharsetDecoder(this);
269
        }
270
        public CharsetEncoder newEncoder() {
271
            return new TestCharsetEncoder(this);
272
        }
273
    }
274
275
    static final class TestCharsetDecoder extends CharsetDecoder {
276
        private static final String hexadecimalChars
277
                                    = "0123456789abcdef";               //NOI18N
278
        TestCharsetDecoder(Charset charset) {
279
            super(charset, 1.0f, 1.0f);
280
        }
281
        @Override
282
        protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
283
            for (;;) {
284
                int value = 0;
285
286
                byte b;
287
                char bChar;
288
                int index;
289
290
                if (!in.hasRemaining()) { return CoderResult.UNDERFLOW; }
291
                b = in.get();
292
                bChar = (char) (b >= 0 ? b : b + 256);
293
                index = hexadecimalChars.indexOf(bChar);
294
                if (index == -1) { return CoderResult.malformedForLength(1); }
295
                value = index;
296
297
                if (!in.hasRemaining()) { return CoderResult.UNDERFLOW; }
298
                b = in.get();
299
                bChar = (char) (b >= 0 ? b : b + 256);
300
                index = hexadecimalChars.indexOf(bChar);
301
                if (index == -1) { return CoderResult.malformedForLength(2); }
302
                value = (value << 4) | index;
303
304
                if (!in.hasRemaining()) { return CoderResult.UNDERFLOW; }
305
                b = in.get();
306
                bChar = (char) (b >= 0 ? b : b + 256);
307
                index = hexadecimalChars.indexOf(bChar);
308
                if (index == -1) { return CoderResult.malformedForLength(3); }
309
                value = (value << 4) | index;
310
311
                if (!in.hasRemaining()) { return CoderResult.UNDERFLOW; }
312
                b = in.get();
313
                bChar = (char) (b >= 0 ? b : b + 256);
314
                index = hexadecimalChars.indexOf(bChar);
315
                if (index == -1) { return CoderResult.malformedForLength(4); }
316
                value = (value << 4) | index;
317
318
                if (!out.hasRemaining()) { return CoderResult.OVERFLOW; }
319
                out.put((char) value);
320
            }
321
        }
322
    }
323
324
    /**
325
     * Encodes each character as a series of four hexadecimal digits expressing
326
     * the character's Unicode value.
327
     */
328
    static final class TestCharsetEncoder extends CharsetEncoder {
329
        private static final byte[] hexadecimalChars
330
            = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
331
        TestCharsetEncoder(Charset charset) {
332
            super(charset, 4.0f, 4.0f, new byte[] {0x30, 0x30, 0x33, 0x66});
333
        }
334
        @Override
335
        protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
336
            for (;;) {
337
                if (!in.hasRemaining()) {
338
                    return CoderResult.UNDERFLOW;
339
                }
340
                char c = in.get();
341
                int cInt = (int) c;
342
                if (!out.hasRemaining()) { return CoderResult.OVERFLOW; }
343
                out.put(hexadecimalChars[(cInt >> 12) & 0x000f]);
344
                if (!out.hasRemaining()) { return CoderResult.OVERFLOW; }
345
                out.put(hexadecimalChars[(cInt >>  8) & 0x000f]);
346
                if (!out.hasRemaining()) { return CoderResult.OVERFLOW; }
347
                out.put(hexadecimalChars[(cInt >>  4) & 0x000f]);
348
                if (!out.hasRemaining()) { return CoderResult.OVERFLOW; }
349
                out.put(hexadecimalChars[ cInt        & 0x000f]);
350
            }
351
        }
352
353
    }
354
355
    public static final class Pool extends DataLoaderPool {
356
        @Override
357
        protected Enumeration<? extends DataLoader> loaders() {
358
            return Enumerations.singleton(SimpleLoader.getLoader(SimpleLoader.class));
359
        }
360
361
    }
362
}

Return to bug 138973