|
@@ -1,881 +0,0 @@
|
|
|
-/*
|
|
|
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
|
- *
|
|
|
- * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
|
- *
|
|
|
- * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
|
|
|
- * Other names may be trademarks of their respective owners.
|
|
|
- *
|
|
|
- * The contents of this file are subject to the terms of either the GNU
|
|
|
- * General Public License Version 2 only ("GPL") or the Common
|
|
|
- * Development and Distribution License("CDDL") (collectively, the
|
|
|
- * "License"). You may not use this file except in compliance with the
|
|
|
- * License. You can obtain a copy of the License at
|
|
|
- * http://www.netbeans.org/cddl-gplv2.html
|
|
|
- * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
|
|
|
- * specific language governing permissions and limitations under the
|
|
|
- * License. When distributing the software, include this License Header
|
|
|
- * Notice in each file and include the License file at
|
|
|
- * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
|
|
|
- * particular file as subject to the "Classpath" exception as provided
|
|
|
- * by Oracle in the GPL Version 2 section of the License file that
|
|
|
- * accompanied this code. If applicable, add the following below the
|
|
|
- * License Header, with the fields enclosed by brackets [] replaced by
|
|
|
- * your own identifying information:
|
|
|
- * "Portions Copyrighted [year] [name of copyright owner]"
|
|
|
- *
|
|
|
- * Contributor(s):
|
|
|
- *
|
|
|
- * The Original Software is NetBeans. The Initial Developer of the Original
|
|
|
- * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
|
|
|
- * Microsystems, Inc. All Rights Reserved.
|
|
|
- *
|
|
|
- * If you wish your version of this file to be governed by only the CDDL
|
|
|
- * or only the GPL Version 2, indicate your decision by adding
|
|
|
- * "[Contributor] elects to include this software in this distribution
|
|
|
- * under the [CDDL or GPL Version 2] license." If you do not indicate a
|
|
|
- * single choice of license, a recipient has the option to distribute
|
|
|
- * your version of this file under either the CDDL, the GPL Version 2 or
|
|
|
- * to extend the choice of license to its licensees as provided above.
|
|
|
- * However, if you add GPL Version 2 code and therefore, elected the GPL
|
|
|
- * Version 2 license, then the option applies only if the new code is
|
|
|
- * made subject to such option by the copyright holder.
|
|
|
- */
|
|
|
-
|
|
|
-package org.netbeans.upgrade.systemoptions;
|
|
|
-
|
|
|
-import java.io.BufferedInputStream;
|
|
|
-import java.io.ByteArrayInputStream;
|
|
|
-import java.io.ByteArrayOutputStream;
|
|
|
-import java.io.CharArrayWriter;
|
|
|
-import java.io.IOException;
|
|
|
-import java.io.InputStream;
|
|
|
-import java.io.InputStreamReader;
|
|
|
-import java.io.ObjectInput;
|
|
|
-import java.io.ObjectInputStream;
|
|
|
-import java.io.OutputStream;
|
|
|
-import java.io.PrintWriter;
|
|
|
-import java.io.Reader;
|
|
|
-import java.io.StringWriter;
|
|
|
-import java.lang.reflect.Method;
|
|
|
-import java.util.HashSet;
|
|
|
-import java.util.Set;
|
|
|
-import java.util.Stack;
|
|
|
-import org.openide.ErrorManager;
|
|
|
-import org.openide.filesystems.FileObject;
|
|
|
-//import org.openide.modules.SpecificationVersion;
|
|
|
-import org.openide.util.Lookup;
|
|
|
-import org.openide.util.SharedClassObject;
|
|
|
-import org.xml.sax.Attributes;
|
|
|
-import org.xml.sax.SAXException;
|
|
|
-import org.xml.sax.XMLReader;
|
|
|
-
|
|
|
-/**
|
|
|
- * Copy of XMLSettingsSupport.SettingsRecognizer by Jan Pokorsky
|
|
|
- */
|
|
|
-public class SettingsRecognizer extends org.xml.sax.helpers.DefaultHandler {
|
|
|
- public static final String INSTANCE_DTD_ID = "-//NetBeans//DTD Session settings 1.0//EN"; // NOI18N
|
|
|
- static final ErrorManager err = ErrorManager.getDefault().getInstance(SettingsRecognizer.class.getName()); // NOI18N
|
|
|
-
|
|
|
- private static final String ELM_SETTING = "settings"; // NOI18N
|
|
|
- private static final String ATR_SETTING_VERSION = "version"; // NOI18N
|
|
|
-
|
|
|
- private static final String ELM_MODULE = "module"; // NOI18N
|
|
|
- private static final String ATR_MODULE_NAME = "name"; // NOI18N
|
|
|
- private static final String ATR_MODULE_SPEC = "spec"; // NOI18N
|
|
|
- private static final String ATR_MODULE_IMPL = "impl"; // NOI18N
|
|
|
-
|
|
|
- private static final String ELM_INSTANCE = "instance"; // NOI18N
|
|
|
- private static final String ATR_INSTANCE_CLASS = "class"; // NOI18N
|
|
|
- private static final String ATR_INSTANCE_METHOD = "method"; // NOI18N
|
|
|
-
|
|
|
- private static final String ELM_INSTANCEOF = "instanceof"; // NOI18N
|
|
|
- private static final String ATR_INSTANCEOF_CLASS = "class"; // NOI18N
|
|
|
-
|
|
|
- private static final String ELM_SERIALDATA = "serialdata"; // NOI18N
|
|
|
- private static final String ATR_SERIALDATA_CLASS = "class"; // NOI18N
|
|
|
-
|
|
|
- //private static final String VERSION = "1.0"; // NOI18N
|
|
|
-
|
|
|
- private boolean header;
|
|
|
- private Stack<String> stack;
|
|
|
-
|
|
|
- private String version;
|
|
|
- private String instanceClass;
|
|
|
- private String instanceMethod;
|
|
|
- private Set<String> instanceOf = new HashSet<String>();
|
|
|
-
|
|
|
- private byte[] serialdata;
|
|
|
- private CharArrayWriter chaos = null;
|
|
|
-
|
|
|
- private String codeName;
|
|
|
- private String codeNameBase;
|
|
|
- private int codeNameRelease;
|
|
|
- //private SpecificationVersion moduleSpec;
|
|
|
- private String moduleImpl;
|
|
|
- /** file with stored settings */
|
|
|
- private final FileObject source;
|
|
|
-
|
|
|
- /** XML handler recognizing settings.
|
|
|
- * @param header if true read just elements instanceof, module and attr classname.
|
|
|
- * @param source file with stored settings
|
|
|
- */
|
|
|
- public SettingsRecognizer(boolean header, FileObject source) {
|
|
|
- this.header = header;
|
|
|
- this.source = source;
|
|
|
- }
|
|
|
-
|
|
|
- public boolean isAllRead() {
|
|
|
- return !header;
|
|
|
- }
|
|
|
-
|
|
|
- public void setAllRead(boolean all) {
|
|
|
- if (!header) return;
|
|
|
- header = all;
|
|
|
- }
|
|
|
-
|
|
|
- public String getSettingsVerison() {
|
|
|
- return version;
|
|
|
- }
|
|
|
-
|
|
|
- public String getCodeName() {
|
|
|
- return codeName;
|
|
|
- }
|
|
|
-
|
|
|
- public String getCodeNameBase() {
|
|
|
- return codeNameBase;
|
|
|
- }
|
|
|
-
|
|
|
- public int getCodeNameRelease() {
|
|
|
- return codeNameRelease;
|
|
|
- }
|
|
|
-
|
|
|
- /*public SpecificationVersion getSpecificationVersion() {
|
|
|
- return moduleSpec;
|
|
|
- }*/
|
|
|
-
|
|
|
- public String getModuleImpl() {
|
|
|
- return moduleImpl;
|
|
|
- }
|
|
|
-
|
|
|
- /** Set of names. */
|
|
|
- public Set getInstanceOf() {
|
|
|
- return instanceOf;
|
|
|
- }
|
|
|
-
|
|
|
- /** Method attribute from the instance element. */
|
|
|
- public String getMethodName() {
|
|
|
- return instanceMethod;
|
|
|
- }
|
|
|
-
|
|
|
- /** Serialized instance, can be null. */
|
|
|
- public InputStream getSerializedInstance() {
|
|
|
- if (serialdata == null) return null;
|
|
|
- return new ByteArrayInputStream(serialdata);
|
|
|
- }
|
|
|
-
|
|
|
- public org.xml.sax.InputSource resolveEntity(String publicId, String systemId)
|
|
|
- throws SAXException {
|
|
|
- if (INSTANCE_DTD_ID.equals(publicId)) {
|
|
|
- return new org.xml.sax.InputSource(new ByteArrayInputStream(new byte[0]));
|
|
|
- } else {
|
|
|
- return null; // i.e. follow advice of systemID
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void characters(char[] values, int start, int length) throws SAXException {
|
|
|
- if (header) return;
|
|
|
- String element = stack.peek();
|
|
|
- if (ELM_SERIALDATA.equals(element)) {
|
|
|
- // [PENDING] should be optimized to do not read all chars to memory
|
|
|
- if (chaos == null) chaos = new CharArrayWriter(length);
|
|
|
- chaos.write(values, start, length);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void startElement(String uri, String localName, String qName, Attributes attribs) throws SAXException {
|
|
|
- stack.push(qName);
|
|
|
- if (ELM_SETTING.equals(qName)) {
|
|
|
- version = attribs.getValue(ATR_SETTING_VERSION);
|
|
|
- } else if (ELM_MODULE.equals(qName)) {
|
|
|
- codeName = attribs.getValue(ATR_MODULE_NAME);
|
|
|
- resolveModuleElm(codeName);
|
|
|
- moduleImpl = attribs.getValue(ATR_MODULE_IMPL);
|
|
|
- try {
|
|
|
- String spec = attribs.getValue(ATR_MODULE_SPEC);
|
|
|
- //moduleSpec = spec == null ? null : new SpecificationVersion(spec);
|
|
|
- } catch (NumberFormatException nfe) {
|
|
|
- throw new SAXException(nfe);
|
|
|
- }
|
|
|
- } else if (ELM_INSTANCEOF.equals(qName)) {
|
|
|
- instanceOf.add(org.openide.util.Utilities.translate(
|
|
|
- attribs.getValue(ATR_INSTANCEOF_CLASS)));
|
|
|
- } else if (ELM_INSTANCE.equals(qName)) {
|
|
|
- instanceClass = attribs.getValue(ATR_INSTANCE_CLASS);
|
|
|
- if (instanceClass == null) {
|
|
|
- System.err.println("Hint: NPE is caused by broken settings file: " + source ); // NOI18N
|
|
|
- }
|
|
|
- instanceClass = org.openide.util.Utilities.translate(instanceClass);
|
|
|
- instanceMethod = attribs.getValue(ATR_INSTANCE_METHOD);
|
|
|
- } else if (ELM_SERIALDATA.equals(qName)) {
|
|
|
- instanceClass = attribs.getValue(ATR_SERIALDATA_CLASS);
|
|
|
- instanceClass = org.openide.util.Utilities.translate(instanceClass);
|
|
|
- if (header) throw new StopSAXException();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /** reade codenamebase + revision */
|
|
|
- private void resolveModuleElm(String codeName) {
|
|
|
- if (codeName != null) {
|
|
|
- int slash = codeName.indexOf("/"); // NOI18N
|
|
|
- if (slash == -1) {
|
|
|
- codeNameBase = codeName;
|
|
|
- codeNameRelease = -1;
|
|
|
- } else {
|
|
|
- codeNameBase = codeName.substring(0, slash);
|
|
|
- try {
|
|
|
- codeNameRelease = Integer.parseInt(codeName.substring(slash + 1));
|
|
|
- } catch (NumberFormatException ex) {
|
|
|
- ErrorManager emgr = ErrorManager.getDefault();
|
|
|
- emgr.annotate(ex, "Content: \n" + getFileContent(source)); // NOI18N
|
|
|
- emgr.annotate(ex, "Source: " + source); // NOI18N
|
|
|
- emgr.notify(ErrorManager.INFORMATIONAL, ex);
|
|
|
- codeNameRelease = -1;
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- codeNameBase = null;
|
|
|
- codeNameRelease = -1;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void endElement(String uri, String localName, String qName) throws SAXException {
|
|
|
- //if (header) return;
|
|
|
- String element = stack.pop();
|
|
|
- if (ELM_SERIALDATA.equals(element)) {
|
|
|
- if (chaos != null) {
|
|
|
- ByteArrayOutputStream baos = new ByteArrayOutputStream(chaos.size() >> 1);
|
|
|
- try {
|
|
|
- chars2Bytes(baos, chaos.toCharArray(), 0, chaos.size());
|
|
|
- serialdata = baos.toByteArray();
|
|
|
- } catch (IOException ex) {
|
|
|
- ErrorManager.getDefault().notify(
|
|
|
- ErrorManager.WARNING, ex
|
|
|
- );
|
|
|
- } finally {
|
|
|
- chaos = null; // don't keep the info twice
|
|
|
- try {
|
|
|
- baos.close();
|
|
|
- } catch (IOException ex) {
|
|
|
- // doesn't matter
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /** Tries to deserialize instance saved in is.
|
|
|
- * @param is stream with stored object, can be null
|
|
|
- * @return deserialized object or null
|
|
|
- */
|
|
|
- private Object readSerial(InputStream is) throws IOException, ClassNotFoundException {
|
|
|
- if (is == null) return null;
|
|
|
- try {
|
|
|
- ObjectInput oi = new ObjectInputStream(is);
|
|
|
- try {
|
|
|
- Object o = oi.readObject();
|
|
|
- return o;
|
|
|
- } finally {
|
|
|
- oi.close();
|
|
|
- }
|
|
|
- } catch (IOException ex) {
|
|
|
- ErrorManager emgr = ErrorManager.getDefault();
|
|
|
- emgr.annotate(ex, "Content: \n" + getFileContent(source)); // NOI18N
|
|
|
- emgr.annotate(ex, "Source: " + source); // NOI18N
|
|
|
- emgr.annotate(ex, "Cannot read class: " + instanceClass); // NOI18N
|
|
|
- throw ex;
|
|
|
- } catch (ClassNotFoundException ex) {
|
|
|
- ErrorManager emgr = ErrorManager.getDefault();
|
|
|
- emgr.annotate(ex, "Content: \n" + getFileContent(source)); // NOI18N
|
|
|
- emgr.annotate(ex, "Source: " + source); // NOI18N
|
|
|
- throw ex;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /** Create an instance.
|
|
|
- * @return the instance of type {@link #instanceClass}
|
|
|
- * @exception IOException if an I/O error occured
|
|
|
- * @exception ClassNotFoundException if a class was not found
|
|
|
- */
|
|
|
- public Object instanceCreate() throws java.io.IOException, ClassNotFoundException {
|
|
|
- Object inst = null;
|
|
|
-
|
|
|
- // deserialize
|
|
|
- inst = readSerial(getSerializedInstance());
|
|
|
-
|
|
|
- // default instance
|
|
|
- if (inst == null) {
|
|
|
- if (instanceMethod != null) {
|
|
|
- inst = createFromMethod(instanceClass, instanceMethod);
|
|
|
- } else {
|
|
|
- // use default constructor
|
|
|
- Class<?> clazz = instanceClass();
|
|
|
- if (SharedClassObject.class.isAssignableFrom(clazz)) {
|
|
|
- inst = SharedClassObject.findObject(clazz.asSubclass(SharedClassObject.class), false);
|
|
|
- if (null != inst) {
|
|
|
- // instance already exists -> reset it to defaults
|
|
|
- try {
|
|
|
- Method method = SharedClassObject.class.getDeclaredMethod("reset", new Class[0]); // NOI18N
|
|
|
- method.setAccessible(true);
|
|
|
- method.invoke(inst, new Object[0]);
|
|
|
- } catch (Exception e) {
|
|
|
- ErrorManager.getDefault().notify(e);
|
|
|
- }
|
|
|
- } else {
|
|
|
- inst = SharedClassObject.findObject(clazz.asSubclass(SharedClassObject.class), true);
|
|
|
- }
|
|
|
- } else {
|
|
|
- try {
|
|
|
- inst = clazz.newInstance();
|
|
|
- } catch (Exception ex) {
|
|
|
- IOException ioe = new IOException();
|
|
|
- ErrorManager emgr = ErrorManager.getDefault();
|
|
|
- emgr.annotate(ioe, ex);
|
|
|
- emgr.annotate(ioe, "Content: \n" + getFileContent(source)); // NOI18N
|
|
|
- emgr.annotate(ioe, "Class: " + clazz); // NOI18N
|
|
|
- emgr.annotate(ioe, "Source: " + source); // NOI18N
|
|
|
- throw ioe;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return inst;
|
|
|
- }
|
|
|
-
|
|
|
- /** Get file content as String. If some exception occures its stack trace
|
|
|
- * is return instead. */
|
|
|
- private static String getFileContent(FileObject fo) {
|
|
|
- try {
|
|
|
- InputStreamReader isr = new InputStreamReader(fo.getInputStream());
|
|
|
- char[] cbuf = new char[1024];
|
|
|
- int length;
|
|
|
- StringBuffer sbuf = new StringBuffer(1024);
|
|
|
- while (true) {
|
|
|
- length = isr.read(cbuf);
|
|
|
- if (length > 0) {
|
|
|
- sbuf.append(cbuf, 0, length);
|
|
|
- } else {
|
|
|
- return sbuf.toString();
|
|
|
- }
|
|
|
- }
|
|
|
- } catch (Exception ex) {
|
|
|
- StringWriter sw = new StringWriter();
|
|
|
- ex.printStackTrace(new PrintWriter(sw));
|
|
|
- return sw.toString();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /** create instance by invoking class method */
|
|
|
- private Object createFromMethod(String srcClazz, String srcMethod)
|
|
|
- throws ClassNotFoundException, IOException {
|
|
|
- int dotIndex = instanceMethod.lastIndexOf('.');
|
|
|
- String targetClass;
|
|
|
- String targetMethod;
|
|
|
- if (dotIndex > 0) {
|
|
|
- targetClass = srcMethod.substring(0, dotIndex);
|
|
|
- targetMethod = srcMethod.substring(dotIndex + 1);
|
|
|
- } else {
|
|
|
- targetClass = srcClazz;
|
|
|
- targetMethod = srcMethod;
|
|
|
- }
|
|
|
-
|
|
|
- Class<?> clazz = loadClass(targetClass);
|
|
|
-
|
|
|
- try {
|
|
|
- Object instance;
|
|
|
- try {
|
|
|
- Method method = clazz.getMethod(targetMethod, new Class[]{FileObject.class});
|
|
|
- method.setAccessible(true);
|
|
|
- instance = method.invoke(null, source);
|
|
|
- } catch (NoSuchMethodException ex) {
|
|
|
- Method method = clazz.getMethod(targetMethod);
|
|
|
- method.setAccessible(true);
|
|
|
- instance = method.invoke(null, new Object[0]);
|
|
|
- }
|
|
|
- if (instance == null) {
|
|
|
- // Strictly verboten. Cf. BT #4827173 for example.
|
|
|
- throw new IOException("Null return not permitted from " + targetClass + "." + targetMethod); // NOI18N
|
|
|
- }
|
|
|
- return instance;
|
|
|
- } catch (Exception ex) {
|
|
|
- IOException ioe = new IOException("Error reading " + source + ": " + ex); // NOI18N
|
|
|
- ErrorManager emgr = ErrorManager.getDefault();
|
|
|
- emgr.annotate(ioe, "Class: " + clazz); // NOI18N
|
|
|
- emgr.annotate(ioe, "Method: " + srcMethod); // NOI18N
|
|
|
- emgr.annotate(ioe, ex);
|
|
|
- emgr.annotate(ioe, "Content:\n" + getFileContent(source)); // NOI18N
|
|
|
- throw ioe;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /** The representation type that may be created as instances.
|
|
|
- * Can be used to test whether the instance is of an appropriate
|
|
|
- * class without actually creating it.
|
|
|
- *
|
|
|
- * @return the representation class of the instance
|
|
|
- * @exception IOException if an I/O error occurred
|
|
|
- * @exception ClassNotFoundException if a class was not found
|
|
|
- */
|
|
|
- public Class instanceClass() throws java.io.IOException, ClassNotFoundException {
|
|
|
- if (instanceClass == null) {
|
|
|
- throw new ClassNotFoundException(source +
|
|
|
- ": missing 'class' attribute in 'instance' element"); //NOI18N
|
|
|
- }
|
|
|
-
|
|
|
- return loadClass(instanceClass);
|
|
|
- }
|
|
|
-
|
|
|
- /** try to load class from system and current classloader. */
|
|
|
- private Class loadClass(String clazz) throws ClassNotFoundException {
|
|
|
- return ((ClassLoader)Lookup.getDefault().lookup(ClassLoader.class)).loadClass(clazz);
|
|
|
- }
|
|
|
-
|
|
|
- /** get class name of instance */
|
|
|
- public String instanceName() {
|
|
|
- if (instanceClass == null) {
|
|
|
- return ""; // NOI18N
|
|
|
- } else {
|
|
|
- return instanceClass;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private int tr(char c) {
|
|
|
- if (c >= '0' && c <= '9') return c - '0';
|
|
|
- if (c >= 'A' && c <= 'F') return c - 'A' + 10;
|
|
|
- if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- /** Converts array of chars to array of bytes. All whitespaces and
|
|
|
- * unknown chars are skipped.
|
|
|
- */
|
|
|
- private void chars2Bytes(OutputStream os, char[] chars, int off, int length)
|
|
|
- throws IOException {
|
|
|
- byte rbyte;
|
|
|
- int read;
|
|
|
-
|
|
|
- for (int i = off; i < length; ) {
|
|
|
- read = tr(chars[i++]);
|
|
|
- if (read >= 0) rbyte = (byte) (read << 4); // * 16;
|
|
|
- else continue;
|
|
|
-
|
|
|
- while (i < length) {
|
|
|
- read = tr(chars[i++]);
|
|
|
- if (read >= 0) {
|
|
|
- rbyte += (byte) read;
|
|
|
- os.write(rbyte);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /** Parse settings file. */
|
|
|
- public void parse() throws IOException {
|
|
|
- InputStream in = null;
|
|
|
-
|
|
|
- try {
|
|
|
- if (header) {
|
|
|
- if (err.isLoggable(err.INFORMATIONAL) && source.getSize() < 12000) {
|
|
|
- // log the content of the stream
|
|
|
- byte[] arr = new byte[(int)source.getSize()];
|
|
|
- InputStream temp = source.getInputStream();
|
|
|
- int len = temp.read(arr);
|
|
|
- if (len != arr.length) {
|
|
|
- throw new IOException("Could not read " + arr.length + " bytes from " + source + " just " + len); // NOI18N
|
|
|
- }
|
|
|
-
|
|
|
- err.log("Parsing:" + new String(arr));
|
|
|
-
|
|
|
- temp.close();
|
|
|
-
|
|
|
- in = new ByteArrayInputStream(arr);
|
|
|
- } else {
|
|
|
- in = new BufferedInputStream(source.getInputStream());
|
|
|
- }
|
|
|
- Set<String> iofs = quickParse(new BufferedInputStream(in));
|
|
|
- if (iofs != null) {
|
|
|
- instanceOf = iofs;
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- } catch (IOException ioe) {
|
|
|
- // ignore - fallback to XML parser follows
|
|
|
- } finally {
|
|
|
- if (in != null) in.close();
|
|
|
- }
|
|
|
- stack = new Stack<String>();
|
|
|
- try {
|
|
|
- in = source.getInputStream();
|
|
|
- XMLReader reader = org.openide.xml.XMLUtil.createXMLReader();
|
|
|
- reader.setContentHandler(this);
|
|
|
- reader.setErrorHandler(this);
|
|
|
- reader.setEntityResolver(this);
|
|
|
- reader.parse(new org.xml.sax.InputSource(new BufferedInputStream(in)));
|
|
|
- } catch (SettingsRecognizer.StopSAXException ex) {
|
|
|
- // Ok, header is read
|
|
|
- } catch (SAXException ex) {
|
|
|
- IOException ioe = new IOException(source.toString()); // NOI18N
|
|
|
- ErrorManager emgr = ErrorManager.getDefault();
|
|
|
- emgr.annotate(ioe, ex);
|
|
|
- if (ex.getException() != null) {
|
|
|
- emgr.annotate(ioe, ex.getException());
|
|
|
- }
|
|
|
- emgr.annotate(ioe, "Content: \n" + getFileContent(source)); // NOI18N
|
|
|
- emgr.annotate(ioe, "Source: " + source); // NOI18N
|
|
|
- throw ioe;
|
|
|
- } finally {
|
|
|
- stack = null;
|
|
|
- try {
|
|
|
- if (in != null) {
|
|
|
- in.close();
|
|
|
- }
|
|
|
- } catch (IOException ex) {
|
|
|
- // ignore already closed
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /** Parse setting from source. */
|
|
|
- public void parse(Reader source) throws IOException {
|
|
|
- stack = new Stack<String>();
|
|
|
-
|
|
|
- try {
|
|
|
- XMLReader reader = org.openide.xml.XMLUtil.createXMLReader();
|
|
|
- reader.setContentHandler(this);
|
|
|
- reader.setErrorHandler(this);
|
|
|
- reader.setEntityResolver(this);
|
|
|
- reader.parse(new org.xml.sax.InputSource(source));
|
|
|
- } catch (SettingsRecognizer.StopSAXException ex) {
|
|
|
- // Ok, header is read
|
|
|
- } catch (SAXException ex) {
|
|
|
- IOException ioe = new IOException(source.toString()); // NOI18N
|
|
|
- ErrorManager emgr = ErrorManager.getDefault();
|
|
|
- emgr.annotate(ioe, ex);
|
|
|
- if (ex.getException() != null) {
|
|
|
- emgr.annotate(ioe, ex.getException());
|
|
|
- }
|
|
|
- throw ioe;
|
|
|
- } finally {
|
|
|
- stack = null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Encoding irrelevant for these getBytes() calls: all are ASCII...
|
|
|
- // (unless someone has their system encoding set to UCS-16!)
|
|
|
- private static final byte[] MODULE_SETTINGS_INTRO = "<?xml version=\"1.0\"?> <!DOCTYPE settings PUBLIC \"-//NetBeans//DTD Session settings 1.0//EN\" \"http://www.netbeans.org/dtds/sessionsettings-1_0.dtd\"> <settings version=\"".getBytes(); // NOI18N
|
|
|
- private static final byte[] MODULE_SETTINGS_INTRO_END = "> <".getBytes(); // NOI18N
|
|
|
- private static final byte[] MODULE_SETTINGS_MODULE_NAME = "odule name=\"".getBytes(); // NOI18N
|
|
|
- private static final byte[] MODULE_SETTINGS_MODULE_SPEC = "spec=\"".getBytes(); // NOI18N
|
|
|
- private static final byte[] MODULE_SETTINGS_MODULE_IMPL = "impl=\"".getBytes(); // NOI18N
|
|
|
- private static final byte[] MODULE_SETTINGS_TAG_END = "> <".getBytes(); // NOI18N
|
|
|
- private static final byte[] MODULE_SETTINGS_INSTANCE = "nstance".getBytes(); // NOI18N
|
|
|
- private static final byte[] MODULE_SETTINGS_INSTANCE_CLZ = "class=\"".getBytes(); // NOI18N
|
|
|
- private static final byte[] MODULE_SETTINGS_INSTANCE_MTD = "method=\"".getBytes(); // NOI18N
|
|
|
- private static final byte[] MODULE_SETTINGS_OF = "f class=\"".getBytes(); // NOI18N
|
|
|
- private static final byte[] MODULE_SETTINGS_SERIAL = "erialdata class=\"".getBytes(); // NOI18N
|
|
|
- private static final byte[] MODULE_SETTINGS_END = "settings>".getBytes(); // NOI18N
|
|
|
-
|
|
|
- /** Attempts to read the stream in the same way as SAX parser but avoids using it.
|
|
|
- * If it does not manage to parse it this way, it returns null, in which case
|
|
|
- * you have to use a real parser.
|
|
|
- * @see "#36718"
|
|
|
- */
|
|
|
- private Set<String> quickParse(InputStream is) throws IOException {
|
|
|
- Set<String> iofs = new HashSet<String>(); // <String>
|
|
|
-
|
|
|
- if (!expect(is, MODULE_SETTINGS_INTRO)) {
|
|
|
- err.log("Could not read intro "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- version = readTo(is, '"');
|
|
|
- if (version == null) {
|
|
|
- err.log("Could not read version "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- if (!expect(is, MODULE_SETTINGS_INTRO_END)) {
|
|
|
- err.log("Could not read stuff after cnb "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- // Now we have (module?, instanceof*, (instance | serialdata)).
|
|
|
- int c;
|
|
|
- PARSE:
|
|
|
- while (true) {
|
|
|
- c = is.read();
|
|
|
- switch (c) {
|
|
|
- case 'm':
|
|
|
- // <module />
|
|
|
- if (!expect(is, MODULE_SETTINGS_MODULE_NAME)) {
|
|
|
- err.log("Could not read up to <module name=\" "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- String codeName = readTo(is, '"');
|
|
|
- if (codeName == null) {
|
|
|
- err.log("Could not read module name value "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- codeName = codeName.intern();
|
|
|
- resolveModuleElm(codeName);
|
|
|
- c = is.read();
|
|
|
- if (c == '/') {
|
|
|
- if (!expect(is, MODULE_SETTINGS_TAG_END)) {
|
|
|
- err.log("Could not read up to end of module tag "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- break;
|
|
|
- } else if (c != ' ') {
|
|
|
- err.log("Could not space after module name "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- // <module spec/>
|
|
|
- if (!expect(is, MODULE_SETTINGS_MODULE_SPEC)) {
|
|
|
- err.log("Could not read up to spec=\" "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- String mspec = readTo(is, '"');
|
|
|
- if (mspec == null) {
|
|
|
- err.log("Could not read module spec value "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- try {
|
|
|
- //moduleSpec = new SpecificationVersion(mspec);
|
|
|
- } catch (NumberFormatException nfe) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- c = is.read();
|
|
|
- if (c == '/') {
|
|
|
- if (!expect(is, MODULE_SETTINGS_TAG_END)) {
|
|
|
- err.log("Could not read up to end of <module name spec/> tag "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- break;
|
|
|
- } else if (c != ' ') {
|
|
|
- err.log("Could not read space after module name "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- // <module impl/>
|
|
|
- if (!expect(is, MODULE_SETTINGS_MODULE_IMPL)) {
|
|
|
- err.log("Could not read up to impl=\" "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- moduleImpl = readTo(is, '"');
|
|
|
- if (moduleImpl == null) {
|
|
|
- err.log("Could not read module impl value "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- moduleImpl = moduleImpl.intern();
|
|
|
- // /> >
|
|
|
- if (!expect(is, MODULE_SETTINGS_TAG_END)) {
|
|
|
- err.log("Could not read up to /> < "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- break;
|
|
|
- case 'i':
|
|
|
- // <instanceof> or <instance>
|
|
|
- if (!expect(is, MODULE_SETTINGS_INSTANCE)) {
|
|
|
- err.log("Could not read up to instance "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- // Now we need to check which one
|
|
|
- c = is.read();
|
|
|
- if (c == 'o') {
|
|
|
- if (!expect(is, MODULE_SETTINGS_OF)) {
|
|
|
- err.log("Could not read up to instance"); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- String iof = readTo(is, '"');
|
|
|
- if (iof == null) {
|
|
|
- err.log("Could not read instanceof value "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- iof = org.openide.util.Utilities.translate(iof).intern();
|
|
|
- iofs.add(iof);
|
|
|
- if (is.read() != '/') {
|
|
|
- err.log("No / at end of <instanceof> " + iof+" "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- if (!expect(is, MODULE_SETTINGS_TAG_END)) {
|
|
|
- err.log("Could not read up to next tag after <instanceof> " + iof+" "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- } else if (c == ' ') {
|
|
|
- // read class and optional method
|
|
|
- if (!expect(is, MODULE_SETTINGS_INSTANCE_CLZ)) {
|
|
|
- err.log("Could not read up to class=\" "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- instanceClass = readTo(is, '"');
|
|
|
- if (instanceClass == null) {
|
|
|
- err.log("Could not read instance class value "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- instanceClass = org.openide.util.Utilities.translate(instanceClass).intern();
|
|
|
- c = is.read();
|
|
|
- if (c == '/') {
|
|
|
- if (!expect(is, MODULE_SETTINGS_TAG_END)) {
|
|
|
- err.log("Could not read up to end of instance tag "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- break;
|
|
|
- } else if (c != ' ') {
|
|
|
- err.log("Could not space after instance class "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- // <instance method/>
|
|
|
- if (!expect(is, MODULE_SETTINGS_INSTANCE_MTD)) {
|
|
|
- err.log("Could not read up to method=\" "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- instanceMethod = readTo(is, '"');
|
|
|
- if (instanceMethod == null) {
|
|
|
- err.log("Could not read method value "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- instanceMethod = instanceMethod.intern();
|
|
|
- c = is.read();
|
|
|
- if (c == '/') {
|
|
|
- if (!expect(is, MODULE_SETTINGS_TAG_END)) {
|
|
|
- err.log("Could not read up to end of instance tag "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- err.log("Strange stuff after method attribute "+source); // NOI18N
|
|
|
- return null;
|
|
|
- } else {
|
|
|
- err.log("Could not read after to instance "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- break;
|
|
|
- case 's':
|
|
|
- // <serialdata class
|
|
|
- if (!expect(is, MODULE_SETTINGS_SERIAL)) {
|
|
|
- err.log("Could not read up to <serialdata class=\" "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- instanceClass = readTo(is, '"');
|
|
|
- if (instanceClass == null) {
|
|
|
- err.log("Could not read serialdata class value "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- instanceClass = org.openide.util.Utilities.translate(instanceClass).intern();
|
|
|
- // here we are complete for header, otherwise we would need to go through serialdata stream
|
|
|
- c = is.read();
|
|
|
- if (c != '>') {
|
|
|
- err.log("Could not read up to end of serialdata tag "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- break PARSE;
|
|
|
- case '/':
|
|
|
- // </settings
|
|
|
- // XXX do not read further is neader is set
|
|
|
- if (!expect(is, MODULE_SETTINGS_END)) {
|
|
|
- err.log("Could not read up to end of settings tag "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- break PARSE;
|
|
|
- default:
|
|
|
- err.log("Strange stuff after <" + (char)c+" "+source); // NOI18N
|
|
|
- return null;
|
|
|
- }
|
|
|
- }
|
|
|
- if (instanceClass != null && !iofs.isEmpty()) {
|
|
|
- return iofs;
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- /** Read some stuff from a stream and skip over it.
|
|
|
- * Newlines conventions and whitespaces are normalized to one space.
|
|
|
- * @return true upon success, false if stream contained something else
|
|
|
- */
|
|
|
- private boolean expect(InputStream is, byte[] stuff) throws IOException {
|
|
|
- int len = stuff.length;
|
|
|
- boolean inWhitespace = false;
|
|
|
- for (int i = 0; i < len; ) {
|
|
|
- int c = is.read();
|
|
|
- if (c == 10 || c == 13 || c == ' ' || c == '\t') {
|
|
|
- // Normalize: s/[\t \r\n]+/\n/g
|
|
|
- if (inWhitespace) {
|
|
|
- continue;
|
|
|
- } else {
|
|
|
- inWhitespace = true;
|
|
|
- c = ' ';
|
|
|
- }
|
|
|
- } else {
|
|
|
- inWhitespace = false;
|
|
|
- }
|
|
|
- if (c != stuff[i++]) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
- if (stuff[len - 1] == 10) {
|
|
|
- // Expecting something ending in a \n - so we have to
|
|
|
- // read any further \r or \n and discard.
|
|
|
- if (!is.markSupported()) throw new IOException("Mark not supported"); // NOI18N
|
|
|
- is.mark(1);
|
|
|
- int c = is.read();
|
|
|
- if (c != -1 && c != 10 && c != 13) {
|
|
|
- // Got some non-newline character, push it back!
|
|
|
- is.reset();
|
|
|
- }
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
- /** Read a maximal string until delim is encountered (which will be removed from stream).
|
|
|
- * This impl reads only ASCII, for speed.
|
|
|
- * Newline conventions are normalized to Unix \n.
|
|
|
- * @return the read string, or null if the delim is not encountered before EOF.
|
|
|
- */
|
|
|
- private String readTo(InputStream is, char delim) throws IOException {
|
|
|
- if (delim == 10) {
|
|
|
- // Not implemented - stream might have "foo\r\n" and we would
|
|
|
- // return "foo" and leave "\n" in the stream.
|
|
|
- throw new IOException("Not implemented"); // NOI18N
|
|
|
- }
|
|
|
- CharArrayWriter caw = new CharArrayWriter(100);
|
|
|
- boolean inNewline = false;
|
|
|
- while (true) {
|
|
|
- int c = is.read();
|
|
|
- if (c == -1) return null;
|
|
|
- if (c > 126) return null;
|
|
|
- if (c == 10 || c == 13) {
|
|
|
- // Normalize: s/[\r\n]+/\n/g
|
|
|
- if (inNewline) {
|
|
|
- continue;
|
|
|
- } else {
|
|
|
- inNewline = true;
|
|
|
- c = 10;
|
|
|
- }
|
|
|
- } else if (c < 32 && c != 9) {
|
|
|
- // Random control character!
|
|
|
- return null;
|
|
|
- } else {
|
|
|
- inNewline = false;
|
|
|
- }
|
|
|
- if (c == delim) {
|
|
|
- return caw.toString();
|
|
|
- } else {
|
|
|
- caw.write(c);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- final static class StopSAXException extends SAXException {
|
|
|
- public StopSAXException() {
|
|
|
- super("Parser stopped"); // NOI18N
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-}
|