All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modules.diff.EncodedReaderFactory Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.modules.diff;

import java.io.*;
import java.lang.reflect.Method;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.EditorKit;
import javax.swing.text.StyledDocument;

import org.openide.ErrorManager;
import org.openide.cookies.EditCookie;
import org.openide.filesystems.FileLock;

import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;

import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.text.CloneableEditorSupport;
import org.openide.util.Lookup;

/**
 * Factory of readers that are encoded according to best known approach how to
 * get the encoding information.
 * 

* This factory should ideally be replaced by some public APIs. This uses just * heuristics combined with a lot of reflection calls to find things out. * This is intended to be only a temporary solution. *

* Use on your own risk. * * @author Martin Entlicher * @deprecated it is here only for compatibility with vcsgeneric modules, otherwise unused */ @Deprecated public class EncodedReaderFactory { /** The FileObject attribute that defines the encoding of the FileObject content. */ private static final String CHAR_SET_ATTRIBUTE = "Content-Encoding"; // NOI18N private static EncodedReaderFactory factory; /** Creates a new instance of EncodedReaderFactory */ private EncodedReaderFactory() { } /** Get the default implementation. */ public static synchronized EncodedReaderFactory getDefault() { if (factory == null) { factory = new EncodedReaderFactory(); } return factory; } /** * Get the reader from file of given MIME type, it tries to find the best encoding itself. */ public Reader getReader(File file, String mimeType) throws FileNotFoundException { return getReader(file, mimeType, getEncoding(file)); } /** * Get the reader from file of given MIME type, suggest the encoding, if known. */ public Reader getReader(File file, String mimeType, String encoding) throws FileNotFoundException { if (encoding != null) { try { return new InputStreamReader(new FileInputStream(file), encoding); } catch (UnsupportedEncodingException ueex) { ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ueex); } } Reader r = null; String name = file.getName(); int endingIndex = name.lastIndexOf('.'); String ext = (endingIndex >= 0 && endingIndex < (name.length() - 1)) ? name.substring(endingIndex + 1) : ""; if (!"java".equalsIgnoreCase(ext)) { // We read the encoding for Java files explicitely try { // If it's not defined, read with default encoding from stream (because of guarded blocks) file = FileUtil.normalizeFile(file); FileObject fo = FileUtil.toFileObject(file); if (fo != null) { r = getReaderFromEditorSupport(fo, fo); } } catch (IllegalArgumentException iaex) { ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, iaex); } if (r == null) { r = getReaderFromKit(file, null, mimeType); } } if (r == null) { // Fallback, use current encoding r = new InputStreamReader(new FileInputStream(file)); } return r; } public Reader getReader(FileObject fo, String encoding) throws FileNotFoundException { return getReader(fo, encoding, fo.getExt()); } public Reader getReader(FileObject fo, String encoding, String secondFileExt) throws FileNotFoundException { return getReader(fo, encoding, fo, secondFileExt); } public Reader getReader(FileObject fo, String encoding, FileObject type) throws FileNotFoundException { return getReader(fo, encoding, type, type.getExt()); } private Reader getReader(FileObject fo, String encoding, FileObject type, String secondFileExt) throws FileNotFoundException { if (encoding != null) { try { return new InputStreamReader(fo.getInputStream(), encoding); } catch (UnsupportedEncodingException ueex) { ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ueex); } } Reader r = null; String ext = type.getExt(); if (!"java".equalsIgnoreCase(ext) || !ext.equals(secondFileExt)) {// We read the encoding for Java files explicitely // If it's not defined, read with default encoding from stream (because of guarded blocks) // But when the extensions of the two files are different (comparing Java files with something else), // we have to use the Document approach for both due to possible different line-endings. r = getReaderFromEditorSupport(fo, type); if (r == null) { r = getReaderFromKit(null, fo, type.getMIMEType()); } } if (r == null) { // Fallback, use current encoding r = new InputStreamReader(fo.getInputStream()); } return r; } /** @return The reader or null. */ private Reader getReaderFromEditorSupport(FileObject fo, FileObject type) throws FileNotFoundException { //System.out.println("getReaderFromEditorSupport("+fo+")"); DataObject dobj; try { dobj = DataObject.find(type); } catch (DataObjectNotFoundException donfex) { return null; } if (!type.equals(dobj.getPrimaryFile())) { return null; } EditCookie edit = (EditCookie) dobj.getCookie(EditCookie.class); CloneableEditorSupport editorSupport = null; if (edit instanceof CloneableEditorSupport) { editorSupport = (CloneableEditorSupport) edit; } //System.out.println(" editorSupport = "+editorSupport); if (editorSupport == null) { return null; } try { Method createKitMethod = getDeclaredMethod(editorSupport.getClass(), "createEditorKit", new Class[] {}); createKitMethod.setAccessible(true); EditorKit kit = (EditorKit) createKitMethod.invoke(editorSupport, new Object[] {}); //System.out.println(" KIT from cloneable editor support = "+kit); Method createStyledDocumentMethod = getDeclaredMethod(editorSupport.getClass(), "createStyledDocument", new Class[] { EditorKit.class }); createStyledDocumentMethod.setAccessible(true); StyledDocument doc = (StyledDocument) createStyledDocumentMethod.invoke(editorSupport, new Object[] { kit }); Method loadFromStreamToKitMethod = getDeclaredMethod(editorSupport.getClass(), "loadFromStreamToKit", new Class[] { StyledDocument.class, InputStream.class, EditorKit.class }); loadFromStreamToKitMethod.setAccessible(true); InputStream in = fo.getInputStream(); try { loadFromStreamToKitMethod.invoke(editorSupport, new Object[] { doc, in, kit }); } finally { try { in.close(); } catch (IOException ioex) {} } String text = doc.getText(0, doc.getLength()); doc = null; // Release it, we have the text return new StringReader(text); } catch (Exception ex) { ex.printStackTrace(); return null; } } /** @return The writer or null. */ private Writer getWriterFromEditorSupport(final FileObject fo, FileLock lock) throws FileNotFoundException { //System.out.println("getWriterFromEditorSupport("+fo+")"); DataObject dobj; try { dobj = DataObject.find(fo); } catch (DataObjectNotFoundException donfex) { return null; } if (!fo.equals(dobj.getPrimaryFile())) { return null; } EditCookie edit = (EditCookie) dobj.getCookie(EditCookie.class); final CloneableEditorSupport editorSupport; if (edit instanceof CloneableEditorSupport) { editorSupport = (CloneableEditorSupport) edit; } else { editorSupport = null; } //System.out.println(" editorSupport = "+editorSupport); if (editorSupport == null) { return null; } try { Method createKitMethod = getDeclaredMethod(editorSupport.getClass(), "createEditorKit", new Class[] {}); createKitMethod.setAccessible(true); final EditorKit kit = (EditorKit) createKitMethod.invoke(editorSupport, new Object[] {}); //System.out.println(" KIT from cloneable editor support = "+kit); Method createStyledDocumentMethod = getDeclaredMethod(editorSupport.getClass(), "createStyledDocument", new Class[] { EditorKit.class }); createStyledDocumentMethod.setAccessible(true); final StyledDocument doc = (StyledDocument) createStyledDocumentMethod.invoke(editorSupport, new Object[] { kit }); final Method saveFromKitToStreamMethod = getDeclaredMethod(editorSupport.getClass(), "saveFromKitToStream", new Class[] { StyledDocument.class, EditorKit.class, OutputStream.class }); saveFromKitToStreamMethod.setAccessible(true); return new DocWriter(doc, fo, lock, null, kit, editorSupport, saveFromKitToStreamMethod); } catch (Exception ex) { ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); return null; } } private static Method getDeclaredMethod(Class objClass, String name, Class[] args) throws NoSuchMethodException, SecurityException { try { return objClass.getDeclaredMethod(name, args); } catch (NoSuchMethodException nsmex) { Class superClass = objClass.getSuperclass(); if (superClass != null) { return getDeclaredMethod(superClass, name, args); } else { throw nsmex; } } } /** @return The reader or null. */ private Reader getReaderFromKit(File file, FileObject fo, String mimeType) throws FileNotFoundException { EditorKit kit = CloneableEditorSupport.getEditorKit(mimeType); if (kit.getContentType().equalsIgnoreCase("text/plain") && "text/x-dtd".equalsIgnoreCase(mimeType)) { // Use XML kit for DTDs if not defined otherwise kit = CloneableEditorSupport.getEditorKit("text/xml"); } //System.out.println(" KIT for "+mimeType+" = "+kit); if (kit != null) { Document doc = kit.createDefaultDocument(); InputStream stream = null; try { if (file != null) { stream = new FileInputStream(file); } else { stream = fo.getInputStream(); } kit.read(stream, doc, 0); String text = doc.getText(0, doc.getLength()); //System.out.println(" TEXT = "+text); doc = null; // Release it, we have the text return new StringReader(text); } catch (IOException ioex) { FileNotFoundException fnfex; if (file != null) { fnfex = new FileNotFoundException("Can not read file "+file.getAbsolutePath()); } else { fnfex = new FileNotFoundException("Can not read file "+fo); } fnfex.initCause(ioex); throw fnfex; } catch (BadLocationException blex) { // Something wrong??? ErrorManager.getDefault().notify(blex); } finally { if (stream != null) { try { stream.close(); } catch (IOException e) {} } } } return null; } /** @return The writer or null. */ private Writer getWriterFromKit(File file, FileObject fo, FileLock lock, String mimeType) throws FileNotFoundException { EditorKit kit = CloneableEditorSupport.getEditorKit(mimeType); if (kit.getContentType().equalsIgnoreCase("text/plain") && "text/x-dtd".equalsIgnoreCase(mimeType)) { // Use XML kit for DTDs if not defined otherwise kit = CloneableEditorSupport.getEditorKit("text/xml"); } //System.out.println(" KIT for "+mimeType+" = "+kit); if (kit != null) { Document doc = kit.createDefaultDocument(); return new DocWriter(doc, fo, lock, file, kit, null, null); } return null; } /** * Get the writer to file of given MIME type, it tries to find the best encoding itself. */ public Writer getWriter(File file, String mimeType) throws FileNotFoundException { return getWriter(file, mimeType, getEncoding(file)); } /** * Get the writer to file of given MIME type, suggest the encoding, if known. */ public Writer getWriter(File file, String mimeType, String encoding) throws FileNotFoundException { if (encoding != null) { try { return new OutputStreamWriter(new FileOutputStream(file), encoding); } catch (UnsupportedEncodingException ueex) { ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ueex); } } Writer w = null; String name = file.getName(); int endingIndex = name.lastIndexOf('.'); String ext = (endingIndex >= 0 && endingIndex < (name.length() - 1)) ? name.substring(endingIndex + 1) : ""; if (!"java".equalsIgnoreCase(ext)) { // We read the encoding for Java files explicitely try { // If it's not defined, read with default encoding from stream (because of guarded blocks) file = FileUtil.normalizeFile(file); FileObject fo = FileUtil.toFileObject(file); if (fo != null) { FileLock lock; try { lock = fo.lock(); } catch (IOException ioex) { FileNotFoundException fnfex = new FileNotFoundException(ioex.getLocalizedMessage()); fnfex.initCause(ioex); throw fnfex; } w = getWriterFromEditorSupport(fo, lock); } } catch (IllegalArgumentException iaex) { ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, iaex); } if (w == null) { w = getWriterFromKit(file, null, null, mimeType); } } if (w == null) { // Fallback, use current encoding w = new OutputStreamWriter(new FileOutputStream(file)); } return w; } /** * Get the writer to file, suggest the encoding, if known. */ public Writer getWriter(FileObject fo, FileLock lock, String encoding) throws IOException { if (lock == null) { lock = fo.lock(); } if (encoding != null) { try { return new OutputStreamWriter(fo.getOutputStream(lock), encoding); } catch (UnsupportedEncodingException ueex) { ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ueex); } } Writer w = null; String ext = fo.getExt(); if (!"java".equalsIgnoreCase(ext)) { // We read the encoding for Java files explicitely // If it's not defined, read with default encoding from stream (because of guarded blocks) w = getWriterFromEditorSupport(fo, lock); if (w == null) { w = getWriterFromKit(null, fo, lock, fo.getMIMEType()); } } if (w == null) { // Fallback, use current encoding w = new OutputStreamWriter(fo.getOutputStream(lock)); } return w; } /** Uses heuritisc to detect file encoding or null. */ public String getEncoding(File file) { return getEncoding(FileUtil.toFileObject(FileUtil.normalizeFile(file))); } public static String decodeName(FileObject fo) { String ret = fo.getNameExt(); if (fo.getParent() != null && fo.getParent().getPath().endsWith("CVS" + File.separator + "RevisionCache")) { // NOI18N String name = fo.getName(); int hashOffset = name.lastIndexOf("#"); // NOI18N if (hashOffset != 1) { ret = name.substring(0, hashOffset); } } return ret; } public String getEncoding(FileObject fo) { String name = decodeName(fo).toLowerCase(); if (name.endsWith(".properties")) { return findPropertiesEncoding(); } if (name.endsWith(".form")) { return "utf8"; } Object encoding = null; if (fo != null) { if (name.endsWith(".java")) { encoding = findJavaEncoding(fo); // is not in cache } if (encoding == null) { encoding = fo.getAttribute(CHAR_SET_ATTRIBUTE); // XXX is not in cache } } if (name.endsWith(".xml") || name.endsWith(".dtd") || name.endsWith(".xsd") || name.endsWith(".xsl")) { // NOI18N InputStream in = null; try { in = new BufferedInputStream(fo.getInputStream(), 2048); encoding = XMLEncodingHelper.detectEncoding(in); } catch (IOException e) { ErrorManager err = ErrorManager.getDefault(); err.annotate(e, "Can not detect encoding for: " + fo.getPath()); // NOI18N err.notify(ErrorManager.INFORMATIONAL, e); } finally { if (in != null) { try { in.close(); } catch (IOException e) { } } } } if (encoding != null) { return encoding.toString(); } else { return null; } } private static String findJavaEncoding(FileObject fo) { ClassLoader systemClassLoader = (ClassLoader) Lookup.getDefault().lookup(ClassLoader.class); Method org_netbeans_modules_java_Util_getFileEncoding = null; try { Class c = systemClassLoader. loadClass("org.netbeans.modules.java.Util"); // NOI18N org_netbeans_modules_java_Util_getFileEncoding = c.getMethod("getFileEncoding", new Class[] {FileObject.class}); } catch (Exception e) { // Ignore } if (org_netbeans_modules_java_Util_getFileEncoding != null) { try { String encoding = (String) org_netbeans_modules_java_Util_getFileEncoding. invoke(null, new Object[] {fo}); return encoding; } catch (Exception e) { ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); } } return null; } private static String findPropertiesEncoding() { return "ISO-8859-1"; // NOI18N } private static class DocWriter extends Writer { private Document doc; private FileObject fo; private FileLock foLock; private File file; private EditorKit kit; private CloneableEditorSupport editorSupport; private Method saveFromKitToStreamMethod; private boolean closed; public DocWriter(Document doc, FileObject fo, FileLock foLock, File file, EditorKit kit, CloneableEditorSupport editorSupport, Method saveFromKitToStreamMethod) { this.doc = doc; this.fo = fo; this.foLock = foLock; this.file = file; this.kit = kit; this.editorSupport = editorSupport; this.saveFromKitToStreamMethod = saveFromKitToStreamMethod; } /** Write a single character. */ public void write(int c) throws IOException { try { doc.insertString(doc.getLength(), Character.toString((char) c), null); } catch (BadLocationException blex) { IOException ioex = new IOException(blex.getLocalizedMessage()); ioex.initCause(blex); throw ioex; } } /** * Write a portion of an array of characters. * * @param cbuf Array of characters * @param off Offset from which to start writing characters * @param len Number of characters to write * * @exception IOException If an I/O error occurs */ public void write(char cbuf[], int off, int len) throws IOException { if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } try { doc.insertString(doc.getLength(), new String(cbuf, off, len), null); } catch (BadLocationException blex) { IOException ioex = new IOException(blex.getLocalizedMessage()); ioex.initCause(blex); throw ioex; } } /** * Write a string. */ public void write(String str) throws IOException { try { doc.insertString(doc.getLength(), str, null); } catch (BadLocationException blex) { IOException ioex = new IOException(blex.getLocalizedMessage()); ioex.initCause(blex); throw ioex; } } public void flush() throws IOException {} /** * Close the stream, flushing it first. Once a stream has been closed, * further write() or flush() invocations will cause an IOException to be * thrown. Closing a previously-closed stream, however, has no effect. * * @exception IOException If an I/O error occurs */ public void close() throws IOException { if (closed) return ; if (saveFromKitToStreamMethod != null) { OutputStream out = fo.getOutputStream(foLock); try { saveFromKitToStreamMethod.invoke(editorSupport, new Object[] { doc, kit, out }); } catch (Exception e) { IOException ioex = new IOException(e.getLocalizedMessage()); ioex.initCause(e); throw ioex; } finally { try { out.close(); } catch (IOException ioex) {} foLock.releaseLock(); } } else { OutputStream out; if (file != null) { out = new FileOutputStream(file); } else { out = fo.getOutputStream(foLock); } try { kit.write(out, doc, 0, doc.getLength()); } catch (BadLocationException blex) { IOException ioex = new IOException(blex.getLocalizedMessage()); ioex.initCause(blex); throw ioex; } finally { out.close(); } } closed = true; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy