001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.visualweb.insync.models;
042:
043: import java.io.IOException;
044: import java.net.MalformedURLException;
045: import java.net.URL;
046: import java.util.ArrayList;
047: import java.util.Collection;
048: import java.util.List;
049: import org.netbeans.modules.visualweb.insync.Model;
050: import org.netbeans.modules.visualweb.insync.UndoEvent;
051: import org.netbeans.modules.xml.xam.spi.Validation;
052: import org.netbeans.modules.xml.xam.spi.Validation.ValidationType;
053: import org.netbeans.modules.xml.xam.spi.Validator;
054: import org.openide.filesystems.FileObject;
055: import org.netbeans.modules.visualweb.extension.openide.util.Trace;
056: import org.netbeans.modules.visualweb.insync.ParserAnnotation;
057: import org.netbeans.modules.web.api.webmodule.WebModule;
058: import org.netbeans.modules.web.jsf.api.ConfigurationUtils;
059: import org.netbeans.modules.web.jsf.api.facesmodel.FacesConfig;
060: import org.netbeans.modules.web.jsf.api.facesmodel.JSFConfigModel;
061: import org.netbeans.modules.web.jsf.api.facesmodel.ManagedBean;
062: import org.openide.cookies.SaveCookie;
063: import org.openide.loaders.DataObject;
064: import org.netbeans.modules.xml.xam.Model.State;
065:
066: /**
067: * Wrapper class for all the faces config files in a project
068: */
069: public class FacesConfigModel extends Model {
070: WebModule webModule;
071:
072: //XAM AbstractModelFactory caches the XAM Model using WeakHashmap, wherein the value is a weak
073: //reference to XAM Model. Therefore it is the responsibility of clients to hold-on to XAM Model
074: //if they want to avoid re-creation of Model. Re-creation cost could be significant when insync
075: //calls getManagedBean many hundreds of times(see #125957). This logic indeed should go inside
076: //web/jsf but may not be implemented in 6.1 time frame. Temporarily we have a workaround, where-in
077: //we hold-on to XAM Models, note that we do not use these Models.
078: List<JSFConfigModel> configModels;
079:
080: //--------------------------------------------------------------------------------- Construction
081:
082: public FacesConfigModel(FacesModelSet owner) {
083: super (owner, owner.getProject().getProjectDirectory());
084: webModule = WebModule.getWebModule(owner.getProject()
085: .getProjectDirectory());
086: }
087:
088: /**
089: * @return default configuration file for the project
090: */
091: public FileObject getFile() {
092: FileObject[] configFiles = ConfigurationUtils
093: .getFacesConfigFiles(webModule);
094: if (configFiles.length > 0) {
095: assert Trace.trace("insync.faces.model",
096: "FCM.FacesConfigModel file:" + configFiles[0]);
097: return configFiles[0];
098: }
099: return null;
100: }
101:
102: private JSFConfigModel getDefaultFacesConfigModel() {
103: return ConfigurationUtils.getConfigModel(getFile(), true);
104: }
105:
106: //--------------------------------------------------------------------------------- MBean access
107:
108: public ManagedBean[] getManagedBeans() {
109: FileObject[] configs = ConfigurationUtils
110: .getFacesConfigFiles(webModule);
111: refreshJSFConfigModelReferences(configs);
112: List<ManagedBean> managedBeans = new ArrayList<ManagedBean>();
113: for (FileObject configFile : configs) {
114: JSFConfigModel model = ConfigurationUtils.getConfigModel(
115: configFile, true);
116: if (!isBusted(model)) {
117: managedBeans.addAll(model.getRootComponent()
118: .getManagedBeans());
119: }
120: }
121:
122: return managedBeans.toArray(new ManagedBean[0]);
123: }
124:
125: public ManagedBean getManagedBean(String name) {
126: FileObject[] configs = ConfigurationUtils
127: .getFacesConfigFiles(webModule);
128: refreshJSFConfigModelReferences(configs);
129: for (FileObject configFile : configs) {
130: JSFConfigModel model = ConfigurationUtils.getConfigModel(
131: configFile, true);
132: if (!isBusted(model)) {
133: Collection<ManagedBean> managedBeans = model
134: .getRootComponent().getManagedBeans();
135: for (ManagedBean managedBean : managedBeans) {
136: if (managedBean.getManagedBeanName().equals(name)) {
137: return managedBean;
138: }
139: }
140: }
141: }
142: return null;
143: }
144:
145: public FacesConfig getFacesConfigForManagedBean(String name) {
146: FileObject[] configs = ConfigurationUtils
147: .getFacesConfigFiles(webModule);
148: refreshJSFConfigModelReferences(configs);
149: for (FileObject configFile : configs) {
150: JSFConfigModel model = ConfigurationUtils.getConfigModel(
151: configFile, true);
152: if (!isBusted(model)) {
153: FacesConfig facesConfig = model.getRootComponent();
154: Collection<ManagedBean> managedBeans = facesConfig
155: .getManagedBeans();
156: for (ManagedBean managedBean : managedBeans) {
157: if (managedBean.getManagedBeanName().equals(name)) {
158: return facesConfig;
159: }
160: }
161: }
162: }
163: return null;
164: }
165:
166: private void refreshJSFConfigModelReferences(FileObject[] configs) {
167: List<JSFConfigModel> newConfigModels = new ArrayList<JSFConfigModel>();
168: try {
169: for (FileObject configFile : configs) {
170: JSFConfigModel model = ConfigurationUtils
171: .getConfigModel(configFile, true);
172: if (model != null) {
173: newConfigModels.add(model);
174: }
175: }
176: } finally {
177: configModels = newConfigModels;
178: }
179: }
180:
181: public ManagedBean ensureManagedBean(String name, String className,
182: ManagedBean.Scope scope) {
183: ManagedBean mb = getManagedBean(name);
184: if (mb == null) {
185: mb = addManagedBean(name, className, scope);
186: assert Trace.trace("insync.faces.model",
187: "FCM.ensureManagedBean added:" + mb);
188: }
189: return mb;
190: }
191:
192: /*
193: public void repackageManagedBean(String oldName, String newName, String oldPkg, String newPkg) {
194: ManagedBean mb = getManagedBean(oldName);
195: if (mb == null) {
196: // There is no managed bean by that name;
197: return;
198: }
199: mb.setName(newName);
200: String clazz = mb.getClazz();
201: clazz = clazz.replaceFirst(oldPkg, newPkg);
202: mb.setClazz(clazz);
203: // !EAT TODO Why is this not done through dirty / sync ?
204: flush();
205: }
206: * */
207:
208: public ManagedBean addManagedBean(String name, String className,
209: ManagedBean.Scope scope) {
210: JSFConfigModel model = getDefaultFacesConfigModel();
211: if (!isBusted(model)) {
212: ManagedBean bean = model.getFactory().createManagedBean();
213: bean.setManagedBeanName(name);
214: bean.setManagedBeanClass(className);
215: bean.setManagedBeanScope(scope);
216: model.startTransaction();
217: model.getRootComponent().addManagedBean(bean);
218: model.endTransaction();
219: save(model);
220: return bean;
221: }
222: return null;
223: }
224:
225: public void removeManagedBean(ManagedBean bean) {
226: //Get the model in which the bean to be removed exists
227: JSFConfigModel model = bean.getParent().getModel();
228: if (!isBusted(model)) {
229: model.startTransaction();
230: model.getRootComponent().removeManagedBean(bean);
231: model.endTransaction();
232: save(model);
233: }
234: }
235:
236: public static String getPackageName(ManagedBean bean) {
237: String clazz = bean.getManagedBeanClass();
238: int term = clazz.lastIndexOf('.');
239: return term >= 0 ? clazz.substring(0, term) : "";
240: }
241:
242: public void save(JSFConfigModel model) {
243: DataObject dObj = (DataObject) model.getModelSource()
244: .getLookup().lookup(DataObject.class);
245: if (dObj != null) {
246: SaveCookie saveCookie = (SaveCookie) dObj.getLookup()
247: .lookup(SaveCookie.class);
248: if (saveCookie != null) {
249: try {
250: saveCookie.save();
251: } catch (IOException ioe) {
252: throw new RuntimeException(ioe);
253: }
254: }
255: }
256: }
257:
258: public boolean isBusted() {
259: FileObject[] configs = ConfigurationUtils
260: .getFacesConfigFiles(webModule);
261: for (FileObject configFile : configs) {
262: JSFConfigModel model = ConfigurationUtils.getConfigModel(
263: configFile, true);
264: if (isBusted(model)) {
265: return true;
266: }
267: }
268: return false;
269: }
270:
271: private boolean isBusted(JSFConfigModel model) {
272: return model.getState() != State.VALID ? true : false;
273: }
274:
275: public ParserAnnotation[] getErrors() {
276: FileObject[] configs = ConfigurationUtils
277: .getFacesConfigFiles(webModule);
278: List<ParserAnnotation> parserAnnotationsList = new ArrayList<ParserAnnotation>();
279: for (FileObject configFile : configs) {
280: JSFConfigModel model = ConfigurationUtils.getConfigModel(
281: configFile, true);
282: if (model.getState() == State.NOT_WELL_FORMED) {
283: /*
284: Collection<? extends Validator> validators = Lookup.getDefault().lookupAll(Validator.class);
285: for(Validator validator : validators) {
286: if(validator != null) {
287: Validation validation = new Validation();
288: validator.validate(model, validation, ValidationType.COMPLETE);
289: for( Validator.ResultItem item : validation.getValidationResult()) {
290: ParserAnnotation annotation = new ParserAnnotation(item.getDescription(),
291: configFile, item.getLineNumber(), item.getColumnNumber());
292: parserAnnotationsList.add(annotation);
293: }
294: }
295: }
296: * */
297: //Temporarily indicate there is error in config file until we find out a
298: //way to get the errors in the config file
299: ParserAnnotation annotation = new ParserAnnotation(
300: "Error in config file", configFile, 1, 1);
301: parserAnnotationsList.add(annotation);
302: }
303: }
304: return parserAnnotationsList
305: .toArray(ParserAnnotation.EMPTY_ARRAY);
306: }
307:
308: //Dummy implementation of abstract methods
309: public UndoEvent writeLock(String description) {
310: return null;
311: }
312:
313: public void writeUnlock(UndoEvent event) {
314: }
315:
316: public boolean isWriteLocked() {
317: return false;
318: }
319:
320: protected void syncImpl() {
321: }
322:
323: public void saveUnits() {
324: }
325:
326: public void flushImpl() {
327: }
328:
329: public void flushNonJavaUnitsImpl() {
330: }
331: }
|