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-2006 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.php.rt.providers.impl.local;
042:
043: import org.netbeans.modules.php.rt.providers.impl.actions.*;
044: import java.io.BufferedInputStream;
045: import java.io.File;
046: import java.io.FileInputStream;
047: import java.io.IOException;
048: import java.io.InputStream;
049: import java.io.OutputStream;
050: import java.util.logging.Level;
051: import java.util.logging.Logger;
052: import org.netbeans.api.progress.ProgressHandle;
053: import org.netbeans.api.progress.ProgressHandleFactory;
054: import org.netbeans.api.project.Project;
055: import org.netbeans.modules.php.rt.providers.impl.AbstractProvider;
056: import org.netbeans.modules.php.rt.utils.ActionsDialogs;
057: import org.netbeans.modules.php.rt.spi.providers.Host;
058: import org.netbeans.modules.php.rt.spi.providers.WebServerProvider;
059: import org.openide.filesystems.FileLock;
060: import org.openide.filesystems.FileObject;
061: import org.openide.filesystems.FileUtil;
062: import org.openide.util.Lookup;
063:
064: /**
065: * @author ads
066: *
067: */
068: class DownloadFilesCommandImpl extends DownloadFilesCommand {
069:
070: static final String LBL_DESTINATION_PATH_INIT_ERROR = "LBL_DestPathInitError"; // NOI18N
071:
072: static final String LBL_PATH_IS_SRC_ROOT = "LBL_DocumentPathIsSrcRoot"; // NOI18N
073:
074: private static Logger LOGGER = Logger
075: .getLogger(AbstractProvider.class.getName());
076:
077: public DownloadFilesCommandImpl(Project project,
078: WebServerProvider provider) {
079: super (project, provider);
080: }
081:
082: public DownloadFilesCommandImpl(Project project, boolean notify,
083: Lookup lookup, WebServerProvider provider) {
084: super (project, notify, provider);
085: }
086:
087: /* (non-Javadoc)
088: * @see java.lang.Runnable#run()
089: */
090: public void run() {
091: refresh();
092:
093: Host host = getHost();
094: if (!checkHost(host)) {
095: return;
096: }
097:
098: ProgressHandle progress = ProgressHandleFactory
099: .createHandle(getLabel()); // NOI18N
100: progress.start();
101:
102: boolean[] success = new boolean[] { true };
103: notifyTransferStarted();
104: try {
105: String context = getContext();
106: FileObject sourceRoot = getSourceRootObject();
107:
108: if (!checkDestinationFile(sourceRoot)) {
109: success[0] = false;
110: return;
111: }
112:
113: String path = getPath(host, context);
114:
115: File file = checkPath(path);
116: if (file == null) {
117: success[0] = false;
118: return;
119: } else {
120: if (isSrcRoot(file)) {
121: return;
122: }
123: }
124:
125: FileObject[] dstFileObjects = getFileObjects();
126: if (dstFileObjects == null) {
127: success[0] = false;
128: } else {
129: copyFiles(file, dstFileObjects, success);
130: }
131: } finally {
132: progress.finish();
133: notifyTransferFinished(success[0]);
134: }
135: }
136:
137: @Override
138: protected boolean checkHost(Host host) {
139: if (!super .checkHost(host)) {
140: return false;
141: }
142: return LocalActionUtils.checkHostFilePart(host, getProject(),
143: getLabel());
144: }
145:
146: private File checkPath(String path) {
147: if (path == null) {
148: notifyMsg(LBL_DESTINATION_PATH_INIT_ERROR);
149: return null;
150: }
151: File file = new File(path).getAbsoluteFile();
152: if (file.exists()) {
153: return file;
154: }
155: return null;
156: }
157:
158: private boolean isSrcRoot(File file) {
159: assert file != null;
160: FileObject[] sources = getSourceObjects(getProject());
161: for (FileObject source : sources) {
162: if (areEqual(source, file)) {
163: notifyMsg(LBL_PATH_IS_SRC_ROOT, file.getPath());
164: return true;
165: }
166: }
167: return false;
168: }
169:
170: private String getPath(Host host, String context) {
171: assert host instanceof LocalHostImpl;
172: LocalHostImpl impl = (LocalHostImpl) host;
173: String hostDocumentRoot = (String) impl
174: .getProperty(LocalHostImpl.DOCUMENT_PATH);
175:
176: if (hostDocumentRoot != null) {
177: if (hostDocumentRoot.endsWith(File.separator)) {
178: hostDocumentRoot = hostDocumentRoot.substring(0,
179: hostDocumentRoot.length() - 1);
180: }
181: String contextPath = context.replace('/',
182: File.separatorChar);
183: if (!contextPath.startsWith(File.separator)) {
184: contextPath = File.separator + contextPath;
185: }
186: return hostDocumentRoot + contextPath;
187: }
188: return null;
189: }
190:
191: private File getFromFile(File fromDir, FileObject dstFileObject) {
192: String from = getRelativeSrcPath(dstFileObject);
193:
194: File fromFile = new File(fromDir, from);
195: if (!fromFile.exists()) {
196: return null;
197: }
198: return fromFile;
199: }
200:
201: private File getToFile(FileObject fileObject) {
202: FileObject dstFileObject = fileObject;
203: if (fileObject.equals(getProject().getProjectDirectory())) {
204: dstFileObject = getSourceRootObject();
205: }
206: return FileUtil.toFile(dstFileObject);
207: }
208:
209: private void copyFiles(File fromDir, FileObject[] dstFileObjects,
210: boolean[] success) {
211: //FileObject sourceRoot = getSourceRootObject();
212:
213: for (FileObject dstFileObject : dstFileObjects) {
214:
215: File fromFile = getFromFile(fromDir, dstFileObject);
216: if (fromFile == null) {
217: continue;
218: }
219:
220: File toFile = getToFile(dstFileObject);
221: if (toFile == null) {
222: continue;
223: }
224:
225: if (fromFile.isDirectory()) {
226: copyFolder(success, fromFile, toFile);
227: } else {
228: try {
229: copyFile(fromFile, toFile);
230: } catch (IOException e) {
231: LOGGER.log(Level.WARNING, null, e);
232: success[0] = false;
233: }
234: }
235: }
236: }
237:
238: private boolean areEqual(FileObject fo, File f) {
239: try {
240: assert fo != null && f != null;
241: File foFile = FileUtil.toFile(fo);
242:
243: return foFile.getCanonicalFile().equals(
244: f.getCanonicalFile());
245: } catch (IOException ex) {
246: LOGGER.log(Level.WARNING, null, ex);
247: return false;
248: }
249:
250: }
251:
252: private void copyFilesRecursively(File[] from, File to,
253: boolean[] errors) {
254: for (File file : from) {
255: copyFilesRecursively(file, to, errors);
256: }
257: }
258:
259: private void copyFilesRecursively(File from, File to,
260: boolean[] errors) {
261: if (!from.isDirectory()) {
262: return;
263: }
264:
265: File[] children = from.listFiles();
266: for (File child : children) {
267: File dst = new File(to, child.getName());
268: if (skipRemoteFile(child) || skipLocalFile(dst)) {
269: rememberSkippedFile(child.getPath());
270: continue;
271: }
272: if (child.isDirectory()) {
273: copyFolder(errors, child, dst);
274: } else {
275: try {
276: if (dst.exists()) {
277: overwriteFile(child, dst);
278: } else {
279: copyFile(child, dst);
280: }
281: } catch (IOException e) {
282: LOGGER.log(Level.WARNING, null, e);
283: errors[0] = false;
284: }
285: }
286: }
287: }
288:
289: private boolean skipLocalFile(File file) {
290: return isNbProject(file);
291: }
292:
293: private boolean skipRemoteFile(File File) {
294: return false;
295: }
296:
297: private void copyFolder(boolean[] errors, File src, File dst) {
298: boolean success = dst.mkdirs();
299: if (!success && !dst.exists()) {
300: errors[0] = false;
301: } else {
302: copyFilesRecursively(src, dst, errors);
303: }
304: }
305:
306: private void overwriteFile(File from, File to) throws IOException {
307: boolean overwrite = false;
308: String fileFullName = to.getPath();
309: if (getOverwriteFiles() == null) {
310: overwrite = confirmOverwrite(fileFullName);
311: } else {
312: overwrite = getOverwriteFiles().booleanValue();
313: }
314:
315: if (overwrite) {
316: copyFile(from, to);
317: } else {
318: rememberNotOverwrittenFile(from.getPath());
319: }
320: }
321:
322: FileObject copyFile(File from, File to) throws IOException {
323: assert to != null;
324: assert from != null;
325:
326: File tmpTo = null;
327: try {
328: tmpTo = getNotExistingTmpFile(to);
329:
330: // copy as file with tmp name and then rename to real name
331: doCopy(from, tmpTo);
332: to.delete();
333:
334: tmpTo.renameTo(to);
335:
336: rememberCopiedFile(to.getPath());
337: refreshParent(to);
338: } finally {
339: if (tmpTo != null && tmpTo.exists()) {
340: tmpTo.delete();
341: }
342: }
343: return null;
344: }
345:
346: FileObject doCopy(File from, File to) throws IOException {
347: assert to != null;
348: assert from != null;
349:
350: // do not use the fiollowing code because File 'to' doesn't have method to
351: // get name without ext easily. FileUtil.copyFile needs name without ext.
352: //FileObject fromFileObject = FileUtil.toFileObject(FileUtil.normalizeFile(from));
353: //FileObject destFolder = FileUtil.toFileObject(to.getParentFile());
354: //if (fromFileObject != null && destFolder != null) {
355: // return FileUtil.copyFile(fromFileObject, destFolder, to.getName());
356: //}
357:
358: FileObject dest = FileUtil.createData(to);
359:
360: FileLock lock = null;
361: InputStream bufIn = null;
362: OutputStream bufOut = null;
363:
364: try {
365: lock = dest.lock();
366: bufIn = new BufferedInputStream(new FileInputStream(from));
367:
368: bufOut = dest.getOutputStream(lock);
369:
370: FileUtil.copy(bufIn, bufOut);
371: } finally {
372: if (bufIn != null) {
373: bufIn.close();
374: }
375:
376: if (bufOut != null) {
377: bufOut.close();
378: }
379:
380: if (lock != null) {
381: lock.releaseLock();
382: }
383: }
384: return dest;
385: }
386:
387: private Project myProject;
388: }
|