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

org.netbeans.modules.properties.PropertiesDataLoader Maven / Gradle / Ivy

There is a newer version: RELEASE230
Show 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.properties;

import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import org.openide.filesystems.FileObject;
import org.openide.loaders.ExtensionList;
import org.openide.loaders.MultiDataObject;
import org.openide.loaders.MultiFileLoader;
import org.openide.util.NbBundle;
import org.openide.util.io.SafeException;

/**
 * Data loader which recognizes properties files.
 * This class is final only for performance reasons,
 * can be unfinaled if desired.
 *
 * @author Ian Formanek, Petr Jiricka
 * @author Marian Petras
 */
public final class PropertiesDataLoader extends MultiFileLoader {

    /** Extension for properties files. */
    static final String PROPERTIES_EXTENSION = "properties"; // NOI18N

    /** Properties MIME type*/
    static final String PROPERTIES_MIME_TYPE = "text/x-properties"; //NOI18N

    /** Character used to separate parts of bundle properties file name */
    public static final char PRB_SEPARATOR_CHAR = '_';

    /** Generated serial version UID. */
    static final long serialVersionUID =4384899552891479449L;
    
    /** name of property with extensions */
    public static final String PROP_EXTENSIONS = "extensions"; // NOI18N
    
    /** */
    private Reference encodingRef;
    
    /** */
    private static Set knownLanguages;
    /** */
    private static Set knownCountries;

    /** */
    private static boolean nestedView = false;

    /** Creates new PropertiesDataLoader. */
    public PropertiesDataLoader() {
        super("org.netbeans.modules.properties.PropertiesDataObject"); // NOI18N
        
        // Set extentions. Due performance reasons do it here instead in initialize method.
        // During startup it's in findPrimaryFile method called getExtensions method. If the 
        // extentions list was not set in constructor the initialize method would be called
        // during startup, but we want to avoid the initialize call since we don't need
        // actions and display name initialized during startup time.
        ExtensionList extList = new ExtensionList();
        extList.addExtension(PROPERTIES_EXTENSION);
        // Add .impl for CORBA module.
        extList.addExtension("impl"); // NOI18N
        setExtensions(extList);
    }

    /**
     */
    PropertiesEncoding getEncoding() {
        PropertiesEncoding encoding;
        if ((encodingRef == null) || ((encoding = encodingRef.get()) == null)) {
            encoding = new PropertiesEncoding();
            encodingRef = new SoftReference(encoding);
        }
        return encoding;
    }
    
    /** */
    @Override
    protected String defaultDisplayName() {
        return NbBundle.getMessage(PropertiesDataLoader.class,
                                   "PROP_PropertiesLoader_Name");       //NOI18N
    }
    
    /**
     * This methods uses the layer action context so it returns
     * a non-null value.
     *
     * @return  name of the context on layer files to read/write actions to
     */
    @Override
    protected String actionsContext () {
        return "Loaders/text/x-properties/Actions/";                    //NOI18N
    }
    
    /**
     * @return  PropertiesDataObject for the specified
     *          FileObject
     */
    protected MultiDataObject createMultiObject(final FileObject fo)
            throws IOException {
        return new PropertiesDataObject(fo, this);
    }

    /** */
    protected FileObject findPrimaryFile (FileObject fo) {
        if (fo.isFolder()) {
            return null;
        }
        if (fo.getExt().equalsIgnoreCase(PROPERTIES_EXTENSION)) {
            
            /*
             * returns a file whose name is the shortest valid prefix
             * corresponding to an existing file
             */
            String fName = fo.getName();
            if (nestedView) {
                int index = fName.indexOf(PRB_SEPARATOR_CHAR);
                while (index != -1) {
                    FileObject candidate = fo.getParent().getFileObject(
                            fName.substring(0, index), fo.getExt());
                    if (candidate != null && isValidLocaleSuffix(fName.substring(index))) {
                        return candidate;
                    }
                    index = fName.indexOf(PRB_SEPARATOR_CHAR, index + 1);
                }
            }
            return fo;
        } else if (getExtensions().isRegistered(fo)) {
            return fo;
        } else if (PROPERTIES_MIME_TYPE.equalsIgnoreCase(fo.getMIMEType(PROPERTIES_MIME_TYPE))) {
            return fo;
        } else {
            return null;
        }
    }

    private static boolean isValidLocaleSuffix(String s) {
        // first char is _
        int n = s.length();
        String s1;
        // check first suffix - language (two chars)
        if (n == 3 || (n > 3 && s.charAt(3) == PRB_SEPARATOR_CHAR)) {
            s1 = s.substring(1, 3).toLowerCase();
            // language must be followed by a valid country suffix or no suffix
        } else {
            return false;
        }
        // check second suffix - country (two chars)
        String s2;
        if (n == 3) {
            s2 = null;
        } else if (n == 6 || (n > 6 && s.charAt(6) == PRB_SEPARATOR_CHAR)) {
            s2 = s.substring(4, 6).toUpperCase();
            // country may be followed by whatever additional suffix
        } else {
            return false;
        }
        
        if (knownLanguages == null) {
            knownLanguages = new HashSet(Arrays.asList(Locale.getISOLanguages()));
        }
        if (!knownLanguages.contains(s1)) {
            return false;
        }

        if (s2 != null) {
            if (knownCountries == null) {
                knownCountries = new HashSet(Arrays.asList(Locale.getISOCountries()));
            }
            if (!knownCountries.contains(s2)) {
                return false;
            }
        }
        return true;
    }

    /**
     * @return  PropertiesFileEntry for the given file
     */
    protected MultiDataObject.Entry createPrimaryEntry(MultiDataObject obj,
                                                       FileObject primaryFile) {
        return new PropertiesFileEntry(obj, primaryFile);
    }

    /**
     * @return  PropertiesFileEntry for the given file
     */
    protected MultiDataObject.Entry createSecondaryEntry(
            MultiDataObject obj,
            FileObject secondaryFile) {
        return new PropertiesFileEntry(obj, secondaryFile);
    }
    

    /**
     * Sets the extension list for this data loader.
     * This data loader will then recognize all files having any extension
     * of the given list.
     *
     * @param  ext  list of extensions
     */
    public void setExtensions(ExtensionList ext) {
        putProperty(PROP_EXTENSIONS, ext, true);
    }

    /**
     * Get the extension list for this data loader.
     *
     * @return  list of extensions
     * @see  #setExtensions
     */
    public ExtensionList getExtensions() {
        ExtensionList l = (ExtensionList) getProperty(PROP_EXTENSIONS);
        if (l == null) {
            l = new ExtensionList();
            putProperty(PROP_EXTENSIONS, l, false);
        }
        return l;
    }

    /** Writes extensions to the stream.
    * @param oo ignored
    */
    @Override
    public void writeExternal (ObjectOutput oo) throws IOException {
        super.writeExternal (oo);

        oo.writeObject (getProperty (PROP_EXTENSIONS));
    }

    /** Reads nothing from the stream.
    * @param oi ignored
    */
    @Override
    public void readExternal (ObjectInput oi)
    throws IOException, ClassNotFoundException {
        SafeException se;
        try {
            super.readExternal (oi);
            se = null;
        } catch (SafeException se2) {
            se = se2;
        }

        setExtensions ((ExtensionList)oi.readObject ());
        if (se != null) {
            throw se;
        }
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy