2
Copyright 2008-2010 Gephi
3
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
4
Website : http://www.gephi.org
6
This file is part of Gephi.
8
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
10
Copyright 2011 Gephi Consortium. All rights reserved.
12
The contents of this file are subject to the terms of either the GNU
13
General Public License Version 3 only ("GPL") or the Common
14
Development and Distribution License("CDDL") (collectively, the
15
"License"). You may not use this file except in compliance with the
16
License. You can obtain a copy of the License at
17
http://gephi.org/about/legal/license-notice/
18
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
19
specific language governing permissions and limitations under the
20
License. When distributing the software, include this License Header
21
Notice in each file and include the License files at
22
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
23
License Header, with the fields enclosed by brackets [] replaced by
24
your own identifying information:
25
"Portions Copyrighted [year] [name of copyright owner]"
27
If you wish your version of this file to be governed by only the CDDL
28
or only the GPL Version 3, indicate your decision by adding
29
"[Contributor] elects to include this software in this distribution
30
under the [CDDL or GPL Version 3] license." If you do not indicate a
31
single choice of license, a recipient has the option to distribute
32
your version of this file under either the CDDL, the GPL Version 3 or
33
to extend the choice of license to its licensees as provided above.
34
However, if you add GPL Version 3 code and therefore, elected the GPL
35
Version 3 license, then the option applies only if the new code is
36
made subject to such option by the copyright holder.
40
Portions Copyrighted 2011 Gephi Consortium.
42
package org.gephi.ui.upgrader;
44
import java.io.BufferedReader;
46
import java.io.FileInputStream;
47
import java.io.FileOutputStream;
48
import java.io.IOException;
49
import java.io.InputStream;
50
import java.io.InputStreamReader;
51
import java.io.OutputStream;
52
import java.io.Reader;
53
import java.util.HashSet;
55
import org.openide.filesystems.FileUtil;
56
import org.openide.util.EditableProperties;
62
public class CopyFiles {
64
private File sourceRoot;
65
private File targetRoot;
66
private EditableProperties currentProperties;
67
private Set<String> includePatterns = new HashSet<String>();
68
private Set<String> excludePatterns = new HashSet<String>();
70
private CopyFiles(File source, File target) {
71
this.sourceRoot = source;
72
this.targetRoot = target;
75
InputStream is = CopyFiles.class.getResourceAsStream("/org/gephi/ui/upgrader/gephi.import");
76
Reader reader = new InputStreamReader(is, "utf-8"); // NOI18N
79
} catch (IOException ex) {
83
public static void copyDeep(File source, File target) throws IOException {
84
CopyFiles copyFiles = new CopyFiles(source, target);
85
System.out.println("Copying from: " + copyFiles.sourceRoot + "\nto: " + copyFiles.targetRoot); //NOI18N
86
copyFiles.copyFolder(copyFiles.sourceRoot);
89
private void copyFolder(File sourceFolder) throws IOException {
90
File[] srcChildren = sourceFolder.listFiles();
91
if (srcChildren == null) {
92
System.err.println(sourceFolder + " is not a directory or is invalid."); //NOI18N
95
for (File child : srcChildren) {
96
if (child.isDirectory()) {
104
/** Copy given file to target root dir if matches include/exclude patterns.
105
* If properties pattern is applicable, it copies only matching keys.
106
* @param sourceFile source file
107
* @throws java.io.IOException if copying fails
109
private void copyFile(File sourceFile) throws IOException {
110
String relativePath = getRelativePath(sourceRoot, sourceFile);
111
boolean includeFile = false;
112
Set<String> includeKeys = new HashSet<String>();
113
Set<String> excludeKeys = new HashSet<String>();
114
for (String pattern : includePatterns) {
115
if (pattern.contains("#")) { //NOI18N
116
includeKeys.addAll(matchingKeys(relativePath, pattern));
118
if (relativePath.matches(pattern)) {
120
includeKeys.clear(); // include entire file
125
if (includeFile || !includeKeys.isEmpty()) {
127
for (String pattern : excludePatterns) {
128
if (pattern.contains("#")) { //NOI18N
129
excludeKeys.addAll(matchingKeys(relativePath, pattern));
131
if (relativePath.matches(pattern)) {
133
includeKeys.clear(); // exclude entire file
139
// System.out.println(String.format("%s, includeFile=%s, includeKeys=%s, excludeKeys=%s", new Object[]{relativePath, includeFile, includeKeys, excludeKeys})); //NOI18N
140
if (!includeFile && includeKeys.isEmpty()) {
145
File targetFile = new File(targetRoot, relativePath);
146
// System.out.println(String.format("Path: %s", relativePath)); //NOI18N
147
if (includeKeys.isEmpty() && excludeKeys.isEmpty()) {
149
copyFile(sourceFile, targetFile);
151
if (!includeKeys.isEmpty()) {
152
currentProperties.keySet().retainAll(includeKeys);
154
currentProperties.keySet().removeAll(excludeKeys);
155
// copy just selected keys
156
// System.out.println(String.format(" Only keys: %s", currentProperties.keySet()));
157
OutputStream out = null;
159
ensureParent(targetFile);
160
out = new FileOutputStream(targetFile);
161
currentProperties.store(out);
170
/** Returns slash separated path relative to given root. */
171
private static String getRelativePath(File root, File file) {
172
String result = file.getAbsolutePath().substring(root.getAbsolutePath().length());
173
result = result.replace('\\', '/'); //NOI18N
174
if (result.startsWith("/") && !result.startsWith("//")) { //NOI18N
175
result = result.substring(1);
180
/** Copy source file to target file. It creates necessary sub folders.
181
* @param sourceFile source file
182
* @param targetFile target file
183
* @throws java.io.IOException if copying fails
185
private static void copyFile(File sourceFile, File targetFile) throws IOException {
186
ensureParent(targetFile);
187
InputStream ins = null;
188
OutputStream out = null;
190
ins = new FileInputStream(sourceFile);
191
out = new FileOutputStream(targetFile);
192
FileUtil.copy(ins, out);
203
/** Creates parent of given file, if doesn't exist. */
204
private static void ensureParent(File file) throws IOException {
205
final File parent = file.getParentFile();
206
if (parent != null && !parent.exists()) {
207
if (!parent.mkdirs()) {
208
throw new IOException("Cannot create folder: " + parent.getAbsolutePath()); //NOI18N
213
/** Returns set of keys matching given pattern.
214
* @param relativePath path relative to sourceRoot
215
* @param propertiesPattern pattern like file.properties#keyPattern
216
* @return set of matching keys, never null
217
* @throws IOException if properties cannot be loaded
219
private Set<String> matchingKeys(String relativePath, String propertiesPattern) throws IOException {
220
Set<String> matchingKeys = new HashSet<String>();
221
String[] patterns = propertiesPattern.split("#", 2);
222
String filePattern = patterns[0];
223
String keyPattern = patterns[1];
224
if (relativePath.matches(filePattern)) {
225
if (currentProperties == null) {
226
currentProperties = getProperties(relativePath);
228
for (String key : currentProperties.keySet()) {
229
if (key.matches(keyPattern)) {
230
matchingKeys.add(key);
237
/** Returns properties from relative path.
238
* @param relativePath relative path
239
* @return properties from relative path.
240
* @throws IOException if cannot open stream
242
private EditableProperties getProperties(String relativePath) throws IOException {
243
EditableProperties properties = new EditableProperties(false);
244
InputStream in = null;
246
in = new FileInputStream(new File(sourceRoot, relativePath));
256
/** Reads the include/exclude set from a given reader.
259
private void readPatterns(Reader r) throws IOException {
260
BufferedReader buf = new BufferedReader(r);
262
String line = buf.readLine();
267
if (line.length() == 0 || line.startsWith("#")) { //NOI18N
270
if (line.startsWith("include ")) { //NOI18N
271
line = line.substring(8);
272
if (line.length() > 0) {
273
includePatterns.addAll(parsePattern(line));
275
} else if (line.startsWith("exclude ")) { //NOI18N
276
line = line.substring(8);
277
if (line.length() > 0) {
278
excludePatterns.addAll(parsePattern(line));
281
throw new java.io.IOException("Wrong line: " + line); //NOI18N
294
/** Parses given compound string pattern into set of single patterns.
295
* @param pattern compound pattern in form filePattern1#keyPattern1#|filePattern2#keyPattern2#|filePattern3
296
* @return set of single patterns containing just one # (e.g. [filePattern1#keyPattern1, filePattern2#keyPattern2, filePattern3])
298
private static Set<String> parsePattern(String pattern) {
299
Set<String> patterns = new HashSet<String>();
300
if (pattern.contains("#")) { //NOI18N
301
StringBuilder partPattern = new StringBuilder();
302
ParserState state = ParserState.START;
304
for (int i = 0; i < pattern.length(); i++) {
305
char c = pattern.charAt(i);
309
state = ParserState.IN_KEY_PATTERN;
310
partPattern.append(c);
311
} else if (c == '(') {
312
state = ParserState.IN_BLOCK;
314
partPattern.append(c);
315
} else if (c == '|') {
316
patterns.add(partPattern.toString());
317
partPattern = new StringBuilder();
319
partPattern.append(c);
324
state = ParserState.AFTER_KEY_PATTERN;
326
partPattern.append(c);
329
case AFTER_KEY_PATTERN:
331
state = ParserState.START;
332
patterns.add(partPattern.toString());
333
partPattern = new StringBuilder();
335
assert false : "Wrong OptionsExport pattern " + pattern + ". Only format like filePattern1#keyPattern#|filePattern2 is supported."; //NOI18N
339
partPattern.append(c);
342
if (blockLevel == 0) {
343
state = ParserState.START;
349
patterns.add(partPattern.toString());
351
patterns.add(pattern);