/*
 * 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.web.project;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.util.*;
import org.netbeans.api.j2ee.core.Profile;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.Sources;
import org.netbeans.api.project.ui.OpenProjects;
import org.netbeans.modules.j2ee.dd.api.web.WebApp;
import org.netbeans.modules.j2ee.dd.api.web.WebAppMetadata;
import org.netbeans.modules.j2ee.dd.api.webservices.WebservicesMetadata;
import org.netbeans.modules.j2ee.deployment.common.api.ConfigurationException;
import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleFactory;
import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider;
import org.netbeans.modules.j2ee.deployment.common.api.EjbChangeDescriptor;
import org.netbeans.modules.web.project.classpath.ClassPathProviderImpl;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.netbeans.spi.project.support.ant.EditableProperties;
import org.openide.filesystems.FileObject;
import org.netbeans.modules.j2ee.deployment.devmodules.api.*;
import org.netbeans.modules.web.project.ui.customizer.WebProjectProperties;
import org.netbeans.spi.java.classpath.ClassPathProvider;
import org.openide.filesystems.FileUtil;
import org.openide.NotifyDescriptor;
import org.openide.DialogDisplayer;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.AbstractLookup;
import org.openide.util.lookup.InstanceContent;
import org.netbeans.modules.j2ee.dd.spi.MetadataUnit;
import org.netbeans.modules.j2ee.dd.spi.web.WebAppMetadataModelFactory;
import org.netbeans.modules.j2ee.dd.spi.webservices.WebservicesMetadataModelFactory;
import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleImplementation2;
import org.netbeans.modules.j2ee.deployment.devmodules.spi.ResourceChangeReporterFactory;
import org.netbeans.modules.j2ee.deployment.devmodules.spi.ResourceChangeReporterImplementation;
import org.netbeans.modules.j2ee.metadata.model.api.MetadataModel;
import org.netbeans.modules.java.api.common.ant.UpdateHelper;
import org.netbeans.modules.web.spi.webmodule.WebModuleImplementation2;
import org.netbeans.modules.websvc.spi.webservices.WebServicesConstants;
import org.openide.filesystems.FileChangeAdapter;
import org.openide.filesystems.FileEvent;

/** A web module implementation on top of project.
 *
 * @author  Pavel Buzek
 * @author ads
 */
public final class ProjectWebModule extends J2eeModuleProvider 
        implements J2eeModuleImplementation2, ModuleChangeReporter, 
        EjbChangeDescriptor, PropertyChangeListener,
        Lookup.Provider 
{
      
    public static final String FOLDER_WEB_INF = "WEB-INF";//NOI18N
//    public static final String FOLDER_CLASSES = "classes";//NOI18N
//    public static final String FOLDER_LIB     = "lib";//NOI18N
    public static final String FILE_DD        = "web.xml";//NOI18N
    
    public static final String LOOKUP_ITEM    = "lookup.item";//NOI18N

    private final ResourceChangeReporter rcr = ResourceChangeReporterFactory.createResourceChangeReporter(new WebResourceChangeReporter());
    
    private WebProject project;
    private UpdateHelper helper;
    private ClassPathProviderImpl cpProvider;
    private String fakeServerInstId = null; // used to get access to properties of other servers
    private Lookup myLookup;
    private InstanceContent myContent;

    private long notificationTimeout = 0; // used to suppress repeating the same messages
    
    private MetadataModel<WebAppMetadata> webAppMetadataModel;
    private MetadataModel<WebAppMetadata> webAppAnnMetadataModel;
    private MetadataModel<WebservicesMetadata> webservicesMetadataModel;
  
    private PropertyChangeSupport propertyChangeSupport;
    
    private J2eeModule j2eeModule;

    ProjectWebModule (WebProject project, UpdateHelper helper, ClassPathProviderImpl cpProvider) {
        this.project = project;
        this.helper = helper;
        this.cpProvider = cpProvider;
        myContent = new InstanceContent();
        myLookup = new AbstractLookup( myContent );
        //project.evaluator().addPropertyChangeListener(this);
    }
    
    public Lookup getLookup(){
        return myLookup;
    }
    
    public void addCookie( Object cookie ){
        if ( cookie == null ){
            return;
        }
        Object old = getLookup().lookup(cookie.getClass());
        myContent.add( cookie );
        getPropertyChangeSupport().firePropertyChange(LOOKUP_ITEM, old, cookie);
    }
    
    public void removeCookie( Object cookie ){
        if ( cookie == null ){
            return;
        }
        myContent.remove( cookie);
        getPropertyChangeSupport().firePropertyChange(LOOKUP_ITEM, cookie, null);
    }
    
    public FileObject getDeploymentDescriptor() {
        return getDeploymentDescriptor(false);
    }

    public FileObject getDeploymentDescriptor(boolean silent) {
        FileObject webInfFo = getWebInf(silent);
        if (webInfFo==null) {
            return null;
        }
        FileObject dd = webInfFo.getFileObject (FILE_DD);
        if (dd == null && !silent 
                && (Profile.J2EE_13.equals(getJ2eeProfile()) ||
                    Profile.J2EE_14.equals(getJ2eeProfile()))) {
            showErrorMessage(NbBundle.getMessage(ProjectWebModule.class,"MSG_WebXmlNotFound", //NOI18N
                    webInfFo.getPath()));
        }
        return dd;
    }

    public String getContextPath () {
        try {
            return getConfigSupport().getWebContextRoot();
        } catch (ConfigurationException e) {
            Exceptions.printStackTrace(e);
            return null;
        }
    }
    
    public void setContextPath (String path) {
        try {
            getConfigSupport().setWebContextRoot(path);
        } catch (ConfigurationException e) {
            Exceptions.printStackTrace(e);
        }
    }
    
    public String getContextPath (String serverInstId) {
        fakeServerInstId = serverInstId;
        String result = getContextPath();
        fakeServerInstId = null;
        return result;
    }
    
    public void setContextPath (String serverInstId, String path) {
        fakeServerInstId = serverInstId;
        setContextPath(path);
        fakeServerInstId = null;
    }
    
    private void showErrorMessage(final String message) {
        synchronized (this) {
            if(new Date().getTime() > notificationTimeout && isProjectOpened()) {
                // set timeout to suppress the same messages during next 20 seconds (feel free to adjust the timeout
                // using more suitable value)
                notificationTimeout = new Date().getTime() + 20000;
            } else {
                return;
            }
        }
        // #240818
        DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message(message, NotifyDescriptor.ERROR_MESSAGE));
    }
    
    public FileObject getDocumentBase () {
        return getDocumentBase(false);
    }

    public FileObject getDocumentBase (boolean silent) {
        String value = helper.getAntProjectHelper().getStandardPropertyEvaluator()
                .getProperty(WebProjectProperties.WEB_DOCBASE_DIR);

        return resolveDocumentBase(value, silent);
    }

    FileObject resolveDocumentBase(String value, boolean silent) {
        FileObject docBase = value != null ? helper.getAntProjectHelper().resolveFileObject(value) : null;
        if (docBase == null && !silent) {
            String path = (value != null ? helper.getAntProjectHelper().resolvePath(value) : null);
            String errorMessage;
            if (path != null) {
                errorMessage = NbBundle.getMessage(ProjectWebModule.class, "MSG_DocBase_Corrupted", project.getName(), path);
            } else {
                errorMessage = NbBundle.getMessage(ProjectWebModule.class, "MSG_DocBase_Corrupted_Unknown", project.getName());
            }
            showErrorMessage(errorMessage);
        }
        return docBase;
    }

    @Deprecated
    public FileObject[] getJavaSources() {
        return project.getSourceRoots().getRoots();
    }
    
//    public ClassPath getJavaSources () {
//        ClassPathProvider cpp = (ClassPathProvider) project.getLookup ().lookup (ClassPathProvider.class);
//        if (cpp != null) {
//            return cpp.findClassPath (getFileObject ("src.dir"), ClassPath.SOURCE); //NOI18N
//        }
//        return null;
//    }
    
    public FileObject getWebInf () {
        return getWebInf(false);
    }
    
    public FileObject getWebInf (boolean silent) {
        String value = helper.getAntProjectHelper().getStandardPropertyEvaluator()
                .getProperty(WebProjectProperties.WEBINF_DIR);

        return resolveWebInf(null, value, silent, false);
    }

    FileObject resolveWebInf(String docBaseValue, String webInfValue, boolean silent, boolean useDocBase) {
        FileObject webInf = null;
        if (webInfValue != null){
             webInf = helper.getAntProjectHelper().resolveFileObject(webInfValue);
//             if (webInf == null && forceCreate){
//                webInf = helper.getAntProjectHelper().getProjectDirectory();
//                StringTokenizer st = new StringTokenizer(webInfValue, "/");
//                while (st.hasMoreTokens()) {
//                    String nameExt = st.nextToken();
//                    try {
//                        FileObject tmp = webInf.getFileObject(nameExt, null);
//                        webInf = tmp != null ? tmp : webInf.createFolder(nameExt);
//                    } catch (IOException ex) {
//                        Exceptions.printStackTrace(ex);
//                        webInf = null;
//                        break;
//                    }
//                }
//             }
        }

        //temporary solution for < 6.0 projects
        if (webInf == null) {
            FileObject documentBase = null;
            if (useDocBase) {
                documentBase = resolveDocumentBase(docBaseValue, silent);
            } else {
                documentBase = getDocumentBase(silent);
            }
            if (documentBase == null) {
                return null;
            }
            webInf = documentBase.getFileObject (FOLDER_WEB_INF);
//            if (webInf == null && forceCreate){
//                try {
//                    webInf = documentBase.createFolder(FOLDER_WEB_INF);
//                } catch (IOException ex) {
//                    Exceptions.printStackTrace(ex);
//                }
//            }
        }

        if (webInf == null && !silent) {
            showErrorMessage(NbBundle.getMessage(ProjectWebModule.class,"MSG_WebInfCorrupted2")); //NOI18N
        }
        return webInf;
    }
    
    public FileObject getConfDir() {
        return getFileObject(WebProjectProperties.CONF_DIR);
    }
    
    public File getConfDirAsFile() {
        return getFile(WebProjectProperties.CONF_DIR);
    }
    
    public FileObject getPersistenceXmlDir() {
        return getFileObject(WebProjectProperties.PERSISTENCE_XML_DIR);
    }
    
    public File getPersistenceXmlDirAsFile() {
        return getFile(WebProjectProperties.PERSISTENCE_XML_DIR);
    }
    
    public ClassPathProvider getClassPathProvider () {
        return (ClassPathProvider) project.getLookup ().lookup (ClassPathProvider.class);
    }
    
    public FileObject getArchive () {
        return getFileObject ("dist.war"); //NOI18N
    }
    
    private FileObject getFileObject(String propname) {
        String prop = helper.getAntProjectHelper().getStandardPropertyEvaluator().getProperty(propname);
        if (prop != null) {
            return helper.getAntProjectHelper().resolveFileObject(prop);
        } else {
            return null;
        }
    }
    
    private File getFile(String propname) {
        String prop = helper.getAntProjectHelper().getStandardPropertyEvaluator().getProperty(propname);
        if (prop != null) {
            return helper.getAntProjectHelper().resolveFile(prop);
        } else {
            return null;
        }
    }
    
    public synchronized J2eeModule getJ2eeModule () {
        if (j2eeModule == null) {
            j2eeModule = J2eeModuleFactory.createJ2eeModule(this);
        }
        return j2eeModule;
    }
    
    public org.netbeans.modules.j2ee.deployment.devmodules.api.ModuleChangeReporter getModuleChangeReporter () {
        return this;
    }

    @Override
    public ResourceChangeReporter getResourceChangeReporter() {
        return rcr;
    }

    @Override
    public DeployOnSaveSupport getDeployOnSaveSupport() {
        return project.getDeployOnSaveSupport();
    }

    @Override
    public boolean isOnlyCompileOnSaveEnabled() {
        return Boolean.parseBoolean(project.evaluator().getProperty(WebProjectProperties.J2EE_COMPILE_ON_SAVE)) &&
            !Boolean.parseBoolean(project.evaluator().getProperty(WebProjectProperties.J2EE_DEPLOY_ON_SAVE));
    }
    
    
    public File getDeploymentConfigurationFile(String name) {
        assert name != null : "File name of the deployement configuration file can't be null"; //NOI18N
        
        String path = getConfigSupport().getContentRelativePath(name);
        if (path == null) {
            path = name;
        }
        
        if (path.startsWith("WEB-INF/")) { //NOI18N
            path = path.substring(8); //removing "WEB-INF/"

            FileObject webInf = getWebInf();
            if (webInf == null) {
                //in case that docbase is null ... but normally it should not be
                return new File(getConfDirAsFile(), name);
            }
            return new File(FileUtil.toFile(webInf), path);
        } else {
            FileObject documentBase = getDocumentBase();
            if (documentBase == null) {
                //in case that docbase is null ... but normally it should not be
                return new File(getConfDirAsFile(), name);
            }
            return new File(FileUtil.toFile(documentBase), path);
        }        
    }

    public FileObject getModuleFolder () {
        return getDocumentBase ();
    }
    
    public String getServerID () {
        String inst = getServerInstanceID ();
        if (inst != null) {
            String id = Deployment.getDefault().getServerID(inst);
            if (id != null) {
                return id;
            }
        }
        return helper.getAntProjectHelper().getStandardPropertyEvaluator ().getProperty (WebProjectProperties.J2EE_SERVER_TYPE);
    }

    public String getServerInstanceID () {
        if (fakeServerInstId != null)
            return fakeServerInstId;
        return helper.getAntProjectHelper().getStandardPropertyEvaluator ().getProperty (WebProjectProperties.J2EE_SERVER_INSTANCE);
    }
    
    public void setServerInstanceID(String severInstanceID) {
        WebProjectProperties.setServerInstance(project, helper, severInstanceID);
    }
    
    public Iterator<J2eeModule.RootedEntry> getArchiveContents () throws java.io.IOException {
        FileObject content = getContentDirectory();
        content.refresh();
        return new IT(content);
    }

    public FileObject getContentDirectory() {
        return getFileObject ("build.web.dir"); //NOI18N
    }

    public FileObject getBuildDirectory() {
        return getFileObject ("build.dir"); //NOI18N
    }

    public File getContentDirectoryAsFile() {
        return getFile ("build.web.dir"); //NOI18N
    }
    
    public <T> MetadataModel<T> getMetadataModel(Class<T> type) {
        if (type == WebAppMetadata.class) {
            @SuppressWarnings("unchecked") // NOI18N
            MetadataModel<T> model = (MetadataModel<T>)getAnnotationMetadataModel();
            return model;
        } else if (type == WebservicesMetadata.class) {
            @SuppressWarnings("unchecked") // NOI18N
            MetadataModel<T> model = (MetadataModel<T>)getWebservicesMetadataModel();
            return model;
        }
        return null;
    }
    
    public synchronized MetadataModel<WebAppMetadata> getMetadataModel() {
        if (webAppMetadataModel == null) {
            FileObject ddFO = getDeploymentDescriptor();
            final FileObject webInf = getWebInf(true);
            if (ddFO == null && webInf != null) {
                webInf.addFileChangeListener(new FileChangeAdapter() {
                    @Override
                    public void fileDataCreated(FileEvent fe) {
                        if (FILE_DD.equals(fe.getFile().getNameExt())) {
                            webInf.removeFileChangeListener(this);
                            resetMetadataModel();
                        }
                    }
                });
            }
            File ddFile = ddFO != null ? FileUtil.toFile(ddFO) : null;
            MetadataUnit metadataUnit = MetadataUnit.create(
                cpProvider.getProjectSourcesClassPath(ClassPath.BOOT),
                cpProvider.getProjectSourcesClassPath(ClassPath.COMPILE),
                cpProvider.getProjectSourcesClassPath(ClassPath.SOURCE),
                ddFile);
            webAppMetadataModel = WebAppMetadataModelFactory.createMetadataModel(metadataUnit, true);
        }
        return webAppMetadataModel;
    }
    
    private synchronized void resetMetadataModel() {
        webAppMetadataModel = null;
    }
    
    /**
     * The server plugin needs all models to be either merged on annotation-based. 
     * Currently only the web model does a bit of merging, other models don't. So
     * for web we actually need two models (one for the server plugins and another
     * for everyone else). Temporary solution until merging is implemented
     * in all models.
     */
    public synchronized MetadataModel<WebAppMetadata> getAnnotationMetadataModel() {
        if (webAppAnnMetadataModel == null) {
            FileObject ddFO = getDeploymentDescriptor();
            File ddFile = ddFO != null ? FileUtil.toFile(ddFO) : null;
            MetadataUnit metadataUnit = MetadataUnit.create(
                cpProvider.getProjectSourcesClassPath(ClassPath.BOOT),
                cpProvider.getProjectSourcesClassPath(ClassPath.COMPILE),
                cpProvider.getProjectSourcesClassPath(ClassPath.SOURCE),
                // XXX: add listening on deplymentDescriptor
                ddFile);
            webAppAnnMetadataModel = WebAppMetadataModelFactory.createMetadataModel(metadataUnit, false);
        }
        return webAppAnnMetadataModel;
    }
    
    public synchronized MetadataModel<WebservicesMetadata> getWebservicesMetadataModel() {
        if (webservicesMetadataModel == null) {
            FileObject ddFO = getDD();
            File ddFile = ddFO != null ? FileUtil.toFile(ddFO) : null;
            MetadataUnit metadataUnit = MetadataUnit.create(
                cpProvider.getProjectSourcesClassPath(ClassPath.BOOT),
                cpProvider.getProjectSourcesClassPath(ClassPath.COMPILE),
                cpProvider.getProjectSourcesClassPath(ClassPath.SOURCE),
                // XXX: add listening on deplymentDescriptor
                ddFile);
            webservicesMetadataModel = WebservicesMetadataModelFactory.createMetadataModel(metadataUnit);
        }
        return webservicesMetadataModel;
    }
   
    public void uncacheDescriptors() {
        // this.getConfigSupport().resetStorage();
        // reset timeout when closing the project
        synchronized (this) {
            notificationTimeout = 0;
        }
    }

    // TODO MetadataModel: rewrite when MetadataModel is ready    
//    private Webservices getWebservices() {
//        if (Util.isJavaEE5orHigher(project)) {
//            WebServicesSupport wss = WebServicesSupport.getWebServicesSupport(project.getProjectDirectory());
//            try {
//                return org.netbeans.modules.j2ee.dd.api.webservices.DDProvider.getDefault().getMergedDDRoot(wss);
//            } catch (IOException ex) {
//                ErrorManager.getDefault().notify(ex);
//            }
//        } else {
//            FileObject wsdd = getDD();
//            if(wsdd != null) {
//                try {
//                    return org.netbeans.modules.j2ee.dd.api.webservices.DDProvider.getDefault()
//                    .getDDRoot(getDD());
//                } catch (java.io.IOException e) {
//                    org.openide.ErrorManager.getDefault().log(e.getLocalizedMessage());
//                }
//            }
//        }
//        return null;
//    }
    
    public org.netbeans.modules.j2ee.deployment.common.api.EjbChangeDescriptor getEjbChanges (long timestamp) {
        return this;
    }

    public J2eeModule.Type getModuleType () {
        return J2eeModule.Type.WAR;
    }

    @Override
    public String getModuleVersion () {
        // return a version based on the Java EE version
        Profile platformVersion = getJ2eeProfile();
        if (Profile.JAVA_EE_8_FULL.equals(platformVersion) || Profile.JAVA_EE_8_WEB.equals(platformVersion)) {
            return WebApp.VERSION_4_0;
        } else if (Profile.JAVA_EE_7_FULL.equals(platformVersion) || Profile.JAVA_EE_7_WEB.equals(platformVersion)) {
            return WebApp.VERSION_3_1;
        } else if (Profile.JAVA_EE_6_FULL.equals(platformVersion) || Profile.JAVA_EE_6_WEB.equals(platformVersion)) {
            return WebApp.VERSION_3_0;
        } else if (Profile.JAVA_EE_5.equals(platformVersion)) {
            return WebApp.VERSION_2_5;
        } else if (Profile.J2EE_14.equals(platformVersion)) {
            return WebApp.VERSION_2_4;
        } else {
            // return 3.1 as default value
            return WebApp.VERSION_3_1;
        }
    }
    
    public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals(org.netbeans.modules.j2ee.dd.api.web.WebApp.PROPERTY_VERSION)) {
            String oldVersion = (String) evt.getOldValue();
            String newVersion = (String) evt.getNewValue();
            getPropertyChangeSupport().firePropertyChange(J2eeModule.PROP_MODULE_VERSION, oldVersion, newVersion);
        } else if (evt.getPropertyName ().equals (WebProjectProperties.J2EE_SERVER_INSTANCE)) {
            Deployment d = Deployment.getDefault ();
            String oldServerID = evt.getOldValue () == null ? null : d.getServerID ((String) evt.getOldValue ());
            String newServerID = evt.getNewValue () == null ? null : d.getServerID ((String) evt.getNewValue ());
            fireServerChange (oldServerID, newServerID);
        }  else if (WebProjectProperties.RESOURCE_DIR.equals(evt.getPropertyName())) {
            String oldValue = (String) evt.getOldValue();
            String newValue = (String) evt.getNewValue();
            getPropertyChangeSupport().firePropertyChange(
                    J2eeModule.PROP_RESOURCE_DIRECTORY, 
                    oldValue == null ? null : new File(oldValue),
                    newValue == null ? null : new File(newValue));
        }  else if (WebProjectProperties.WEB_DOCBASE_DIR.equals(evt.getPropertyName())) {
            getPropertyChangeSupport().firePropertyChange(
                    WebModuleImplementation2.PROPERTY_DOCUMENT_BASE,
                    (String)evt.getOldValue(),
                    (String)evt.getNewValue());
        }  else if (WebProjectProperties.WEBINF_DIR.equals(evt.getPropertyName())) {
            getPropertyChangeSupport().firePropertyChange(
                    WebModuleImplementation2.PROPERTY_WEB_INF,
                    (String)evt.getOldValue(),
                    (String)evt.getNewValue());
        }
    }
        
    public String getUrl () {
         EditableProperties ep =  helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
         String warName = ep.getProperty(WebProjectProperties.WAR_NAME);
         return warName == null ? "" : ("/"+warName); //NOI18N
    }

    public boolean isManifestChanged (long timestamp) {
        return false;
    }

    public void setUrl (String url) {
        throw new UnsupportedOperationException ("Cannot customize URL of web module"); //NOI18N
    }

    public boolean ejbsChanged () {
        return false;
    }

    public String[] getChangedEjbs () {
        return new String[] {};
    }

    public Profile getJ2eeProfile () {
        return Profile.fromPropertiesString(helper.getAntProjectHelper().getStandardPropertyEvaluator ().getProperty(WebProjectProperties.J2EE_PLATFORM));
    }
    
    public FileObject getDD() {
       FileObject webInfFo = getWebInf();
       if (webInfFo==null) {
           showErrorMessage(NbBundle.getMessage(ProjectWebModule.class,"MSG_WebInfCorrupted"));
           return null;
       }
       return getWebInf().getFileObject(WebServicesConstants.WEBSERVICES_DD, "xml"); // NOI18N
   }
    
    @Override
    public FileObject[] getSourceRoots() {
        Sources sources = ProjectUtils.getSources(project);
        SourceGroup[] groups = sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
        
        List<FileObject> roots = new LinkedList<FileObject>();
        FileObject documentBase = getDocumentBase();
        if (documentBase != null)
            roots.add(documentBase);
        
        for (int i = 0; i < groups.length; i++) {
            roots.add(groups[i].getRootFolder());
        }
        
        FileObject[] rootArray = new FileObject[roots.size()];
        return roots.toArray(rootArray);
    }
    
    private boolean isProjectOpened() {
        // XXX workaround: OpenProjects.getDefault() can be null 
        // when called from ProjectOpenedHook.projectOpened() upon IDE startup
        if (OpenProjects.getDefault() == null)
            return true;
        
        Project[] projects = OpenProjects.getDefault().getOpenProjects();
        for (int i = 0; i < projects.length; i++) {
            if (projects[i].equals(project)) 
                return true;
        }
        return false;
    }

    @Override
    public File getResourceDirectory() {
        File f = getFile(WebProjectProperties.RESOURCE_DIR);
        if (f == null) {
            f = new File(FileUtil.toFile(project.getProjectDirectory()), "setup"); // NOI18N
        }
        return f;
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        //synchronized (this) {
            // XXX need to listen on the module version
            // if (!webAppPropChangeLInitialized) {
            //     try {
            //         project.getWebModule().getMetadataModel().runReadAction(new MetadataModelAction<WebAppMetadata, Void>() {
            //             public Void run(WebAppMetadata metadata) throws MetadataModelException, IOException {
            //                 WebApp webAp p = metadata.getRoot();
            //                 PropertyChangeListener l = (PropertyChangeListener) WeakListeners.create(PropertyChangeListener.class, ProjectWebModule.this, webApp);
            //                 webApp.addPropertyChangeListener(l);
            //                 return null;
            //             }
            //         });
            //         webAppPropChangeLInitialized = true;
            //     } catch (MetadataModelException e) {
            //         // TODO MetadataModel: how should we handle this?
            //     } catch (IOException e) {
            //         // TODO MetadataModel: how should we handle this?
            //     }
            // }
        //}
        getPropertyChangeSupport().addPropertyChangeListener(listener);
    }
    
    public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
        if (propertyChangeSupport == null) {
            return;
        }
        propertyChangeSupport.removePropertyChangeListener(listener);
    }
    
    private synchronized PropertyChangeSupport getPropertyChangeSupport() {
        if (propertyChangeSupport == null) {
            propertyChangeSupport = new PropertyChangeSupport(this);
        }
        return propertyChangeSupport;
    }

    private class WebResourceChangeReporter implements ResourceChangeReporterImplementation {

        public boolean isServerResourceChanged(long lastDeploy) {
            File resDir = getResourceDirectory();
            if (resDir != null && resDir.exists() && resDir.isDirectory()) {
                File[] children = resDir.listFiles();
                if (children != null) {
                    for (File file : children) {
                        if (file.lastModified() > lastDeploy) {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
    }

    private static class IT implements Iterator<J2eeModule.RootedEntry> {
        ArrayList<FileObject> ch;
        FileObject root;
        
        private IT (FileObject f) {
            this.ch = new ArrayList<FileObject>();
            ch.add (f);
            this.root = f;
        }
        
        public boolean hasNext () {
            return ! ch.isEmpty();
        }
        
        public J2eeModule.RootedEntry next () {
            FileObject f = ch.get(0);
            ch.remove(0);
            if (f.isFolder()) {
                f.refresh();
                FileObject chArr[] = f.getChildren ();
                for (int i = 0; i < chArr.length; i++) {
                    ch.add(chArr [i]);
                }
            }
            return new FSRootRE (root, f);
        }
        
        public void remove () {
            throw new UnsupportedOperationException ();
        }
        
    }

    private static final class FSRootRE implements J2eeModule.RootedEntry {
        FileObject f;
        FileObject root;
        
        FSRootRE (FileObject root, FileObject f) {
            this.f = f;
            this.root = root;
        }
        
        public FileObject getFileObject () {
            return f;
        }
        
        public String getRelativePath () {
            return FileUtil.getRelativePath (root, f);
        }
    }
}
