0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041: package org.netbeans.modules.visualweb.insync.models;
0042:
0043: import org.netbeans.modules.visualweb.project.jsf.api.JsfProjectUtils;
0044: import java.awt.Image;
0045: import java.beans.PropertyChangeEvent;
0046: import java.beans.PropertyChangeListener;
0047: import java.beans.PropertyChangeSupport;
0048: import java.io.File;
0049: import java.io.IOException;
0050: import java.net.MalformedURLException;
0051: import java.net.URI;
0052: import java.net.URISyntaxException;
0053: import java.net.URL;
0054: import java.util.Arrays;
0055: import java.util.Comparator;
0056: import java.util.Enumeration;
0057: import java.util.HashMap;
0058: import java.util.IdentityHashMap;
0059: import java.util.Iterator;
0060: import java.util.Map;
0061:
0062: import javax.swing.SwingUtilities;
0063: import javax.swing.event.ChangeEvent;
0064: import javax.swing.event.ChangeListener;
0065: import javax.xml.parsers.DocumentBuilder;
0066: import javax.xml.parsers.DocumentBuilderFactory;
0067:
0068: import org.netbeans.api.java.classpath.ClassPath;
0069: import org.netbeans.api.project.FileOwnerQuery;
0070: import org.netbeans.api.project.Project;
0071: import org.netbeans.api.project.ProjectUtils;
0072: import org.netbeans.api.project.ui.OpenProjects;
0073: import org.netbeans.api.queries.SharabilityQuery;
0074: import org.netbeans.spi.project.AuxiliaryConfiguration;
0075: import org.openide.ErrorManager;
0076: import org.openide.awt.StatusDisplayer;
0077: import org.openide.filesystems.FileAttributeEvent;
0078: import org.openide.filesystems.FileChangeListener;
0079: import org.openide.filesystems.FileEvent;
0080: import org.openide.filesystems.FileObject;
0081: import org.openide.filesystems.FileRenameEvent;
0082: import org.openide.filesystems.FileStateInvalidException;
0083: import org.openide.filesystems.FileSystem;
0084: import org.openide.filesystems.FileUtil;
0085: import org.openide.filesystems.URLMapper;
0086: import org.openide.loaders.DataObject;
0087: import org.openide.util.NbBundle;
0088: import org.w3c.dom.Document;
0089: import org.w3c.dom.Element;
0090: import org.w3c.dom.Node;
0091: import org.netbeans.modules.visualweb.extension.openide.util.Trace;
0092:
0093: import com.sun.rave.designtime.DesignBean;
0094: import com.sun.rave.designtime.DesignContext;
0095: import com.sun.rave.designtime.faces.FacesDesignProject;
0096: import com.sun.rave.designtime.DesignProperty;
0097: import com.sun.rave.designtime.event.DesignProjectListener;
0098: import org.netbeans.modules.visualweb.insync.Model;
0099: import org.netbeans.modules.visualweb.insync.ModelSet;
0100: import org.netbeans.modules.visualweb.insync.SourceUnit;
0101: import org.netbeans.modules.visualweb.insync.faces.ElAttrUpdater;
0102: import org.netbeans.modules.visualweb.insync.java.JavaUnit;
0103: import org.netbeans.modules.visualweb.insync.live.LiveUnit;
0104: import org.netbeans.modules.visualweb.insync.markup.MarkupUnit;
0105: import org.netbeans.modules.visualweb.jsfsupport.container.FacesContainer;
0106:
0107: import org.netbeans.api.project.SourceGroup;
0108: import org.netbeans.api.project.Sources;
0109: import java.util.List;
0110: import java.util.Collection;
0111: import java.util.ArrayList;
0112: import java.util.logging.Level;
0113: import java.util.logging.LogRecord;
0114: import java.util.logging.Logger;
0115: import org.netbeans.modules.web.jsf.api.facesmodel.ManagedBean;
0116: import org.openide.windows.TopComponent;
0117: import java.awt.Component;
0118: import java.awt.Container;
0119: import org.openide.windows.Mode;
0120: import org.openide.windows.WindowManager;
0121:
0122: /**
0123: * A specific concrete ModelSet class that knows all about JSF.
0124: * @author cquinn
0125: */
0126: public class FacesModelSet extends ModelSet implements
0127: FacesDesignProject {
0128:
0129: PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
0130: this );
0131:
0132: protected static final String PROJECTDATA_ELEMENT_NAMESPACE = "http://creator.sun.com/project/DesignTimeApiProjectData";
0133: protected static final String PROJECTDATA_ELEMENT_KEY_PREFIX = "designtimeapi-projectdata-";
0134: // TODO When done with this type of debugging remove this var and all references
0135: public static final boolean LOG_SYNC_ALLS = false;
0136:
0137: protected static IdentityHashMap openProjects = new IdentityHashMap();
0138:
0139: FacesConfigModel facesConfigModel;
0140:
0141: private ProjectBuiltQuery.Status projectBuiltQueryStatus;
0142: private ChangeListener projectBuiltQueryStatusChangeListener;
0143:
0144: // Listener to monitor file system changes. This is used to keep the folder structure under the
0145: // document root folder synchronized with the folder structure under the page bean root folder.
0146: private static class FolderStructureFileChangeListener implements
0147: FileChangeListener {
0148:
0149: public void fileAttributeChanged(FileAttributeEvent fe) {
0150: // Don't care
0151: }
0152:
0153: public void fileChanged(FileEvent fe) {
0154: // Don't care
0155: }
0156:
0157: public void fileDataCreated(FileEvent fe) {
0158: // Don't care
0159: }
0160:
0161: public void fileDeleted(FileEvent fe) {
0162: // Don't care
0163: }
0164:
0165: public void fileFolderCreated(FileEvent fe) {
0166: FileObject fileObject = fe.getFile();
0167:
0168: FileObject documentRootFolder = null;
0169: Project project = null;
0170: // Search in open projects list if any of them own the folder
0171: // Note: We cannot use FileOwnerQuery.getOwner() API because
0172: // the folder may be created during the process of project Creation
0173: // and FileOwnerQuery.getOwner() throws an exception in such cases.
0174: Project[] projects = OpenProjects.getDefault()
0175: .getOpenProjects();
0176: for (int i = 0; i < projects.length; i++) {
0177: Project aProject = projects[i];
0178: if (JsfProjectUtils.isJsfProject(aProject)) {
0179: documentRootFolder = JsfProjectUtils
0180: .getDocumentRoot(aProject);
0181: if (documentRootFolder == null) {
0182: continue;
0183: }
0184: if (FileUtil.isParentOf(documentRootFolder,
0185: fileObject)) {
0186: project = aProject;
0187: break;
0188: }
0189: }
0190: }
0191:
0192: if (project == null || documentRootFolder == null) {
0193: return;
0194: }
0195:
0196: String relativePath = FileUtil.getRelativePath(
0197: documentRootFolder, fileObject);
0198: if (relativePath.startsWith("WEB-INF")
0199: || relativePath.startsWith("META-INF")
0200: || relativePath.startsWith("resources")) { // NOI18N Skip folders names WEB-INF
0201: return;
0202: }
0203: FileObject pageBeanRootFolder = JsfProjectUtils
0204: .getPageBeanRoot(project);
0205: if (pageBeanRootFolder == null) {
0206: return;
0207: }
0208: FileObject destFolder = pageBeanRootFolder
0209: .getFileObject(relativePath);
0210: if (destFolder == null || !destFolder.isValid()) {
0211: // try to create it
0212: try {
0213: destFolder = FileUtil.createFolder(
0214: pageBeanRootFolder, relativePath);
0215: } catch (IOException e) {
0216: ErrorManager.getDefault().log(
0217: ErrorManager.INFORMATIONAL, e.toString());
0218: }
0219: }
0220: }
0221:
0222: public void fileRenamed(FileRenameEvent fe) {
0223: // Don't care TODO
0224: }
0225: }
0226:
0227: private static FolderStructureFileChangeListener folderStructureFileChangeListener = new FolderStructureFileChangeListener();
0228:
0229: // for recording the filesystems to which the listener has been added
0230: private static ArrayList fileChangeListenerAddedTo = new ArrayList();
0231:
0232: static {
0233: // Go through initial set of project that were opened
0234: Project[] projects = OpenProjects.getDefault()
0235: .getOpenProjects();
0236: for (int i = 0; i < projects.length; i++) {
0237: Project project = projects[i];
0238: if (JsfProjectUtils.isJsfProject(project)) {
0239: ensureJspJavaFolderStructure(project);
0240: openProjects.put(project, project);
0241: // now add a listener to project's file system - if not already added
0242: FileSystem aFileSystem;
0243: try {
0244: aFileSystem = project.getProjectDirectory()
0245: .getFileSystem();
0246: if (!fileChangeListenerAddedTo
0247: .contains(aFileSystem)) {
0248: aFileSystem
0249: .addFileChangeListener(folderStructureFileChangeListener);
0250: fileChangeListenerAddedTo.add(aFileSystem);
0251: }
0252: } catch (FileStateInvalidException e) {
0253: ErrorManager.getDefault().notify(e);
0254: }
0255: }
0256: }
0257: }
0258:
0259: private static void ensureJspJavaFolderStructure(Project project) {
0260: if (project == null) {
0261: return;
0262: }
0263: FileObject documentRootFolder = JsfProjectUtils
0264: .getDocumentRoot(project);
0265: if (documentRootFolder == null) {
0266: return;
0267: }
0268: FileObject pageBeanRootFolder = JsfProjectUtils
0269: .getPageBeanRoot(project);
0270: if (pageBeanRootFolder == null) {
0271: return;
0272: }
0273: ensureJspJavaFolderStructure(documentRootFolder,
0274: pageBeanRootFolder, 0);
0275: }
0276:
0277: private static void ensureJspJavaFolderStructure(
0278: FileObject srcParentFolder, FileObject destParentFolder,
0279: int depth) {
0280: assert srcParentFolder != null;
0281: assert destParentFolder != null;
0282:
0283: // Bug Fix# 108800
0284: // Do not copy folder structure if the src folder is under page bean root.
0285: Project project = FileOwnerQuery.getOwner(srcParentFolder);
0286: if (project == null) {
0287: return;
0288: }
0289:
0290: FileObject pageBeanRootFolder = JsfProjectUtils
0291: .getPageBeanRoot(project);
0292: if (pageBeanRootFolder == null) {
0293: return;
0294: }
0295:
0296: ClassPath classPath = ClassPath.getClassPath(
0297: pageBeanRootFolder, ClassPath.SOURCE);
0298: if (classPath == null) {
0299: return;
0300: }
0301:
0302: FileObject srcRoot = classPath
0303: .findOwnerRoot(pageBeanRootFolder);
0304:
0305: if (srcRoot == null) {
0306: return;
0307: }
0308:
0309: if (FileUtil.isParentOf(srcRoot, srcParentFolder)
0310: || srcRoot.equals(srcParentFolder)) {
0311: return;
0312: }
0313:
0314: FileObject[] fileObjects = srcParentFolder.getChildren();
0315: for (int i = 0; i < fileObjects.length; i++) {
0316: FileObject fileObject = fileObjects[i];
0317: if (fileObject.isFolder()) {
0318: String nameExt = fileObject.getNameExt();
0319: if (depth == 0
0320: && (nameExt.equals("WEB-INF")
0321: || nameExt.equals("META-INF") || nameExt
0322: .equals("resources"))) { // NOI18N Skip folders names WEB-INF
0323: continue;
0324: }
0325: FileObject destFolder = destParentFolder
0326: .getFileObject(nameExt);
0327: if (destFolder == null || !destFolder.isValid()) {
0328: // try to create it
0329: try {
0330: destFolder = destParentFolder
0331: .createFolder(nameExt);
0332: } catch (IOException e) {
0333: ErrorManager.getDefault().log(
0334: ErrorManager.INFORMATIONAL,
0335: e.toString());
0336: }
0337: }
0338: if (destFolder != null) {
0339: // recurse
0340: ensureJspJavaFolderStructure(fileObject,
0341: destFolder, (depth + 1));
0342: }
0343: }
0344: }
0345: }
0346:
0347: // monitor project open and close
0348: protected static class OpenProjectsListener implements
0349: PropertyChangeListener {
0350: public void propertyChange(PropertyChangeEvent event) {
0351: // The list of open projects has changed
0352: if (OpenProjects.PROPERTY_OPEN_PROJECTS.equals(event
0353: .getPropertyName())) {
0354: // Remove fileChangeListeners from all known filesystems
0355: for (Iterator iter = fileChangeListenerAddedTo
0356: .iterator(); iter.hasNext();) {
0357: FileSystem aFileSystem = (FileSystem) iter.next();
0358: aFileSystem
0359: .removeFileChangeListener(folderStructureFileChangeListener);
0360: }
0361:
0362: fileChangeListenerAddedTo.clear();
0363:
0364: Project[] projects = OpenProjects.getDefault()
0365: .getOpenProjects();
0366: for (int i = 0; i < projects.length; i++) {
0367: Project project = projects[i];
0368: if (JsfProjectUtils.isJsfProject(project)) {
0369: // now add a listener to project's file system - if not already added
0370: FileSystem aFileSystem;
0371: try {
0372: aFileSystem = project.getProjectDirectory()
0373: .getFileSystem();
0374: if (!fileChangeListenerAddedTo
0375: .contains(aFileSystem)) {
0376: aFileSystem
0377: .addFileChangeListener(folderStructureFileChangeListener);
0378: fileChangeListenerAddedTo
0379: .add(aFileSystem);
0380: }
0381: } catch (FileStateInvalidException e) {
0382: ErrorManager.getDefault().notify(e);
0383: }
0384: }
0385: if (!openProjects.containsKey(project)) {
0386: if (JsfProjectUtils.isJsfProject(project)) {
0387: ensureJspJavaFolderStructure(project);
0388: }
0389: }
0390: }
0391:
0392: openProjects.clear();
0393:
0394: // remember the new list of open projects
0395: for (int i = 0; i < projects.length; i++) {
0396: Project project = projects[i];
0397: openProjects.put(project, project);
0398: }
0399: }
0400:
0401: }
0402: }
0403:
0404: static {
0405: OpenProjects.getDefault().addPropertyChangeListener(
0406: new OpenProjectsListener());
0407: }
0408:
0409: //--------------------------------------------------------------------------------- Construction
0410:
0411: public static FacesModelSet startModeling(FileObject file) {
0412: Project project = FileOwnerQuery.getOwner(file);
0413: if (project == null) {
0414: return null;
0415: }
0416: return startModeling(project);
0417: }
0418:
0419: public static FacesModelSet startModeling(Project project) {
0420: return (FacesModelSet) ModelSet.startModeling(project,
0421: FacesModelSet.class);
0422: }
0423:
0424: public static FacesModelSet getInstance(FileObject file) {
0425: return (FacesModelSet) ModelSet.getInstance(file,
0426: FacesModelSet.class);
0427: }
0428:
0429: /**
0430: *
0431: * @param project
0432: * @return
0433: */
0434: public static FacesModelSet getInstance(Project project) {
0435: return (FacesModelSet) ModelSet.getInstance(project,
0436: FacesModelSet.class);
0437: }
0438:
0439: public static FacesModel getFacesModelIfAvailable(
0440: FileObject fileObject) {
0441: ModelSet modelSet = getModelSet(fileObject);
0442: if (modelSet instanceof FacesModelSet
0443: && modelSet.isInitialized()) {
0444: return ((FacesModelSet) modelSet).getFacesModel(fileObject);
0445: }
0446: return null;
0447: }
0448:
0449: private FacesContainer facesContainer;
0450:
0451: // Memory leak probing
0452: private static final Logger TIMERS = Logger
0453: .getLogger("TIMER.visualweb"); // NOI18N
0454:
0455: /**
0456: * @param project
0457: */
0458: public FacesModelSet(Project project) {
0459: super (project);
0460: getFacesContainer();
0461:
0462: if (TIMERS.isLoggable(Level.FINE)) {
0463: LogRecord rec = new LogRecord(Level.FINE, "FacesModelSet"); // NOI18N
0464: rec.setParameters(new Object[] { this });
0465: TIMERS.log(rec);
0466: }
0467:
0468: facesConfigModel = new FacesConfigModel(this );
0469: setConfigModel(facesConfigModel);
0470:
0471: doModeling();
0472:
0473: projectBuiltQueryStatus = ProjectBuiltQuery.getStatus(project);
0474: projectBuiltQueryStatusChangeListener = new ChangeListener() {
0475: public void stateChanged(ChangeEvent changeEvent) {
0476: try {
0477: if (projectBuiltQueryStatus != null
0478: && projectBuiltQueryStatus.isBuilt()) {
0479: classPathChanged();
0480: SwingUtilities.invokeLater(new Runnable() {
0481: public void run() {
0482: List<FacesModel> visibleModels = getVisibleModels();
0483: if (visibleModels.size() > 0) {
0484: StatusDisplayer
0485: .getDefault()
0486: .setStatusText(
0487: NbBundle
0488: .getMessage(
0489: FacesModelSet.class,
0490: "MSG_RefreshingModels")); // NOI18N
0491: }
0492: try {
0493: // refresh visible models immediately and rest of them whenever they are visible
0494: for (Iterator i = getModelsMap()
0495: .values().iterator(); i
0496: .hasNext();) {
0497: FacesModel fm = (FacesModel) i
0498: .next();
0499: boolean immediate = false;
0500: if (visibleModels.size() > 0
0501: && (visibleModels
0502: .contains(fm) || !fm
0503: .isPageBean())) {
0504: immediate = true;
0505: }
0506: fm.refreshUnits(immediate);
0507: }
0508: } finally {
0509: if (visibleModels.size() > 0) {
0510: StatusDisplayer
0511: .getDefault()
0512: .setStatusText(
0513: NbBundle
0514: .getMessage(
0515: FacesModelSet.class,
0516: "MSG_RefreshingModelsDone")); // NOI18N
0517: }
0518: }
0519: }
0520: });
0521: }
0522: } catch (IllegalStateException ise) {
0523: ErrorManager.getDefault().notify(ise);
0524: }
0525: }
0526: };
0527: projectBuiltQueryStatus
0528: .addChangeListener(projectBuiltQueryStatusChangeListener);
0529: }
0530:
0531: private List<FacesModel> getVisibleModels() {
0532: List<FacesModel> visibleModels = new ArrayList<FacesModel>();
0533: for (Mode mode : WindowManager.getDefault().getModes()) {
0534: TopComponent tc = mode.getSelectedTopComponent();
0535: if (tc != null && tc.isOpened()
0536: && isMultiViewTopComponent(tc)) {
0537: TopComponent topComponent = getSelectedMultiView(tc);
0538: if (topComponent != null
0539: && isDesignerTopComponent(topComponent)) {
0540: DataObject dObj = topComponent.getActivatedNodes()[0]
0541: .getLookup().lookup(DataObject.class);
0542: visibleModels.add((FacesModel) getModel(dObj
0543: .getPrimaryFile()));
0544: }
0545: }
0546: }
0547: return visibleModels;
0548: }
0549:
0550: // Copied from org.netbeans.modules.visualweb.outline.OutlineManagerListener
0551: private static boolean isDesignerTopComponent(TopComponent tc) {
0552: return tc != null
0553: && "org.netbeans.modules.visualweb.designer.jsf.ui.JsfTopComponent"
0554: .equals(tc.getClass().getName()); // NOI18N
0555: }
0556:
0557: // Copied from org.netbeans.modules.visualweb.outline.OutlineManagerListener
0558: private static boolean isMultiViewTopComponent(TopComponent tc) {
0559: return tc != null
0560: && "org.netbeans.core.multiview.MultiViewCloneableTopComponent"
0561: .equals(tc.getClass().getName()); // NOI18N
0562: }
0563:
0564: // Copied from org.netbeans.modules.visualweb.outline.OutlineManagerListener
0565: private static TopComponent getSelectedMultiView(TopComponent tc) {
0566: for (TopComponent containedTC : findDescendantsOfTopComponent(tc)) {
0567: if (containedTC.isVisible()) { // XXX Means is selected in that multiview (terrible hack)
0568: return containedTC;
0569: }
0570: }
0571: return null;
0572: }
0573:
0574: // Copied from org.netbeans.modules.visualweb.outline.OutlineManagerListener
0575: private static TopComponent[] findDescendantsOfTopComponent(
0576: Container parent) {
0577: List<TopComponent> list = new ArrayList<TopComponent>();
0578: for (Component child : parent.getComponents()) {
0579: if (child instanceof TopComponent) {
0580: list.add((TopComponent) child);
0581: continue;
0582: }
0583: if (child instanceof Container) {
0584: list
0585: .addAll(java.util.Arrays
0586: .asList(findDescendantsOfTopComponent((Container) child)));
0587: }
0588: }
0589: return list.toArray(new TopComponent[0]);
0590: }
0591:
0592: private void doModeling() {
0593: //In case of new project, we need to model all the managed beans in order
0594: //to generate the cross referencing accessors
0595: Object newProject = project.getProjectDirectory().getAttribute(
0596: "NewProject"); //NOI18N
0597: if (newProject instanceof Boolean && (Boolean) newProject) {
0598: //Sync all models
0599: try {
0600: syncAll();
0601: } finally {
0602: try {
0603: //Reset the attribute to prevent initial modeling during the startup
0604: project.getProjectDirectory().setAttribute(
0605: "NewProject", null); //NOI18N
0606: } catch (IOException ioe) {
0607: assert Trace
0608: .trace(this .getClass(),
0609: "Failed to reset the attribute: "
0610: + project); //NOI18N
0611: }
0612: }
0613: //Remove any dead ones that aborted opening.
0614: for (Iterator i = models.values().iterator(); i.hasNext();) {
0615: Model m = (Model) i.next();
0616: if (!m.isValid())
0617: i.remove();
0618: }
0619:
0620: // run flush once in case any models self-adjusted themselves
0621: flushAll();
0622: // save the files to prevent them being open unsaved
0623: saveAll();
0624: }
0625: }
0626:
0627: /**
0628: *
0629: */
0630: public void destroy() {
0631: // Prevent NPE
0632: if (facesContainer != null) {
0633: facesContainer.destroy();
0634: }
0635: if (projectBuiltQueryStatus != null) {
0636: projectBuiltQueryStatus
0637: .removeChangeListener(projectBuiltQueryStatusChangeListener);
0638: }
0639: projectBuiltQueryStatusChangeListener = null;
0640: projectBuiltQueryStatus = null;
0641: super .destroy();
0642: }
0643:
0644: //------------------------------------------------------------------------------------ Accessors
0645:
0646: /**
0647: * @return
0648: */
0649: public FacesContainer getFacesContainer() {
0650: if (facesContainer == null) {
0651: //long start = System.currentTimeMillis();
0652: boolean isPortlet = false;
0653: if (project != null
0654: && JsfProjectUtils.getPortletSupport(project) != null) {
0655: isPortlet = true;
0656: }
0657: facesContainer = new FacesContainer(
0658: getProjectClassLoader(), isPortlet);
0659: //long duration = System.currentTimeMillis() - start;
0660: //System.err.println("FMS: FacesContainer initialize time: " + duration + "ms");
0661: }
0662: return facesContainer;
0663: }
0664:
0665: /**
0666: * @return
0667: */
0668: public FacesConfigModel getFacesConfigModel() {
0669: return facesConfigModel;
0670: }
0671:
0672: /**
0673: * @return
0674: */
0675: public FacesModel[] getFacesModels() {
0676: //!CQ TODO: later, these might not all be FacesModels. Will need to use an iterator
0677: return (FacesModel[]) getModelsMap().values().toArray(
0678: FacesModel.EMPTY_ARRAY);
0679: }
0680:
0681: /*
0682: * Override in order to ensure that if a .java file object is passed, that
0683: * we will be able to return the model which is keyed under the .jsp file.
0684: */
0685: public Model getModel(FileObject file) {
0686: Model model = super .getModel(file);
0687: if (model == null) {
0688: FileObject jspFile = FacesModel.getJspForJava(file);
0689: if (jspFile != null)
0690: model = super .getModel(jspFile);
0691: }
0692: return model;
0693: }
0694:
0695: /**
0696: * Get the FacesModel for a given FileObject iff the file is modeled. Allow for either file to
0697: * be passed to look up a paired file model.
0698: *
0699: * @param file object
0700: * @return the FacesModel for a given FileObject
0701: */
0702: public FacesModel getFacesModel(FileObject file) {
0703: FacesModel model = (FacesModel) getModel(file);
0704: if (model != null) {
0705: model.sync();
0706: }
0707: return model;
0708: }
0709:
0710: /**
0711: * Get the FacesModel for a given FileObject iff the file is modeled. Allow for either file to
0712: * be passed to look up a paired file model.
0713: *
0714: * @param file object
0715: * @return the FacesModel for a given FileObject
0716: */
0717: public FacesModel getFacesModel(String beanName) {
0718: if (beanName == null)
0719: return null;
0720: for (Iterator iterator = getModelsMap().values().iterator(); iterator
0721: .hasNext();) {
0722: Model model = (Model) iterator.next();
0723: if (model instanceof FacesModel) {
0724: FacesModel facesModel = (FacesModel) model;
0725: if (beanName.equals(facesModel.getBeanName()))
0726: return facesModel;
0727: }
0728: }
0729: return null;
0730: }
0731:
0732: //----------------------------------------------------------------------------- Model processing
0733:
0734: /**
0735: * @param oldname
0736: * @param newname
0737: */
0738: public void updateBeanElReferences(String oldname, String newname) {
0739: FacesModel[] fms = getFacesModels();
0740: for (int mi = 0; mi < fms.length; mi++) {
0741: LiveUnit lu = fms[mi].getLiveUnit();
0742: if (lu != null) {
0743: ArrayList beans = lu.getBeansList();
0744: for (int bi = 0, n = beans.size(); bi < n; bi++) {
0745: DesignProperty[] props = ((DesignBean) beans
0746: .get(bi)).getProperties();
0747: for (int pi = 0; pi < props.length; pi++) {
0748: String ps = props[pi].getValueSource();
0749: if (ps != null) {
0750: String newps = ElAttrUpdater.update(ps,
0751: oldname, newname);
0752: if (newps != null)
0753: props[pi].setValueSource(newps);
0754: }
0755: }
0756: }
0757: }
0758: }
0759: }
0760:
0761: /**
0762: * @param oldname
0763: */
0764: public void removeBeanElReferences(String oldname) {
0765: String match = "#{" + oldname;
0766: FacesModel[] fms = getFacesModels();
0767: for (int mi = 0; mi < fms.length; mi++) {
0768: LiveUnit lu = fms[mi].getLiveUnit();
0769: if (lu != null) {
0770: DesignBean[] beans = lu.getBeans();
0771: ArrayList beansList = lu.getBeansList();
0772: for (int bi = 0; bi < beans.length; bi++) {
0773: //Make sure the bean is not removed from the list as a result of unset
0774: if (beansList.indexOf(beans[bi]) != -1) {
0775: DesignProperty[] props = beans[bi]
0776: .getProperties();
0777: for (int pi = 0; pi < props.length; pi++) {
0778: String ps = props[pi].getValueSource();
0779: if (ps != null && ps.contains(match))
0780: props[pi].unset();
0781: }
0782: }
0783: }
0784: }
0785: }
0786: }
0787:
0788: public Collection getBeanNamesToXRef(ManagedBean.Scope scope,
0789: FacesModel facesModel) {
0790: ArrayList list = new ArrayList();
0791: if (scope == null)
0792: return list;
0793: FacesModel[] bModels = getFacesModels();
0794: for (int i = 0; i < bModels.length; i++) {
0795: if (isModelToXRef(facesModel, scope, bModels[i])) {
0796: list.add(bModels[i].getBeanName());
0797: }
0798: }
0799: return list;
0800: }
0801:
0802: private boolean isModelToXRef(FacesModel fromModel,
0803: ManagedBean.Scope fromScope, FacesModel toModel) {
0804: // TODO add asserts
0805: if (!toModel.isBusted()) {
0806: String toName = toModel.getBeanName();
0807: if (toName != null) {
0808: ManagedBean toMb = getFacesConfigModel()
0809: .getManagedBean(toName);
0810: if (toMb != null) {
0811: ManagedBean.Scope toScope = toMb
0812: .getManagedBeanScope();
0813: boolean include = false;
0814: //Page and Request beans are of same scope, but we still
0815: //need request bean accessors in page bean
0816: if (fromModel.isPageBean())
0817: include = toScope.compareTo(fromScope) >= 0;
0818: else
0819: include = toScope.compareTo(fromScope) > 0;
0820: //No page bean accessors are allowed
0821: if (include && !toModel.isPageBean()) {
0822: return true;
0823: }
0824: }
0825: }
0826: }
0827: return false;
0828: }
0829:
0830: //------------------------------------- DesignProject & FacesDesignProject implementation
0831: /**
0832: * Add a property change listener to the design project so that it could fire
0833: * events such as classloader changed.
0834: */
0835: public void addPropertyChangeListener(
0836: PropertyChangeListener propChangeListener) {
0837: propertyChangeSupport
0838: .addPropertyChangeListener(propChangeListener);
0839: }
0840:
0841: /**
0842: * Remove property change listener.
0843: */
0844: public void removePropertyChangeListener(
0845: PropertyChangeListener propChangeListener) {
0846: propertyChangeSupport
0847: .removePropertyChangeListener(propChangeListener);
0848: }
0849:
0850: public ClassLoader getContextClassLoader() {
0851: return getProjectClassLoader();
0852: }
0853:
0854: /*
0855: * @see com.sun.rave.designtime.DesignProject#getDesignContexts()
0856: */
0857: public DesignContext[] getDesignContexts() {
0858: syncAll();
0859: FacesModel[] models = getFacesModels();
0860: if (models != null && models.length > 0) {
0861: ArrayList units = new ArrayList();
0862: for (int i = 0; i < models.length; i++) {
0863: FacesModel model = models[i];
0864: if (model.isValid() && !model.isBusted()) {
0865: LiveUnit lu = models[i].getLiveUnit();
0866: if (lu != null)
0867: units.add(lu);
0868: }
0869: }
0870: return (DesignContext[]) units.toArray(new LiveUnit[units
0871: .size()]);
0872: }
0873: return new DesignContext[0];
0874: }
0875:
0876: public DesignContext findDesignContext(String beanName) {
0877: ManagedBean mb = getFacesConfigModel().getManagedBean(beanName);
0878: if (mb != null) {
0879: return findDesignContext(mb, false);
0880: }
0881: return null;
0882: }
0883:
0884: public DesignContext findDesignContext(ManagedBean mb,
0885: boolean ignorePage) {
0886: FacesModel facesModel = null;
0887: //getFacesModel(String beanName) relies on java file, in case of
0888: //page bean, java file may not be set if the model is not synced yet
0889: //Therefore, try to get the model by bean name, if it fails then the
0890: //managed bean should be a page and it is handled next
0891: facesModel = getFacesModel(mb.getManagedBeanName());
0892: if (facesModel != null && facesModel.isPageBean() && ignorePage) {
0893: return null;
0894: }
0895:
0896: if (!ignorePage && facesModel == null) {
0897: String javaFileName = mb.getManagedBeanClass().replace('.',
0898: '/')
0899: + ".java"; //NOI18N;
0900: Sources sources = ProjectUtils.getSources(getProject());
0901: SourceGroup groups[] = sources.getSourceGroups("java");
0902: FileObject javaFile = null;
0903: for (int i = 0; i < groups.length; i++) {
0904: SourceGroup group = groups[i];
0905: FileObject sourceFolder = group.getRootFolder();
0906: javaFile = sourceFolder.getFileObject(javaFileName);
0907: if (javaFile != null) {
0908: //Check if it is a page bean if it is to be ignored
0909: FileObject jspFile = JsfProjectUtils
0910: .getJspForJava(javaFile);
0911: if (jspFile != null) {
0912: facesModel = getFacesModel(jspFile);
0913: break;
0914: }
0915: }
0916: }
0917: }
0918:
0919: if (facesModel != null) {
0920: facesModel.sync();
0921: if (facesModel.isValid() && !facesModel.isBusted()) {
0922: return facesModel.getLiveUnit();
0923: }
0924: }
0925: return null;
0926: }
0927:
0928: public DesignContext[] findDesignContexts(String[] scopes) {
0929: Collection scopeList = Arrays.asList(scopes);
0930: FacesConfigModel facesConfigModel = getFacesConfigModel();
0931: ManagedBean[] mbs = facesConfigModel.getManagedBeans();
0932: List dcs = new ArrayList();
0933: for (int i = 0; i < mbs.length; i++) {
0934: if (scopeList.contains(mbs[i].getManagedBeanScope()
0935: .toString())) {
0936: boolean ignorePage = false;
0937: if (mbs[i].getManagedBeanScope().equals(
0938: ManagedBean.Scope.REQUEST)) {
0939: ignorePage = true;
0940: }
0941: DesignContext dc = findDesignContext(mbs[i], ignorePage);
0942: if (dc != null)
0943: dcs.add(dc);
0944: }
0945: }
0946:
0947: return (DesignContext[]) dcs.toArray(new LiveUnit[dcs.size()]);
0948: }
0949:
0950: /**
0951: * Creates a new DesignContext (backing file) in this project.
0952: *
0953: * @param className The desired fully-qualified class name for the file
0954: * @param baseClass The desired base class for the file
0955: * @param contextData A Map of context data to apply to the newly created context file
0956: * @return The newly created DesignContext, or null if the operation was unsuccessful
0957: */
0958: public DesignContext createDesignContext(String className,
0959: Class baseClass, Map contextData) {
0960: //!JOE: TODO: create a new managed bean (managed-beans.xml) and put in the scope
0961: // defined by user: contextData.get(Constants.ContextData.SCOPE)
0962: // !EAT TODO: discussions on this with Joe
0963: return null;
0964: }
0965:
0966: protected boolean removeUnits(final SourceUnit[] units) {
0967: boolean result = true;
0968: boolean removeFile = true;
0969:
0970: //If any of the files are marked non sharable(for example if there are
0971: //conflicts during CVS update), mark a flag to indicate that the
0972: //DataObjects should not be deleted
0973: for (int i = 0; i < units.length; i++) {
0974: SourceUnit unit = units[i];
0975: if (unit != null) {
0976: DataObject object = unit.getDataObject();
0977: if (object != null) {
0978: FileObject fObj = object.getPrimaryFile();
0979: if (fObj != null
0980: && SharabilityQuery.getSharability(FileUtil
0981: .toFile(fObj)) == SharabilityQuery.NOT_SHARABLE) {
0982: removeFile = false;
0983: break;
0984: }
0985: }
0986: }
0987: }
0988:
0989: // Bug Fix# 107080
0990: // Handle folder rename case
0991: if (removeFile) {
0992: FileObject javaFile = null;
0993: FileObject markupFile = null;
0994: for (int i = 0; i < units.length; i++) {
0995: SourceUnit unit = units[i];
0996: if (unit instanceof JavaUnit) {
0997: javaFile = unit.getFileObject();
0998: } else if (unit instanceof MarkupUnit) {
0999: markupFile = unit.getFileObject();
1000: }
1001: }
1002: if (javaFile != null && markupFile != null) {
1003: // Delete files only if the jsp and java file correspond to each other
1004: if (!javaFile.equals(JsfProjectUtils
1005: .getJavaForJsp(markupFile))) {
1006: removeFile = false;
1007: }
1008: }
1009: }
1010:
1011: for (int i = 0; i < units.length; i++) {
1012: SourceUnit unit = units[i];
1013: if (unit != null) {
1014: // save before the delete, to avoid FileAlreadyLockedException (IZ 101853)
1015: unit.save();
1016: unit.destroy();
1017: DataObject object = unit.getDataObject();
1018: if (removeFile && object != null && object.isValid()) {
1019: try {
1020: object.delete();
1021: } catch (IOException ex) {
1022: ErrorManager.getDefault().notify(ex);
1023: result = false;
1024: }
1025: }
1026: }
1027: }
1028: return result;
1029: }
1030:
1031: /**
1032: * Removes an existing DesignContext (backing file) from this project.
1033: *
1034: * @param context The desired DesignContext to remove from the project
1035: * @return true if the operation was successful, false if not
1036: */
1037: public boolean removeDesignContext(DesignContext context) {
1038: // !EAT TODO: need to look into issues of deleting the file actually being worked on ?
1039: // Should delete be done async, but then how to handle return result
1040: // remove a managed bean from the project (and managed-beans.xml)
1041: if (context == null)
1042: return false;
1043:
1044: FacesModel model = ((LiveUnit) context).getModel();
1045: boolean removed = removeUnits(new SourceUnit[] {
1046: model.getJavaUnit(), model.getMarkupUnit() });
1047: if (!removed)
1048: return false;
1049: String beanName = model.getBeanName();
1050: if (beanName != null) {
1051: FacesConfigModel facesConfigModel = ((FacesModelSet) model
1052: .getOwner()).getFacesConfigModel();
1053: ManagedBean mb = facesConfigModel.getManagedBean(beanName);
1054: if (mb != null)
1055: facesConfigModel.removeManagedBean(mb);
1056: }
1057: models.remove(model);
1058: return true;
1059: }
1060:
1061: //----------------------------------------------------------------------------- Resource Methods
1062:
1063: /**
1064: * <p>Returns the set of top-level resources in this project as an array of local resource
1065: * identifiers. The URIs are paths from the project root, including folder hiearchy within the
1066: * project. Use <code>getResourceFile(URI)</code> to retrieve a File object for a particular
1067: * resource in the project.</p>
1068: *
1069: * @param rootPath The root path to fetch resources underneath. Passing <code>null</code> will
1070: * start at the root of the project.
1071: * @param recurseFolders <code>true</code> to include the sub-resources inside of any folders
1072: * @return A URI[] representing all the resource files under the specified root path
1073: */
1074: public URI[] getResources(URI folderUri, boolean recurseFolders) {
1075: if (folderUri == null)
1076: folderUri = getProjectDirectoryUri();
1077: FileObject folder = resolveToFileObject(folderUri);
1078: if (folder == null)
1079: return new URI[0];
1080: Enumeration folderEnum = folder.getChildren(recurseFolders);
1081: ArrayList list = new ArrayList();
1082: while (folderEnum.hasMoreElements()) {
1083: FileObject fileObject = (FileObject) folderEnum
1084: .nextElement();
1085: URI uri = relativize(fileObject);
1086: if (uri != null)
1087: list.add(uri);
1088: }
1089: URI[] result = new URI[list.size()];
1090: list.toArray(result);
1091: return result;
1092: }
1093:
1094: /**
1095: * Returns a File object containing the specified resource.
1096: *
1097: * @param resourceUri The desired project relative resource uri to fetch a file object
1098: * @return A File object containing the project resource
1099: */
1100: public File getResourceFile(URI resourceUri) {
1101: FileObject fileObject = resolveToFileObject(resourceUri);
1102: if (fileObject == null)
1103: return null;
1104: return FileUtil.toFile(fileObject);
1105: }
1106:
1107: /**
1108: * Copies a resource into this project, and converts the external URL into a local URI
1109: * (resource identifier string).
1110: *
1111: * @param sourceUrl A URL pointing to the desired external resource
1112: * @param targetUri The desired resource URI (path) within the project directory
1113: * @return The resulting project relative resource uri (resourceUri)
1114: * @throws IOException if the resource cannot be copied
1115: */
1116: public URI addResource(URL sourceUrl, URI targetUri)
1117: throws IOException {
1118: FileObject source = resolveToFileObject(sourceUrl);
1119: if (source == null)
1120: return null;
1121: URI resolvedUri = resolveToUri(targetUri);
1122: File targetFile = new File(resolvedUri);
1123: File parentFile = targetFile.getParentFile();
1124: if (!parentFile.exists())
1125: parentFile.mkdirs();
1126: FileObject parentFileObject = FileUtil.toFileObject(parentFile);
1127: if (parentFileObject == null)
1128: return null;
1129: // Extract the extension part to fit the NB API below
1130: String name = targetFile.getName();
1131: String extension = "";
1132: int index = name.lastIndexOf('.');
1133: if (index > 0) {
1134: extension = name.substring(index + 1);
1135: name = name.substring(0, index);
1136: }
1137: FileObject copy = source
1138: .copy(parentFileObject, name, extension);
1139: URI uri = relativize(copy);
1140: return uri;
1141: }
1142:
1143: public FileObject getProjectDirectory() {
1144: return getProject().getProjectDirectory();
1145: }
1146:
1147: public FileObject getDocumentDirectory() {
1148: return JsfProjectUtils.getDocumentRoot(getProject());
1149: }
1150:
1151: protected URI getProjectDirectoryUri() {
1152: try {
1153: URI projectDirectoryUri = new URI(getProject()
1154: .getProjectDirectory().getURL().toExternalForm());
1155: return projectDirectoryUri;
1156: } catch (URISyntaxException e) {
1157: assert Trace.trace(this .getClass(), e);
1158: return null;
1159: } catch (FileStateInvalidException e) {
1160: assert Trace.trace(this .getClass(), e);
1161: return null;
1162: }
1163: }
1164:
1165: public URI relativize(FileObject file) {
1166: URI projectDirectoryUri = getProjectDirectoryUri();
1167: if (projectDirectoryUri == null)
1168: return null;
1169: try {
1170: URI fileUri = new URI(file.getURL().toExternalForm());
1171: URI uri = projectDirectoryUri.relativize(fileUri);
1172: return uri;
1173: } catch (FileStateInvalidException e) {
1174: assert Trace.trace(this .getClass(), e);
1175: } catch (URISyntaxException e) {
1176: assert Trace.trace(this .getClass(), e);
1177: }
1178: return null;
1179: }
1180:
1181: /**
1182: * Return a URI which provides a path to get to file, from relativeTo.
1183: *
1184: * @param file
1185: * @param relativeTo
1186: * @return
1187: */
1188: public URI relativize(FileObject file, FileObject relativeTo) {
1189: if (file == null || relativeTo == null)
1190: return null;
1191: try {
1192: URI fileUri = new URI(file.getURL().toExternalForm());
1193: URI relativeToUri = new URI(relativeTo.getURL()
1194: .toExternalForm());
1195: return relativeToUri.relativize(fileUri);
1196: } catch (URISyntaxException e) {
1197: assert Trace.trace(this .getClass(), e);
1198: return null;
1199: } catch (FileStateInvalidException e) {
1200: assert Trace.trace(this .getClass(), e);
1201: return null;
1202: }
1203: }
1204:
1205: protected FileObject resolveToFileObject(URI uri) {
1206: if (uri == null)
1207: return null;
1208: URL url = resolveToUrl(uri);
1209: if (url == null)
1210: return null;
1211: FileObject file = resolveToFileObject(url);
1212: return file;
1213: }
1214:
1215: protected FileObject resolveToFileObject(URL url) {
1216: if (url == null)
1217: return null;
1218: FileObject file = URLMapper.findFileObject(url);
1219: return file;
1220: }
1221:
1222: protected URI resolveToUri(URI uri) {
1223: URL url = resolveToUrl(uri);
1224: if (url == null)
1225: return null;
1226: try {
1227: URI result = new URI(url.toExternalForm());
1228: return result;
1229: } catch (URISyntaxException e) {
1230: assert Trace.trace(this .getClass(), e);
1231: return null;
1232: }
1233: }
1234:
1235: protected URL resolveToUrl(URI uri) throws IllegalArgumentException {
1236: if (uri == null)
1237: return null;
1238: try {
1239: URI projectDirectoryUri = getProjectDirectoryUri();
1240: URI resolvedUri = projectDirectoryUri.resolve(uri);
1241: URL url = resolvedUri.toURL();
1242: return url;
1243: } catch (MalformedURLException e) {
1244: assert Trace.trace(this .getClass(), e);
1245: return null;
1246: }
1247: }
1248:
1249: /**
1250: * Removes a resource from the project directory.
1251: *
1252: * @param resourceUri The desired resource to remove from the project
1253: * @return boolean <code>true</code> if the resource was successfully removed,
1254: * <code>false</code> if not
1255: */
1256: public boolean removeResource(URI resourceUri) {
1257: //!EAT TODO: we need to add some security to this ? Any file can be removed ???
1258: FileObject file = resolveToFileObject(resourceUri);
1259: if (file == null)
1260: return false;
1261: try {
1262: file.delete();
1263: return true;
1264: } catch (IOException e) {
1265: assert Trace.trace(this .getClass(), e);
1266: return false;
1267: }
1268: }
1269:
1270: HashMap userData = new HashMap();
1271:
1272: /*
1273: * @see com.sun.rave.designtime.DesignProject#setProjectData(java.lang.String, java.lang.Object)
1274: */
1275: public void setProjectData(String key, Object data) {
1276: userData.put(key, data);
1277: // PROJECTTODO2: Still need to put this on project save not on set.
1278: AuxiliaryConfiguration config = (AuxiliaryConfiguration) project
1279: .getLookup().lookup(AuxiliaryConfiguration.class);
1280: assert config != null : "project has no AuxiliaryConfiguration";
1281: DocumentBuilderFactory docFactory = DocumentBuilderFactory
1282: .newInstance();
1283: try {
1284: // !EAT TODO move this to flushProjectData()
1285: DocumentBuilder builder = docFactory.newDocumentBuilder();
1286: Document doc = builder.newDocument();
1287: Element element = doc.createElementNS(
1288: PROJECTDATA_ELEMENT_NAMESPACE,
1289: PROJECTDATA_ELEMENT_KEY_PREFIX + key);
1290: String string = data != null ? data.toString() : null;
1291: Node node = doc.createCDATASection(string);
1292: element.appendChild(node);
1293: doc.appendChild(element);
1294: config.putConfigurationFragment(element, false);
1295: } catch (Exception e) {
1296: throw new RuntimeException(e);
1297: }
1298: return;
1299: }
1300:
1301: /*
1302: * @see com.sun.rave.designtime.DesignProject#getProjectData(java.lang.String)
1303: */
1304: public Object getProjectData(String key) {
1305: if (userData.containsKey(key)) {
1306: Object result = userData.get(key);
1307: return String.valueOf(result);
1308: }
1309: // if (JsfProjectUtils.isEnabled()) {
1310: AuxiliaryConfiguration config = (AuxiliaryConfiguration) project
1311: .getLookup().lookup(AuxiliaryConfiguration.class);
1312: assert config != null : "project has no AuxiliaryConfiguration";
1313: Element element = config.getConfigurationFragment(
1314: PROJECTDATA_ELEMENT_KEY_PREFIX + key,
1315: PROJECTDATA_ELEMENT_NAMESPACE, false);
1316: if (element == null)
1317: return null;
1318: String result = element.getFirstChild().getNodeValue();
1319: userData.put(key, result);
1320: return result;
1321: // }
1322: // return project.getProperty(key);
1323: }
1324:
1325: /**
1326: *
1327: */
1328: protected void flushProjectData() {
1329: // PROJECTTODO2: cleanup, this needs to get called somehow
1330: // no-op until I move the code from setProjectData to here and have this called somehow
1331: // This is code that existed prior to new project API
1332: // for (Iterator i = userData.entrySet().iterator(); i.hasNext(); ) {
1333: // Map.Entry entry = (Map.Entry)i.next();
1334: // Object data = entry.getValue();
1335: // Util.updateItemProperty(project, (String)entry.getKey(),
1336: // data != null ? data.toString() : null);
1337: // }
1338: }
1339:
1340: /*
1341: * @see com.sun.rave.designtime.DesignProject#setGlobalData(String, Object)
1342: * EAT: TODO: implement this! (was Ide.getIdeData())
1343: */
1344: public void setGlobalData(String key, Object data) {
1345: }
1346:
1347: /*
1348: * @see com.sun.rave.designtime.DesignProject#getGlobalData(String)
1349: * EAT: TODO: implement this! (was Ide.setIdeData())
1350: */
1351: public Object getGlobalData(String key) {
1352: return null;
1353: }
1354:
1355: //---------------------------------------------------------------------------------- DisplayInfo
1356:
1357: /*
1358: * @see com.sun.rave.designtime.DisplayInfo#getDisplayName()
1359: */
1360: public String getDisplayName() {
1361: return ProjectUtils.getInformation(project).getDisplayName();
1362: }
1363:
1364: /*
1365: * @see com.sun.rave.designtime.DisplayInfo#getDescription()
1366: */
1367: public String getDescription() {
1368: return getDisplayName();
1369: }
1370:
1371: public Image getLargeIcon() {
1372: return null;
1373: }
1374:
1375: public Image getSmallIcon() {
1376: return null;
1377: }
1378:
1379: public String getHelpKey() {
1380: return null;
1381: }
1382:
1383: /**
1384: * Respond to changes in the project class path by updating the models.
1385: * @see com.sun.rave.project.model.ProjectContentChangeListener#classPathChanged(com.sun.rave.project.model.ProjectContentChangeEvent)
1386: * PROJECTTODO2: I dont get this event anymore
1387: */
1388: public void classPathChanged() {
1389: ClassLoader oldClassLoader = classLoader;
1390: super .classPathChanged();
1391:
1392: // XXX why called again. Already called in super.classPathChanged()
1393: ClassLoader classLoader = getProjectClassLoader();
1394: for (Iterator i = getModelsMap().values().iterator(); i
1395: .hasNext();)
1396: ((FacesModel) i.next()).updateClassLoader(classLoader);
1397: if (facesContainer != null) {
1398: facesContainer.setClassLoader(classLoader);
1399: }
1400: propertyChangeSupport.firePropertyChange(
1401: FacesDesignProject.CONTEXT_CLASS_LOADER,
1402: oldClassLoader, classLoader); //NOI18N
1403: }
1404:
1405: //--------------------------------------------------------------------------- DesignProject Events
1406:
1407: protected final ArrayList listeners = new ArrayList();
1408:
1409: /*
1410: * @see com.sun.rave.designtime.DesignProject#addDesignProjectListener(com.sun.rave.designtime.DesignProjectListener)
1411: */
1412: public void addDesignProjectListener(DesignProjectListener listener) {
1413: listeners.add(listener);
1414: }
1415:
1416: /*
1417: * @see com.sun.rave.designtime.DesignProject#removeDesignProjectListener(com.sun.rave.designtime.DesignProjectListener)
1418: */
1419: public void removeDesignProjectListener(
1420: DesignProjectListener listener) {
1421: listeners.remove(listener);
1422: }
1423:
1424: /*
1425: * @see com.sun.rave.designtime.DesignProject#getDesignProjectListeners()
1426: */
1427: public DesignProjectListener[] getDesignProjectListeners() {
1428: return (DesignProjectListener[]) listeners
1429: .toArray(new DesignProjectListener[listeners.size()]);
1430: }
1431:
1432: /**
1433: * A small hack to prevent the creation of contexts objects if there are no listeners,
1434: * such as project open time.
1435: *
1436: * @return
1437: */
1438: public boolean hasDesignProjectListeners() {
1439: return !listeners.isEmpty();
1440: }
1441:
1442: /**
1443: * @param context
1444: */
1445: protected void fireContextOpened(DesignContext context) {
1446: DesignProjectListener[] listeners = getDesignProjectListeners();
1447: for (int i = 0; i < listeners.length; i++) {
1448: listeners[i].contextOpened(context);
1449: }
1450: }
1451:
1452: /**
1453: * @param context
1454: */
1455: protected void fireContextClosed(DesignContext context) {
1456: DesignProjectListener[] listeners = getDesignProjectListeners();
1457: for (int i = 0; i < listeners.length; i++) {
1458: listeners[i].contextClosed(context);
1459: }
1460: }
1461:
1462: protected Collection evalOrderModels(Collection modelsToOrder) {
1463: FacesConfigModel facesConfigModel = getFacesConfigModel();
1464: if (facesConfigModel == null)
1465: return modelsToOrder;
1466: final HashMap modelsByName = new HashMap();
1467: for (Iterator iterator = modelsToOrder.iterator(); iterator
1468: .hasNext();) {
1469: FacesModel model = (FacesModel) iterator.next();
1470: String name = model.getBeanName();
1471: // this is to ensure that even models without names are included in modelsByName
1472: if (name == null)
1473: name = "### NO NAME ###";
1474: ArrayList list = (ArrayList) modelsByName.get(name);
1475: if (list == null) {
1476: list = new ArrayList();
1477: modelsByName.put(name, list);
1478: }
1479: list.add(model);
1480: }
1481: ArrayList orderedModels = new ArrayList(modelsToOrder.size());
1482: ManagedBean[] managedBeans = facesConfigModel.getManagedBeans();
1483: Arrays.sort(managedBeans, new Comparator() {
1484: public int compare(Object object1, Object object2) {
1485: ManagedBean managedBean1 = (ManagedBean) object1;
1486: ManagedBean managedBean2 = (ManagedBean) object2;
1487: int compare = managedBean1.getManagedBeanScope()
1488: .compareTo(managedBean2.getManagedBeanScope());
1489: if (compare != 0)
1490: return compare;
1491: if (managedBean1.getManagedBeanScope() != ManagedBean.Scope.REQUEST)
1492: return 0;
1493: ArrayList list1 = (ArrayList) modelsByName
1494: .get(managedBean1.getManagedBeanName());
1495: ArrayList list2 = (ArrayList) modelsByName
1496: .get(managedBean2.getManagedBeanName());
1497: if (list1 == null || list2 == null)
1498: return 0;
1499: FacesModel model1 = (FacesModel) list1.get(0);
1500: FacesModel model2 = (FacesModel) list2.get(0);
1501: if (model1.isPageBean() && model2.isPageBean())
1502: return 0;
1503: if (model1.isPageBean())
1504: return 1;
1505: return -1;
1506: }
1507: });
1508: for (int i = 0; i < managedBeans.length; i++) {
1509: ManagedBean ManagedBean = managedBeans[i];
1510: ArrayList list = (ArrayList) modelsByName.get(ManagedBean
1511: .getManagedBeanName());
1512: if (list != null) {
1513: orderedModels.addAll(list);
1514: modelsByName.remove(ManagedBean.getManagedBeanName());
1515: }
1516: }
1517: // Add non-pages first, in order to make sure ensurexref is done properly
1518: for (Iterator iterator = modelsByName.values().iterator(); iterator
1519: .hasNext();) {
1520: ArrayList list = (ArrayList) iterator.next();
1521: FacesModel model = (FacesModel) list.get(0);
1522: if (!model.isPageBean())
1523: orderedModels.addAll(list);
1524: }
1525: for (Iterator iterator = modelsByName.values().iterator(); iterator
1526: .hasNext();) {
1527: ArrayList list = (ArrayList) iterator.next();
1528: FacesModel model = (FacesModel) list.get(0);
1529: if (model.isPageBean())
1530: orderedModels.addAll(list);
1531: }
1532: return orderedModels;
1533: }
1534:
1535: public void removeModel(Model model) {
1536: LiveUnit liveUnit = null;
1537: if (model instanceof FacesModel) {
1538: FacesModel facesModel = (FacesModel) model;
1539: liveUnit = facesModel.getLiveUnit();
1540: removeDesignContext((DesignContext) liveUnit);
1541: }
1542: super .removeModel(model);
1543: }
1544:
1545: public FileObject getJavaRootFolder() {
1546: return JsfProjectUtils.getSourceRoot(getProject());
1547: }
1548:
1549: public FileObject getPageJavaRootFolder() {
1550: return JsfProjectUtils.getPageBeanRoot(getProject());
1551: }
1552:
1553: public FileObject getPageJspRootFolder() {
1554: return JsfProjectUtils.getDocumentRoot(getProject());
1555: }
1556:
1557: /**
1558: * Other can be a file in my web or java folder tree. Either
1559: * way I return the appropriate java one.
1560: * If in neither tree, return null.
1561: *
1562: * @param other
1563: * @return
1564: */
1565: public FileObject getJavaFolderFor(FileObject other, boolean tryHard) {
1566: if (other == null)
1567: return null;
1568: FileObject jspRoot = getPageJspRootFolder();
1569: String relativePath = FileUtil.getRelativePath(jspRoot, other);
1570: if (relativePath != null) {
1571: // File is in jsp root
1572: FileObject javaRoot = getPageJavaRootFolder();
1573: FileObject result = javaRoot.getFileObject(relativePath);
1574: if (result != null)
1575: return result;
1576: } else {
1577: FileObject javaRoot = getJavaRootFolder();
1578: if (FileUtil.isParentOf(javaRoot, other))
1579: return other;
1580: }
1581: if (!tryHard)
1582: return null;
1583: // Try a little harder to handle in-place edit where file object was renamed, but data objects not
1584: FileObject result = null;
1585: for (Iterator i = getModelsMap().values().iterator(); i
1586: .hasNext();) {
1587: Model model = (Model) i.next();
1588: if (model instanceof FacesModel) {
1589: FacesModel facesModel = (FacesModel) model;
1590: if (facesModel.getMarkupFile() != null
1591: && facesModel.getMarkupFile().getParent() == other) {
1592: return getJavaFolderFor(facesModel.getJavaFile()
1593: .getParent(), false);
1594: }
1595: if (facesModel.getJavaFile() != null
1596: && facesModel.getJavaFile().getParent() == other) {
1597: return getJavaFolderFor(facesModel.getJavaFile()
1598: .getParent(), false);
1599: }
1600: }
1601: }
1602: return result;
1603: }
1604:
1605: int counter = LOG_SYNC_ALLS ? 0 : 0; // Done this way to make sure it gets removed when the var is removed
1606: long startTime = LOG_SYNC_ALLS ? 0l : 0l; // Done this way to make sure it gets removed when the var is removed
1607:
1608: protected void syncAll() {
1609: if (LOG_SYNC_ALLS) {
1610: if (counter == 0) {
1611: startTime = System.currentTimeMillis();
1612: }
1613: counter++;
1614: System.out.println("SyncAll: " + counter);
1615: }
1616: super .syncAll();
1617: if (LOG_SYNC_ALLS) {
1618: System.out.println(" done SyncAll: time="
1619: + (System.currentTimeMillis() - startTime));
1620: }
1621: }
1622:
1623: }
|