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:
042: /*
043: * DefaultProjectCatalogSupport.java
044: *
045: * Created on December 18, 2006, 3:55 PM
046: *
047: * To change this template, choose Tools | Template Manager
048: * and open the template in the editor.
049: */
050:
051: package org.netbeans.modules.xml.catalogsupport;
052:
053: import java.io.File;
054: import java.io.IOException;
055: import java.net.URI;
056: import java.net.URISyntaxException;
057: import java.util.ArrayList;
058: import java.util.Arrays;
059: import java.util.Set;
060: import java.util.StringTokenizer;
061: import org.netbeans.api.project.FileOwnerQuery;
062: import org.netbeans.api.project.Project;
063: import org.netbeans.api.project.ProjectUtils;
064: import org.netbeans.api.project.SourceGroup;
065: import org.netbeans.api.project.Sources;
066: import org.netbeans.modules.xml.catalogsupport.util.ProjectReferenceUtility;
067: import org.netbeans.modules.xml.retriever.catalog.CatalogEntry;
068: import org.netbeans.modules.xml.retriever.catalog.CatalogWriteModel;
069: import org.netbeans.modules.xml.retriever.catalog.CatalogWriteModelFactory;
070: import org.netbeans.modules.xml.xam.locator.CatalogModelException;
071: import org.netbeans.spi.project.SubprojectProvider;
072: import org.netbeans.spi.project.support.ant.AntProjectHelper;
073: import org.netbeans.spi.project.support.ant.PropertyUtils;
074: import org.netbeans.spi.project.support.ant.ReferenceHelper;
075: import org.openide.filesystems.FileObject;
076: import org.netbeans.modules.xml.retriever.catalog.ProjectCatalogSupport;
077: import org.openide.filesystems.FileUtil;
078:
079: /**
080: *
081: * @author Ajit
082: */
083: public class DefaultProjectCatalogSupport extends ProjectCatalogSupport {
084:
085: public Project project;
086: public AntProjectHelper helper;
087: public ReferenceHelper refHelper;
088:
089: /**
090: * Creates a new instance of DefaultProjectCatalogSupport
091: */
092: public DefaultProjectCatalogSupport(Project project) {
093: this (project, null, null);
094: }
095:
096: public DefaultProjectCatalogSupport(Project project,
097: AntProjectHelper helper, ReferenceHelper refHelper) {
098: this .project = project;
099: this .helper = helper;
100: this .refHelper = refHelper;
101: }
102:
103: public static DefaultProjectCatalogSupport getInstance(
104: FileObject source) {
105: Project owner = FileOwnerQuery.getOwner(source);
106: if (owner != null) {
107: DefaultProjectCatalogSupport support = (DefaultProjectCatalogSupport) owner
108: .getLookup().lookup(
109: DefaultProjectCatalogSupport.class);
110: if (support != null)
111: return support;
112: }
113: return new DefaultProjectCatalogSupport(owner);
114: }
115:
116: public boolean supportsCrossProject() {
117: return helper != null;
118: }
119:
120: public URI constructProjectProtocol(FileObject foTobeAddedInCat) {
121: Project owner = FileOwnerQuery.getOwner(foTobeAddedInCat);
122: if (owner != null) {
123: String ssp = getUsableProjectName(owner);
124: String fragment = getRelativePath(owner
125: .getProjectDirectory(), foTobeAddedInCat);
126: try {
127: return new URI(ProjectConstants.NBURI_SCHEME, ssp,
128: fragment);
129: } catch (URISyntaxException ex) {
130: }
131: }
132: return null;
133: }
134:
135: public boolean isProjectProtocol(URI uriStoredInCatFile) {
136: return ProjectConstants.NBURI_SCHEME.equals(uriStoredInCatFile
137: .getScheme());
138: }
139:
140: public FileObject resolveProjectProtocol(URI uriToBeResolved) {
141: if (supportsCrossProject()
142: && isProjectProtocol(uriToBeResolved)) {
143: String ssp = uriToBeResolved.getSchemeSpecificPart();
144: String targetPrjRelativeRoot = helper.getProperties(
145: AntProjectHelper.PROJECT_PROPERTIES_PATH)
146: .getProperty("project.".concat(ssp));
147: if (targetPrjRelativeRoot != null) {
148: File myPrjRoot = FileUtil.toFile(project
149: .getProjectDirectory());
150: File tgtPrjRoot = new File(myPrjRoot.toURI().resolve(
151: targetPrjRelativeRoot));
152: FileObject tgtPrjFobj = FileUtil.toFileObject(FileUtil
153: .normalizeFile(tgtPrjRoot));
154: return tgtPrjFobj.getFileObject(uriToBeResolved
155: .getFragment());
156: }
157: }
158: return null;
159: }
160:
161: public boolean needsCatalogEntry(FileObject source,
162: FileObject target) {
163: assert source != null && target != null;
164: // check if target belongs to different project or different source root
165: if (project != FileOwnerQuery.getOwner(target)) {
166: return true;
167: }
168:
169: FileObject folder = getSourceFolder(source);
170: if (folder != null && !FileUtil.isParentOf(folder, target)) {
171: return true;
172: }
173:
174: return false;
175: }
176:
177: public URI createCatalogEntry(FileObject source, FileObject target)
178: throws IOException, CatalogModelException {
179: assert source != null && target != null;
180: CatalogWriteModel cwm = CatalogWriteModelFactory.getInstance()
181: .getCatalogWriteModelForProject(
182: project.getProjectDirectory());
183: assert cwm != null;
184: Project targetProject = FileOwnerQuery.getOwner(target);
185: URI targetURI = null;
186: URI sourceURI = null;
187: try {
188: sourceURI = getReferenceURI(source, target);
189: } catch (URISyntaxException ex) {
190: return null;
191: }
192: if (project != targetProject) {
193: if (!getProjectReferences().contains(targetProject)
194: && supportsCrossProject()) {
195: ProjectReferenceUtility.addProjectReference(refHelper,
196: targetProject);
197: }
198: ;
199: targetURI = constructProjectProtocol(target);
200: } else {
201: try {
202: targetURI = new URI(getRelativePath(cwm
203: .getCatalogFileObject(), target));
204: } catch (URISyntaxException ex) {
205: return null;
206: }
207: }
208: cwm.addURI(sourceURI, targetURI);
209: return sourceURI;
210: }
211:
212: public URI getReferenceURI(FileObject source, FileObject target)
213: throws URISyntaxException {
214: Project targetProject = FileOwnerQuery.getOwner(target);
215: FileObject sourceFolder = getSourceFolder(source);
216: if (sourceFolder == null) {
217: throw new IllegalArgumentException(source.getPath()
218: + " is not in project source"); //NOI18N
219: }
220: String relPathToSrcGroup = getRelativePath(source.getParent(),
221: sourceFolder);
222: String relPathToSrcGroupWithSlash = relPathToSrcGroup.trim()
223: .equals("") ? "" : relPathToSrcGroup.concat("/");
224: if (project != targetProject) {
225: FileObject folder = getSourceFolder(targetProject, target);
226: if (folder == null) {
227: throw new IllegalArgumentException(target.getPath()
228: + " is not in target project source"); //NOI18N
229: }
230: String relPathFromTgtGroup = getRelativePath(folder, target);
231: return new URI(relPathToSrcGroupWithSlash.concat(
232: getUsableProjectName(targetProject)).concat("/")
233: .concat(relPathFromTgtGroup));
234: } else {
235: FileObject targetSourceFolder = getSourceFolder(target);
236: if (targetSourceFolder == null) {
237: throw new IllegalArgumentException(target.getPath()
238: + " is not in project source"); //NOI18N
239: }
240: String relPathFromTgtGroup = getRelativePath(
241: targetSourceFolder, target);
242: return new URI(relPathToSrcGroupWithSlash
243: .concat(relPathFromTgtGroup));
244: }
245: }
246:
247: public Set getProjectReferences() {
248: SubprojectProvider provider = (SubprojectProvider) project
249: .getLookup().lookup(SubprojectProvider.class);
250: return provider.getSubprojects();
251: }
252:
253: private FileObject getSourceFolder(FileObject source) {
254: return getSourceFolder(project, source);
255: }
256:
257: private static String[] sourceTypes = new String[] {
258: ProjectConstants.SOURCES_TYPE_XML,
259: ProjectConstants.SOURCES_TYPE_JAVA,
260: ProjectConstants.TYPE_DOC_ROOT,
261: ProjectConstants.TYPE_WEB_INF };
262:
263: private static FileObject getSourceFolder(Project project,
264: FileObject source) {
265: Sources sources = ProjectUtils.getSources(project);
266: assert sources != null;
267: ArrayList<SourceGroup> sourceGroups = new ArrayList<SourceGroup>();
268: for (String type : sourceTypes) {
269: SourceGroup[] groups = sources.getSourceGroups(type);
270: if (groups != null) {
271: sourceGroups.addAll(Arrays.asList(groups));
272: }
273: }
274:
275: assert sourceGroups.size() > 0;
276: for (SourceGroup sourceGroup : sourceGroups) {
277: if (FileUtil
278: .isParentOf(sourceGroup.getRootFolder(), source))
279: return sourceGroup.getRootFolder();
280: }
281:
282: FileObject metaInf = project.getProjectDirectory()
283: .getFileObject("src/conf"); //NOI18N
284: if (metaInf != null) {
285: if (FileUtil.isParentOf(metaInf, source)) {
286: return metaInf;
287: }
288: }
289: return null;
290: }
291:
292: private static String getRelativePath(FileObject source,
293: FileObject target) {
294: File sourceLocationFile = FileUtil.toFile(source);
295: File targetLocationFile = FileUtil.toFile(target);
296: String sourceLocation = sourceLocationFile.toURI().toString();
297: String targetLocation = targetLocationFile.toURI().toString();
298: StringTokenizer st1 = new StringTokenizer(sourceLocation, "/");
299: StringTokenizer st2 = new StringTokenizer(targetLocation, "/");
300: String relativeLoc = "";
301: while (st1.hasMoreTokens() && st2.hasMoreTokens()) {
302: relativeLoc = st2.nextToken();
303: if (!st1.nextToken().equals(relativeLoc)) {
304: break;
305: }
306: if (!st1.hasMoreTokens() || !st2.hasMoreTokens()) {
307: // seems like one of the file is parent directory of other file
308: if (st1.hasMoreElements()) {
309: // seems like target is parent of source
310: relativeLoc = "..";
311: st1.nextToken();
312: } else if (st2.hasMoreTokens()) {
313: // seems like source is parent of target
314: relativeLoc = st2.nextToken();
315: } else {
316: // both represent same file
317: relativeLoc = "";
318: }
319: }
320: }
321: while (st1.hasMoreTokens()) {
322: relativeLoc = "../".concat(relativeLoc);
323: st1.nextToken();
324: }
325: while (st2.hasMoreTokens()) {
326: relativeLoc = relativeLoc.concat("/").concat(
327: st2.nextToken());
328: }
329: return relativeLoc;
330: }
331:
332: private static String getUsableProjectName(Project project) {
333: return PropertyUtils.getUsablePropertyName(
334: ProjectUtils.getInformation(project).getName())
335: .replace('.', '_');
336: }
337:
338: public boolean removeCatalogEntry(URI uri) throws IOException {
339: CatalogWriteModel cwm = null;
340: try {
341: cwm = CatalogWriteModelFactory.getInstance()
342: .getCatalogWriteModelForProject(
343: project.getProjectDirectory());
344: } catch (CatalogModelException ex) {
345: return false;
346: }
347: boolean entryFound = false;
348: for (CatalogEntry ce : cwm.getCatalogEntries()) {
349: URI src = null;
350: try {
351: src = new URI(ce.getSource());
352: } catch (URISyntaxException ex) {
353: continue;
354: }
355: if (src.equals(uri)) {
356: entryFound = true;
357: break;
358: }
359: }
360: if (entryFound) {
361: cwm.removeURI(uri);
362: return true;
363: }
364: return false;
365: }
366:
367: }
|