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

org.netbeans.modules.java.j2sedeploy.J2SEDeployActionProvider Maven / Gradle / Ivy

/*
 * 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.java.j2sedeploy;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.List;
import java.util.Properties;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import org.apache.tools.ant.module.api.support.ActionUtils;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.api.scripting.Scripting;
import org.netbeans.modules.java.j2seproject.api.J2SEPropertyEvaluator;
import org.netbeans.spi.project.ActionProgress;
import org.netbeans.spi.project.ActionProvider;
import org.netbeans.spi.project.LookupProvider;
import org.netbeans.spi.project.ProjectServiceProvider;
import org.netbeans.spi.project.support.ant.GeneratedFilesHelper;
import org.netbeans.spi.project.support.ant.PropertyEvaluator;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.execution.ExecutorTask;
import org.openide.filesystems.FileObject;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.Parameters;
import org.openide.util.RequestProcessor;
import org.openide.util.Task;
import org.openide.util.TaskListener;

/**
 *
 * @author Tomas Zezula
 * @author Petr Somol
 */
@ProjectServiceProvider(
    service = ActionProvider.class,
    projectTypes={@LookupProvider.Registration.ProjectType(id="org-netbeans-modules-java-j2seproject",position=500)})
public class J2SEDeployActionProvider implements ActionProvider {

    private static final String TARGET_BUILD_NATIVE = "build-native";               //NOI18N
    private static final String NOSCRIPT_SUFFIX = "-noscript";                      //NOI18N
    private static final String PROP_PACKAGE_TYPE = "native.bundling.type";              //NOI18N
    private static final String PROP_DISABLE_JAR_CREATION = "jar.archive.disabled";//NOI18N
    private static final String PROP_BUILD_FILE = "buildfile";                      //NOI18N

    private static final RequestProcessor RP = new RequestProcessor(J2SEDeployActionProvider.class);


    private final Listener listener;
    private boolean isJSAvailable = true;
    private boolean isJSAvailableChecked = false;


    public J2SEDeployActionProvider(@NonNull final Project prj) {
        this.listener = new Listener(prj);
    }

    @Override
    public String[] getSupportedActions() {
        final Set nbts = NativeBundleType.getSupported();
        final Queue res = new ArrayDeque<>(nbts.size());
        for (NativeBundleType nbt : nbts) {
            res.add(nbt.getCommand());
        }
        return res.toArray(new String[res.size()]);
    }

    @NbBundle.Messages("LBL_No_Build_XML_Found=The project does not have a valid build script {0}.")
    @Override
    public void invokeAction(String command, Lookup context) throws IllegalArgumentException {
        final Project prj = context.lookup(Project.class);
        if (prj == null) {
            throw new IllegalArgumentException(String.format(
                "The context %s has no Project.",   //NOI18N
                context));
        }
        final NativeBundleType nbt = NativeBundleType.forCommand(command);
        if (nbt == null) {
            throw new IllegalArgumentException(String.format(
                "Unsupported command %s.",  //NOI18N
                command));
        }
        final FileObject buildScript = findBuildScript(listener.getProject());
        if (buildScript == null || !buildScript.isValid()) {
            NotifyDescriptor nd = new NotifyDescriptor.Message(
                Bundle.LBL_No_Build_XML_Found(getBuildXmlName(listener.getProject())),
                NotifyDescriptor.WARNING_MESSAGE);
            DialogDisplayer.getDefault().notify(nd);
            return;
        }
        final ActionProgress listener = ActionProgress.start(context);
        boolean success = false;
        try {
            final Properties p = new Properties();
            p.setProperty(PROP_PACKAGE_TYPE, nbt.getAntProperyValue());
            p.setProperty(PROP_DISABLE_JAR_CREATION, Boolean.TRUE.toString());
            String noScript = isJavaScriptAvailable() ? "" : NOSCRIPT_SUFFIX; // NOI18N
            final ExecutorTask task = ActionUtils.runTarget(
                buildScript,
                new String[] {TARGET_BUILD_NATIVE.concat(noScript)},
                p);
            task.addTaskListener(new TaskListener() {
                @Override
                public void taskFinished(Task _tmp) {
                    listener.finished(task.result() == 0);
                }
            });
            success = true;
        } catch (IOException ex) {            
            Exceptions.printStackTrace(ex);
        } finally {
            if (!success) {
                listener.finished(false);
            }
        }
    }

    @Override
    public boolean isActionEnabled(String command, Lookup context) throws IllegalArgumentException {
        return supportsCommand(command) &&
               listener.getProject().equals(context.lookup(Project.class)) &&
               listener.isEnabled();
    }

    private boolean isJavaScriptAvailable() {
        if(isJSAvailableChecked) {
            return isJSAvailable;
        }
        ScriptEngineManager mgr = Scripting.createManager();
        List factories = mgr.getEngineFactories();
        for (ScriptEngineFactory factory: factories) {
            List engNames = factory.getNames();
            for(String name: engNames) {
                if(name.equalsIgnoreCase("js") || name.equalsIgnoreCase("javascript")) { //NOI18N
                    isJSAvailableChecked = true;
                    isJSAvailable = true;
                    return isJSAvailable;
                }
            }
        }
        isJSAvailableChecked = true;
        isJSAvailable = false;
        return isJSAvailable;
    }

    private boolean supportsCommand (@NonNull final String command) {
        for (String supportedCommand : getSupportedActions()) {
            if (supportedCommand.equals(command)) {
                return true;
            }
        }
        return false;
    }
    
    @CheckForNull
    private static FileObject findBuildScript (@NonNull final Project prj) {                
        return prj.getProjectDirectory().getFileObject(getBuildXmlName(prj));
    }

    @NonNull
    private static String getBuildXmlName (@NonNull final Project prj) {
        final J2SEPropertyEvaluator evalProvider = prj.getLookup().lookup(J2SEPropertyEvaluator.class);
        String buildScriptPath = evalProvider == null ?
            null :
            evalProvider.evaluator().getProperty(PROP_BUILD_FILE);
        if (buildScriptPath == null) {
            buildScriptPath = GeneratedFilesHelper.BUILD_XML_PATH;
        }
        return buildScriptPath;
    }


    

    private static final class Listener implements Runnable, PropertyChangeListener {

        private final Project prj;
        private final RequestProcessor.Task refresh;
        private final AtomicBoolean initialized;
        private volatile Boolean cachedEnabled;

        Listener(@NonNull final Project prj) {
            Parameters.notNull("prj", prj); //NOI18N
            this.prj = prj;
            this.initialized = new AtomicBoolean();
            refresh = RP.create(this);                    
        }

        @Override
        public void run() {
            ProjectManager.mutex().readAccess(new Runnable() {
                @Override
                public void run() {
                    isEnabled();
                }
            });
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            final String propName = evt.getPropertyName();
            if (propName == null || J2SEDeployProperties.NATIVE_BUNDLING_ENABLED.equals(propName)) {
                cachedEnabled = null;
                refresh.schedule(0);
            }
        }

        boolean isEnabled() {
            Boolean res = cachedEnabled;
            if (res != null) {
                return res;
            }
            final J2SEPropertyEvaluator j2seEval = prj.getLookup().lookup(J2SEPropertyEvaluator.class);
            if (j2seEval == null) {
               cachedEnabled = res = Boolean.FALSE;
            } else {
                final PropertyEvaluator eval = j2seEval.evaluator();
                if (initialized.compareAndSet(false, true)) {
                    eval.addPropertyChangeListener(this);
                }
                cachedEnabled = res = isTrue(eval.getProperty(J2SEDeployProperties.NATIVE_BUNDLING_ENABLED));
            }
            return res;
        }

        @NonNull
        Project getProject() {
            return prj;
        }

        private static boolean isTrue(@NullAllowed String value) {
            return "true".equals(value) ||  //NOI18N
                   "yes".equals(value)  ||  //NOI18N
                   "on".equals(value);      //NOI18N
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy