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: package org.netbeans.modules.apisupport.project.ui.wizard.librarydescriptor;
043:
044: import java.io.IOException;
045: import java.io.InputStream;
046: import java.io.OutputStream;
047: import java.net.URL;
048: import java.util.Collection;
049: import java.util.Collections;
050: import java.util.HashMap;
051: import java.util.Iterator;
052: import java.util.Map;
053: import java.util.zip.ZipEntry;
054: import java.util.zip.ZipOutputStream;
055: import org.netbeans.api.project.Project;
056: import org.netbeans.api.project.libraries.Library;
057: import org.netbeans.modules.apisupport.project.CreatedModifiedFiles;
058: import org.netbeans.modules.apisupport.project.CreatedModifiedFilesFactory;
059: import org.netbeans.modules.apisupport.project.ManifestManager;
060: import org.netbeans.modules.apisupport.project.NbModuleProject;
061: import org.openide.filesystems.FileLock;
062: import org.openide.filesystems.FileObject;
063: import org.openide.filesystems.FileUtil;
064: import org.openide.filesystems.URLMapper;
065:
066: /**
067: *
068: * @author Radek Matous
069: */
070: final class CreatedModifiedFilesProvider {
071:
072: private CreatedModifiedFilesProvider() {
073: }
074:
075: private static final String VOLUME_CLASS = "classpath";//NOI18N
076: private static final String VOLUME_SRC = "src";//NOI18N
077: private static final String VOLUME_JAVADOC = "javadoc";//NOI18N
078:
079: private static final String LIBRARY_LAYER_ENTRY = "org-netbeans-api-project-libraries/Libraries";//NOI18N
080:
081: static CreatedModifiedFiles createInstance(
082: NewLibraryDescriptor.DataModel data) {
083:
084: CreatedModifiedFiles retval = new CreatedModifiedFiles(data
085: .getProject());
086: addOperations(retval, data);
087:
088: return retval;
089: }
090:
091: private static void addOperations(CreatedModifiedFiles fileSupport,
092: NewLibraryDescriptor.DataModel data) {
093: FileObject template = CreatedModifiedFiles
094: .getTemplate("libdescriptemplate.xml");//NOI18N
095: Map<String, String> tokens = getTokens(fileSupport, data
096: .getProject(), data);
097: String layerEntry = getLibraryDescriptorEntryPath(data
098: .getLibraryName());
099:
100: fileSupport.add(fileSupport.createLayerEntry(layerEntry,
101: template, tokens, null, null));
102:
103: fileSupport.add(fileSupport.bundleKeyDefaultBundle(data
104: .getLibraryName(), data.getLibraryDisplayName()));
105: }
106:
107: private static String getPackagePlusBundle(Project project) {
108: NbModuleProject nbproj = project.getLookup().lookup(
109: NbModuleProject.class);
110: assert nbproj != null : "this template works only with default netbeans modules.";
111: ManifestManager mm = ManifestManager.getInstance(nbproj
112: .getManifest(), false);
113:
114: String bundle = mm.getLocalizingBundle().replace('/', '.');
115: if (bundle.endsWith(".properties")) { // NOI18N
116: bundle = bundle.substring(0, bundle.length() - 11);
117: }
118:
119: return bundle;
120: }
121:
122: static String getLibraryDescriptorEntryPath(String libraryName) {
123: StringBuffer sb = new StringBuffer();
124:
125: sb.append(LIBRARY_LAYER_ENTRY).append("/").append(libraryName)
126: .append(".xml");//NOI18N
127:
128: return sb.toString();//NOI18N
129: }
130:
131: private static String transformURL(final String cnb,
132: final String pathPrefix, final String archiveName) {
133: StringBuffer sb = new StringBuffer();
134:
135: sb.append("jar:nbinst://").append(cnb).append("/");//NOI18N
136: sb.append(pathPrefix).append(archiveName).append("!/");//NOI18N
137:
138: return sb.toString();
139: }
140:
141: private static Map<String, String> getTokens(
142: CreatedModifiedFiles fileSupport, Project project,
143: NewLibraryDescriptor.DataModel data) {
144: Map<String, String> retval = new HashMap<String, String>();
145: Library library = data.getLibrary();
146: retval.put("NAME", data.getLibraryName());//NOI18N
147: retval.put("BUNDLE", getPackagePlusBundle(project).replace('/',
148: '.'));//NOI18N
149:
150: Iterator<URL> it = library.getContent(VOLUME_CLASS).iterator();
151: retval.put("CLASSPATH", getTokenSubstitution(it, fileSupport,
152: data, "libs/"));//NOI18N
153:
154: it = library.getContent(VOLUME_SRC).iterator();
155: retval.put("SRC", getTokenSubstitution(it, fileSupport, data,
156: "sources/"));//NOI18N
157:
158: it = library.getContent(VOLUME_JAVADOC).iterator();
159: retval.put("JAVADOC", getTokenSubstitution(it, fileSupport,
160: data, "docs/"));//NOI18N
161:
162: return retval;
163: }
164:
165: private static String getTokenSubstitution(Iterator<URL> it,
166: CreatedModifiedFiles fileSupport,
167: NewLibraryDescriptor.DataModel data, String pathPrefix) {
168: StringBuffer sb = new StringBuffer();
169: while (it.hasNext()) {
170: URL originalURL = it.next();
171: String archiveName;
172: archiveName = addArchiveToCopy(fileSupport, data,
173: originalURL, "release/" + pathPrefix);//NOI18N
174: if (archiveName != null) {
175: String codeNameBase = data.getModuleInfo()
176: .getCodeNameBase();
177: String urlToString = transformURL(codeNameBase,
178: pathPrefix, archiveName);//NOI18N
179: sb.append("<resource>");//NOI18N
180: sb.append(urlToString);
181: if (it.hasNext()) {
182: sb.append("</resource>\n");//NOI18N
183: } else {
184: sb.append("</resource>");//NOI18N
185: }
186: }
187: }
188: return sb.toString();
189: }
190:
191: /** returns archive name or temporarily null cause there is no zip support for file protocol */
192: private static String addArchiveToCopy(
193: CreatedModifiedFiles fileSupport,
194: NewLibraryDescriptor.DataModel data, URL originalURL,
195: String pathPrefix) {
196: String retval = null;
197:
198: URL archivURL = FileUtil.getArchiveFile(originalURL);
199: if (archivURL != null && FileUtil.isArchiveFile(archivURL)) {
200: FileObject archiv = URLMapper.findFileObject(archivURL);
201: assert archiv != null;
202: retval = archiv.getNameExt();
203: StringBuffer sb = new StringBuffer();
204: sb.append(pathPrefix).append(retval);
205: fileSupport.add(fileSupport.createFile(sb.toString(),
206: archiv));
207: } else {
208: if ("file".equals(originalURL.getProtocol())) {//NOI18N
209: FileObject folderToZip;
210: folderToZip = URLMapper.findFileObject(originalURL);
211: if (folderToZip != null) {
212: retval = data.getLibraryName() + ".zip";//NOI18N
213: pathPrefix += retval;
214: fileSupport.add(new ZipAndCopyOperation(data
215: .getProject(), folderToZip, pathPrefix));
216: }
217: }
218: }
219: return retval;
220: }
221:
222: private static class ZipAndCopyOperation extends
223: CreatedModifiedFilesFactory.OperationBase {
224: private FileObject folderToZip;
225: private String relativePath;
226:
227: ZipAndCopyOperation(Project prj, FileObject folderToZip,
228: String relativePath) {
229: super (prj);
230: this .folderToZip = folderToZip;
231: this .relativePath = relativePath;
232: addCreatedOrModifiedPath(relativePath, false);
233: }
234:
235: public void run() throws IOException {
236: Collection<? extends FileObject> files = Collections
237: .list(folderToZip.getChildren(true));
238: if (files.isEmpty())
239: return;
240: FileObject prjDir = getProject().getProjectDirectory();
241: assert prjDir != null;
242:
243: FileObject zipedTarget = prjDir.getFileObject(relativePath);
244: if (zipedTarget == null) {
245: zipedTarget = FileUtil.createData(prjDir, relativePath);
246: }
247:
248: assert zipedTarget != null;
249: FileLock fLock = null;
250: OutputStream os = null;
251:
252: try {
253: fLock = zipedTarget.lock();
254: os = zipedTarget.getOutputStream(fLock);
255: createZipFile(os, folderToZip, files);
256: } finally {
257: if (os != null) {
258: os.close();
259: }
260:
261: if (fLock != null) {
262: fLock.releaseLock();
263: }
264: }
265: }
266:
267: private static void createZipFile(OutputStream target,
268: FileObject root, Collection<? extends FileObject> files)
269: throws IOException {
270: ZipOutputStream str = null;
271: try {
272: str = new ZipOutputStream(target);
273: for (FileObject fo : files) {
274: String relativePath = FileUtil.getRelativePath(
275: root, fo);
276: if (fo.isFolder()) {
277: if (fo.getChildren().length > 0) {
278: continue;
279: } else if (!relativePath.endsWith("/")) {
280: relativePath += "/";
281: }
282: }
283: ZipEntry entry = new ZipEntry(relativePath);
284: str.putNextEntry(entry);
285: if (fo.isData()) {
286: InputStream in = null;
287: try {
288: in = fo.getInputStream();
289: FileUtil.copy(in, str);
290: } finally {
291: if (in != null) {
292: in.close();
293: }
294: }
295: }
296: str.closeEntry();
297: }
298: } finally {
299: if (str != null) {
300: str.close();
301: }
302: }
303: }
304: }
305: }
|